1 4 5 9 10 package org.openlaszlo.remote.soap; 11 12 import java.util.*; 13 import java.io.*; 14 import javax.xml.rpc.*; 15 import javax.xml.parsers.*; 16 import javax.xml.namespace.*; 17 import org.w3c.dom.*; 18 import org.xml.sax.*; 19 import org.apache.axis.Constants; 20 21 import org.apache.log4j.Logger; 22 23 import org.apache.axis.utils.*; 24 25 26 public class SchemaParser 27 { 28 public static Logger mLogger = Logger.getLogger(SchemaParser.class); 29 30 static final int ARRAY = 0; 31 static final int REGULAR_OBJECT = 1; 32 static final int SEQUENCED_OBJECT = 2; 33 34 37 38 Map mBaseForwardTypeMap; 42 Map mArrayForwardTypeMap; 43 44 Map mComplexTypeMap; 45 46 String mNamespaceURI_SOAP_ENC; 48 String mNamespaceURI_SCHEMA_XSD; 49 String mNamespaceURI_WSDL; 50 String mTargetNamespaceURI; 51 52 QName mSOAPEncodingArray; 53 QName mSOAPEncodingArrayType; 54 55 Element mSchema; 56 57 61 public SchemaParser(WSDLParser wp, Element schema) { 62 63 mNamespaceURI_SCHEMA_XSD = wp.mNamespaceURI_SCHEMA_XSD; 64 mNamespaceURI_SOAP_ENC = wp.mNamespaceURI_SOAP_ENC; 65 mNamespaceURI_WSDL = wp.mNamespaceURI_WSDL; 66 67 mSOAPEncodingArray = new QName(mNamespaceURI_SOAP_ENC, "Array"); 68 mSOAPEncodingArrayType = new QName(mNamespaceURI_SOAP_ENC, "arrayType"); 69 70 mTargetNamespaceURI = schema.getAttribute("targetNamespace"); 72 73 mBaseForwardTypeMap = new HashMap(); 74 mArrayForwardTypeMap = new HashMap(); 75 76 mSchema = schema; 77 78 if (mLogger.isDebugEnabled()) { 79 mLogger.debug("mNamespaceURI_SCHEMA_XSD: " + mNamespaceURI_SCHEMA_XSD); 80 mLogger.debug("mNamespaceURI_SOAP_ENC: " + mNamespaceURI_SOAP_ENC); 81 mLogger.debug("mNamespaceURI_WSDL_SOAP: " + mNamespaceURI_WSDL); 82 mLogger.debug("mSOAPEncodingArray: " + mSOAPEncodingArray); 83 mLogger.debug("mSOAPEncodingArrayType: " + mSOAPEncodingArrayType); 84 mLogger.debug("mTargetNamespaceURI: " + mTargetNamespaceURI); 85 } 86 } 87 88 91 public void parse(Map complexTypeMap) { 92 93 mComplexTypeMap = complexTypeMap; 95 96 NodeList list = mSchema.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "complexType"); 98 99 for (int i=0; i < list.getLength(); i++) { 100 try { 101 ComplexType so = getComplexType((Element)list.item(i)); 102 if (so != null) { 103 fixBaseForwardRefs(so); 104 fixArrayForwardRefs(so); 105 complexTypeMap.put(so.getName(), so); 106 } else { 107 mLogger.warn("skipping: " + list.item(i)); 108 } 109 } catch (Exception e) { 110 mLogger.error("skipping complexType: " + e.getMessage(), e); 111 } 112 } 113 114 if (mBaseForwardTypeMap.size() != 0) { 115 mLogger.warn("The following base classes were not defined:"); 116 Iterator iter = mBaseForwardTypeMap.keySet().iterator(); 117 while (iter.hasNext()) { 118 QName baseQName = (QName)iter.next(); 119 mLogger.warn(" " + baseQName); 120 } 121 } 122 } 123 124 128 void fixBaseForwardRefs(ComplexType baseType) { 129 QName baseQName = baseType.getName(); 130 Vector list = (Vector)mBaseForwardTypeMap.get(baseQName); 131 if (list == null) return; 132 for (int i=0; i < list.size(); i++) { 133 ComplexType ct = (ComplexType)list.get(i); 134 ct.setBase(baseType); 135 } 136 mBaseForwardTypeMap.remove(baseQName); 137 } 138 139 143 void fixArrayForwardRefs(ComplexType arrayItemType) { 144 QName arrayQName = arrayItemType.getName(); 145 Vector list = (Vector)mArrayForwardTypeMap.get(arrayQName); 146 if (list == null) return; 147 for (int i=0; i < list.size(); i++) { 148 ComplexType ct = (ComplexType)list.get(i); 149 ct.setArrayItemType(arrayItemType); 150 } 151 mArrayForwardTypeMap.remove(arrayQName); 152 } 153 154 160 void setBaseType(QName baseQName, ComplexType ct) { 161 ComplexType baseType = (ComplexType)mComplexTypeMap.get(baseQName); 162 if (baseType == null) { 163 if (Constants.isSOAP_ENC(baseQName.getNamespaceURI()) ) { 165 baseType = new ComplexType(baseQName); 166 mComplexTypeMap.put(baseQName, baseType); 167 ct.setBase(baseType); 168 } else { 169 Vector list = (Vector)mBaseForwardTypeMap.get(baseQName); 170 if (list == null) { 171 list = new Vector(); 172 mBaseForwardTypeMap.put(baseQName, list); 173 } 174 list.add(ct); 175 } 176 } else { 177 ct.setBase(baseType); 178 } 179 } 180 181 187 void setArrayItemType(QName arrayQName, ComplexType ct) { 188 ComplexType arrayItemType = (ComplexType)mComplexTypeMap.get(arrayQName); 189 if (arrayItemType == null) { 190 if (Constants.isSchemaXSD(arrayQName.getNamespaceURI()) ) { 192 arrayItemType = new ComplexType(arrayQName); 193 mComplexTypeMap.put(arrayQName, arrayItemType); 194 ct.setArrayItemType(arrayItemType); 195 } else { 196 Vector list = (Vector)mArrayForwardTypeMap.get(arrayQName); 198 if (list == null) { 199 list = new Vector(); 200 mArrayForwardTypeMap.put(arrayQName, list); 201 } 202 list.add(ct); 203 } 204 205 } else { 206 ct.setArrayItemType(arrayItemType); 207 } 208 } 209 210 ComplexType getComplexType(Element ct) throws Exception { 211 String name = ct.getAttribute("name"); 212 213 NodeList list; 214 list = ct.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "complexContent"); 215 if (foundOne(list)) { 216 return checkComplexContent(name, (Element)list.item(0)); 218 } 219 220 list = ct.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "all"); 221 if (foundOne(list)) { 222 return checkAllOrSequence(name, (Element)list.item(0)); 224 } 225 226 list = ct.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "sequence"); 227 if (foundOne(list)) { 228 return checkAllOrSequence(name, (Element)list.item(0)); 230 } 231 232 mLogger.warn("no <complexContent>, <all>, or <sequence> nodes found under <complexType>"); 233 return null; 234 } 235 236 237 241 ComplexType checkComplexContent(String name, Element cc) throws Exception { 242 if (mLogger.isDebugEnabled()) { 243 mLogger.debug("checkComplexContent: " + name + ", " + cc); 244 } 245 246 NodeList list; 247 list = cc.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "restriction"); 248 if (foundOne(list)) { 249 return checkRestriction(name, (Element)list.item(0)); 250 } 251 252 list = cc.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "extension"); 253 if (foundOne(list)) { 254 return checkExtension(name, (Element)list.item(0)); 255 } 256 257 mLogger.warn("No <restriction> or <extension> tags were found inside of <complexContent>"); 259 return null; 260 } 261 262 265 ComplexType checkExtension(String name, Element extension) throws Exception { 266 NodeList list; 267 ComplexType ct = null; 268 list = extension.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "all"); 269 if (foundOne(list)) { 270 ct = checkAllOrSequence(name, (Element)list.item(0)); 272 } 273 274 list = extension.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "sequence"); 275 if (foundOne(list)) { 276 ct = checkAllOrSequence(name, (Element)list.item(0)); 278 } 279 280 if (ct == null) { 281 mLogger.warn("no <all> or <sequence> nodes found under <extension>"); 282 return null; 283 } 284 285 String base = extension.getAttribute("base"); 286 if (base == null || base.equals("")) { 287 throw new Exception ("no base attribute found in <extension>"); 288 } 289 290 QName baseQName = XMLUtils.getQNameFromString(base, extension); 291 setBaseType(baseQName, ct); 292 return ct; 293 } 294 295 298 ComplexType checkRestriction(String name, Element restriction) throws Exception { 299 String base = restriction.getAttribute("base"); 300 if (base == null || base.equals("")) { 301 throw new Exception ("no base attribute found in <restriction>"); 302 } 303 304 QName baseQName = XMLUtils.getQNameFromString(base, restriction); 305 if (! mSOAPEncodingArray.equals(baseQName)) { 306 throw new Exception ("only arrays are supported in <restriction>, instead found " 307 + baseQName); 308 } 309 310 NodeList list = restriction.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "attribute"); 313 if (! foundOne(list)) { 314 throw new Exception ("expecting only one attribute inside <restriction base=\"soapenc:Array\">"); 318 } 319 320 Element attributeElement = (Element)list.item(0); 321 String ref = attributeElement.getAttribute("ref"); 322 323 String arrayItemType = attributeElement.getAttributeNS(mNamespaceURI_WSDL, "arrayType"); 324 325 if (ref.equals("")) { 326 throw new Exception ("empty ref attribute in <attribute> inside of <restriction> for <complexType> named " + name); 327 } 328 329 if (arrayItemType.equals("")) { 330 throw new Exception ("empty ref attribute in <attribute> inside of <restriction> for <complexType> named " + name); 331 } 332 333 QName refQName = XMLUtils.getQNameFromString(ref, attributeElement); 334 if (! mSOAPEncodingArrayType.equals(refQName)) { 335 throw new Exception ("ref attribute in <attribute> inside of <restriction> does not refer to SOAP-ENC array"); 336 } 337 338 String type = removeBrackets(arrayItemType); 339 QName typeQName = XMLUtils.getQNameFromString(type, attributeElement); 340 341 ComplexType ct = new ComplexType(new QName(mTargetNamespaceURI, name), true); 343 setArrayItemType(typeQName, ct); 344 setBaseType(baseQName, ct); 345 return ct; 346 } 347 348 349 352 String removeBrackets(String arrayItemType) { 353 int index = arrayItemType.indexOf('['); 354 if (index == -1) { 355 return arrayItemType; 356 } 357 return arrayItemType.substring(0, index); 358 } 359 360 361 365 ComplexType checkAllOrSequence(String name, Element node) throws Exception { 366 if (mLogger.isDebugEnabled()) { 367 mLogger.debug("checkAllOrSequence: " + name + ", " + node); 368 } 369 370 String tag = node.getTagName(); 371 Map members = new HashMap(); 372 NodeList list = node.getElementsByTagNameNS(mNamespaceURI_SCHEMA_XSD, "element"); 373 for (int i=0; i < list.getLength(); i++) { 374 Element element = (Element)list.item(i); 375 String elRef = element.getAttribute("ref"); 376 String elName = element.getAttribute("name"); 377 String elType = element.getAttribute("type"); 378 if (! elRef.equals("")) { 379 mLogger.warn("!!! skipping element #" + (i+1) + " !!! " + 380 "references ignored"); 381 continue; 382 } else { 383 if (elName.equals("")) { 384 mLogger.warn("!!! skipping element #" + (i+1) + " !!! " + 385 "name attribute missing in inside <" + tag + 386 ">: " + node); 387 continue; 388 } 389 if (elType.equals("")) { 390 mLogger.warn("!!! skipping element #" + (i+1) + " !!! " + 391 "type attribute missing inside <" + tag + 392 ">: " + node + "(anonymous types not supported)"); 393 continue; 394 } 395 } 396 QName elTypeQName = XMLUtils.getQNameFromString(elType, element); 397 members.put(elName, elTypeQName); 398 } 399 400 return new ComplexType(new QName(mTargetNamespaceURI, name), members); 402 } 403 404 405 408 boolean foundOne(NodeList list) { 409 return list.getLength() == 1; 410 } 411 } 412 | Popular Tags |