00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 package org.apache.xmlrpc.parser;
00020
00021 import java.util.HashMap;
00022 import java.util.Map;
00023
00024 import javax.xml.namespace.QName;
00025
00026 import org.apache.ws.commons.util.NamespaceContextImpl;
00027 import org.apache.xmlrpc.common.TypeFactory;
00028 import org.apache.xmlrpc.common.XmlRpcStreamConfig;
00029 import org.apache.xmlrpc.serializer.MapSerializer;
00030 import org.apache.xmlrpc.serializer.TypeSerializerImpl;
00031 import org.xml.sax.Attributes;
00032 import org.xml.sax.SAXException;
00033 import org.xml.sax.SAXParseException;
00034
00035
00039 public class MapParser extends RecursiveTypeParserImpl {
00040 private int level = 0;
00041 private StringBuffer nameBuffer = new StringBuffer();
00042 private Object nameObject;
00043 private Map map;
00044 private boolean inName, inValue, doneValue;
00045
00051 public MapParser(XmlRpcStreamConfig pConfig,
00052 NamespaceContextImpl pContext,
00053 TypeFactory pFactory) {
00054 super(pConfig, pContext, pFactory);
00055 }
00056
00057 protected void addResult(Object pResult) throws SAXException {
00058 if (inName) {
00059 nameObject = pResult;
00060 } else {
00061 if (nameObject == null) {
00062 throw new SAXParseException("Invalid state: Expected name",
00063 getDocumentLocator());
00064 } else {
00065 if (map.containsKey(nameObject)) {
00066 throw new SAXParseException("Duplicate name: " + nameObject,
00067 getDocumentLocator());
00068 } else {
00069 map.put(nameObject, pResult);
00070 }
00071 }
00072 }
00073 }
00074
00075 public void startDocument() throws SAXException {
00076 super.startDocument();
00077 level = 0;
00078 map = new HashMap();
00079 inValue = inName = false;
00080 }
00081
00082 public void characters(char[] pChars, int pOffset, int pLength) throws SAXException {
00083 if (inName && !inValue) {
00084 nameBuffer.append(pChars, pOffset, pLength);
00085 } else {
00086 super.characters(pChars, pOffset, pLength);
00087 }
00088 }
00089
00090 public void ignorableWhitespace(char[] pChars, int pOffset, int pLength) throws SAXException {
00091 if (inName) {
00092 characters(pChars, pOffset, pLength);
00093 } else {
00094 super.ignorableWhitespace(pChars, pOffset, pLength);
00095 }
00096 }
00097
00098 public void startElement(String pURI, String pLocalName, String pQName,
00099 Attributes pAttrs) throws SAXException {
00100 switch (level++) {
00101 case 0:
00102 if (!"".equals(pURI) || !MapSerializer.STRUCT_TAG.equals(pLocalName)) {
00103 throw new SAXParseException("Expected " + MapSerializer.STRUCT_TAG + ", got "
00104 + new QName(pURI, pLocalName),
00105 getDocumentLocator());
00106 }
00107 break;
00108 case 1:
00109 if (!"".equals(pURI) || !MapSerializer.MEMBER_TAG.equals(pLocalName)) {
00110 throw new SAXParseException("Expected " + MapSerializer.MEMBER_TAG + ", got "
00111 + new QName(pURI, pLocalName),
00112 getDocumentLocator());
00113 }
00114 doneValue = inName = inValue = false;
00115 nameObject = null;
00116 nameBuffer.setLength(0);
00117 break;
00118 case 2:
00119 if (doneValue) {
00120 throw new SAXParseException("Expected /" + MapSerializer.MEMBER_TAG
00121 + ", got " + new QName(pURI, pLocalName),
00122 getDocumentLocator());
00123 }
00124 if ("".equals(pURI) && MapSerializer.NAME_TAG.equals(pLocalName)) {
00125 if (nameObject == null) {
00126 inName = true;
00127 } else {
00128 throw new SAXParseException("Expected " + TypeSerializerImpl.VALUE_TAG
00129 + ", got " + new QName(pURI, pLocalName),
00130 getDocumentLocator());
00131 }
00132 } else if ("".equals(pURI) && TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
00133 if (nameObject == null) {
00134 throw new SAXParseException("Expected " + MapSerializer.NAME_TAG
00135 + ", got " + new QName(pURI, pLocalName),
00136 getDocumentLocator());
00137 } else {
00138 inValue = true;
00139 startValueTag();
00140 }
00141
00142 }
00143 break;
00144 case 3:
00145 if (inName && "".equals(pURI) && TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
00146 if (cfg.isEnabledForExtensions()) {
00147 inValue = true;
00148 startValueTag();
00149 } else {
00150 throw new SAXParseException("Expected /" + MapSerializer.NAME_TAG
00151 + ", got " + new QName(pURI, pLocalName),
00152 getDocumentLocator());
00153 }
00154 } else {
00155 super.startElement(pURI, pLocalName, pQName, pAttrs);
00156 }
00157 break;
00158 default:
00159 super.startElement(pURI, pLocalName, pQName, pAttrs);
00160 break;
00161 }
00162 }
00163
00164 public void endElement(String pURI, String pLocalName, String pQName) throws SAXException {
00165 switch (--level) {
00166 case 0:
00167 setResult(map);
00168 break;
00169 case 1:
00170 break;
00171 case 2:
00172 if (inName) {
00173 inName = false;
00174 if (nameObject == null) {
00175 nameObject = nameBuffer.toString();
00176 } else {
00177 for (int i = 0; i < nameBuffer.length(); i++) {
00178 if (!Character.isWhitespace(nameBuffer.charAt(i))) {
00179 throw new SAXParseException("Unexpected non-whitespace character in member name",
00180 getDocumentLocator());
00181 }
00182 }
00183 }
00184 } else if (inValue) {
00185 endValueTag();
00186 doneValue = true;
00187 }
00188 break;
00189 case 3:
00190 if (inName && inValue && "".equals(pURI) && TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
00191 endValueTag();
00192 } else {
00193 super.endElement(pURI, pLocalName, pQName);
00194 }
00195 break;
00196 default:
00197 super.endElement(pURI, pLocalName, pQName);
00198 }
00199 }
00200 }