View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.webservices.builder;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.net.URI;
23  import java.net.URISyntaxException;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Stack;
31  import java.util.jar.JarFile;
32  import java.util.zip.ZipEntry;
33  import javax.wsdl.Definition;
34  import javax.wsdl.Import;
35  import javax.wsdl.Service;
36  import javax.wsdl.Types;
37  import javax.wsdl.WSDLException;
38  import javax.wsdl.extensions.ExtensibilityElement;
39  import javax.wsdl.extensions.ExtensionRegistry;
40  import javax.wsdl.extensions.UnknownExtensibilityElement;
41  import javax.wsdl.extensions.schema.Schema;
42  import javax.wsdl.factory.WSDLFactory;
43  import javax.wsdl.xml.WSDLLocator;
44  import javax.wsdl.xml.WSDLReader;
45  import javax.xml.namespace.QName;
46  
47  import com.ibm.wsdl.extensions.PopulatedExtensionRegistry;
48  import com.ibm.wsdl.extensions.schema.SchemaConstants;
49  import org.apache.commons.logging.Log;
50  import org.apache.commons.logging.LogFactory;
51  import org.apache.geronimo.webservices.WebServiceContainer;
52  import org.apache.geronimo.common.DeploymentException;
53  import org.apache.geronimo.xbeans.wsdl.DefinitionsDocument;
54  import org.apache.geronimo.xbeans.wsdl.TDefinitions;
55  import org.apache.geronimo.xbeans.wsdl.TPort;
56  import org.apache.geronimo.xbeans.wsdl.TService;
57  import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
58  import org.apache.xmlbeans.SchemaField;
59  import org.apache.xmlbeans.SchemaGlobalElement;
60  import org.apache.xmlbeans.SchemaParticle;
61  import org.apache.xmlbeans.SchemaType;
62  import org.apache.xmlbeans.SchemaTypeSystem;
63  import org.apache.xmlbeans.XmlBeans;
64  import org.apache.xmlbeans.XmlCursor;
65  import org.apache.xmlbeans.XmlError;
66  import org.apache.xmlbeans.XmlException;
67  import org.apache.xmlbeans.XmlObject;
68  import org.apache.xmlbeans.XmlOptions;
69  import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
70  import org.w3c.dom.Element;
71  import org.xml.sax.EntityResolver;
72  import org.xml.sax.InputSource;
73  import org.xml.sax.SAXException;
74  
75  /**
76   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
77   */
78  public class SchemaInfoBuilder {
79      private static final Log log = LogFactory.getLog(SchemaInfoBuilder.class);
80      private static final SchemaTypeSystem basicTypeSystem;
81  //  private static final String[] errorNames = {"Error", "Warning", "Info"};
82      private static final String SOAP_NS = "http://schemas.xmlsoap.org/wsdl/soap/";
83      private static final QName ADDRESS_QNAME = new QName(SOAP_NS, "address");
84      private static final QName LOCATION_QNAME = new QName("", "location");
85  
86      static {
87          InputStream is = WSDescriptorParser.class.getClassLoader().getResourceAsStream("META-INF/schema/soap_encoding_1_1.xsd");
88          if (is == null) {
89              throw new RuntimeException("Could not locate soap encoding schema");
90          }
91          ArrayList errors = new ArrayList();
92          XmlOptions xmlOptions = XmlBeansUtil.createXmlOptions(errors);
93          try {
94              SchemaDocument parsed = SchemaDocument.Factory.parse(is, xmlOptions);
95              if (errors.size() != 0) {
96                  throw new XmlException(errors.toArray().toString());
97              }
98  
99              basicTypeSystem = XmlBeans.compileXsd(new XmlObject[]{parsed}, XmlBeans.getBuiltinTypeSystem(), xmlOptions);
100             if (errors.size() > 0) {
101                 throw new RuntimeException("Could not compile schema type system: errors: " + errors);
102             }
103         } catch (XmlException e) {
104             throw new RuntimeException("Could not compile schema type system", e);
105         } catch (IOException e) {
106             throw new RuntimeException("Could not compile schema type system", e);
107         } finally {
108             try {
109                 is.close();
110             } catch (IOException ignore) {
111                 // ignore
112             }
113         }
114     }
115 
116     private final JarFile moduleFile;
117     private final Definition definition;
118     private final Stack uris = new Stack();
119     private final Map wsdlMap = new HashMap();
120     private final Map schemaTypeKeyToSchemaTypeMap;
121     private final Map complexTypeMap;
122     private final Map elementMap;
123     private final Map simpleTypeMap;
124     private final Map portMap;
125 
126 
127     public SchemaInfoBuilder(JarFile moduleFile, URI wsdlUri) throws DeploymentException {
128         this(moduleFile, wsdlUri, null, null);
129     }
130 
131     public SchemaInfoBuilder(JarFile moduleFile, Definition definition) throws DeploymentException {
132         this(moduleFile, null, definition, null);
133     }
134 
135     SchemaInfoBuilder(JarFile moduleFile, URI uri, SchemaTypeSystem schemaTypeSystem) throws DeploymentException {
136         this(moduleFile, uri, null, schemaTypeSystem);
137     }
138 
139     SchemaInfoBuilder(JarFile moduleFile, URI uri, Definition definition, SchemaTypeSystem schemaTypeSystem) throws DeploymentException {
140         this.moduleFile = moduleFile;
141         if (uri != null) {
142             uris.push(uri);
143             if (definition == null && schemaTypeSystem == null) {
144                 definition = readWsdl(moduleFile, uri);
145             }
146         } else if (definition != null) {
147             try {
148                 uri = new URI(definition.getDocumentBaseURI());
149                 uris.push(uri);
150             } catch (URISyntaxException e) {
151                 throw new DeploymentException("Could not locate definition", e);
152             }
153         } else {
154             throw new DeploymentException("You must supply uri or definition");
155         }
156         if (schemaTypeSystem == null) {
157             schemaTypeSystem = compileSchemaTypeSystem(definition);
158         }
159         this.definition = definition;
160         schemaTypeKeyToSchemaTypeMap = buildSchemaTypeKeyToSchemaTypeMap(schemaTypeSystem);
161         complexTypeMap = buildComplexTypeMap();
162         simpleTypeMap = buildSimpleTypeMap();
163         elementMap = buildElementMap();
164         portMap = buildPortMap();
165     }
166 
167     public Map getSchemaTypeKeyToSchemaTypeMap() {
168         return schemaTypeKeyToSchemaTypeMap;
169     }
170 
171     public Definition getDefinition() {
172         return definition;
173     }
174 
175     public Map getWsdlMap() {
176         return wsdlMap;
177     }
178 
179     /**
180      * Find all the complex types in the previously constructed schema analysis.
181      * Put them in a map from complex type QName to schema fragment.
182      *
183      * @return map of complexType QName to schema fragment
184      */
185     public Map getComplexTypesInWsdl() {
186         return complexTypeMap;
187     }
188 
189     private Map buildComplexTypeMap() {
190         Map complexTypeMap = new HashMap();
191         for (Iterator iterator = schemaTypeKeyToSchemaTypeMap.entrySet().iterator(); iterator.hasNext();) {
192             Map.Entry entry = (Map.Entry) iterator.next();
193             SchemaTypeKey key = (SchemaTypeKey) entry.getKey();
194             if (!key.isSimpleType() && !key.isAnonymous()) {
195                 QName qName = key.getqName();
196                 SchemaType schemaType = (SchemaType) entry.getValue();
197                 complexTypeMap.put(qName, schemaType);
198             }
199         }
200         return complexTypeMap;
201     }
202 
203     public Map getElementToTypeMap() {
204         return elementMap;
205     }
206 
207     private Map buildElementMap() {
208         Map elementToTypeMap = new HashMap();
209         for (Iterator iterator = schemaTypeKeyToSchemaTypeMap.entrySet().iterator(); iterator.hasNext();) {
210             Map.Entry entry = (Map.Entry) iterator.next();
211             SchemaTypeKey key = (SchemaTypeKey) entry.getKey();
212             if (key.isElement()) {
213                 QName elementQName = key.getqName();
214                 SchemaType schemaType = (SchemaType) entry.getValue();
215                 QName typeQName = schemaType.getName();
216                 elementToTypeMap.put(elementQName, typeQName);
217             }
218         }
219         return elementToTypeMap;
220     }
221 
222     /**
223      * Gets a map of all the javax.wsdl.Port instance in the WSDL definition keyed by the port's QName
224      * <p/>
225      * WSDL 1.1 spec: 2.6 "The name attribute provides a unique name among all ports defined within in the enclosing WSDL document."
226      *
227      * @return Map of port QName to javax.wsdl.Port for that QName.
228      */
229 
230     public Map getPortMap() {
231         return portMap;
232     }
233 
234     private Map buildPortMap() {
235         HashMap ports = new HashMap();
236         if (definition != null) {
237             Collection services = definition.getServices().values();
238             for (Iterator iterator = services.iterator(); iterator.hasNext();) {
239                 Service service = (Service) iterator.next();
240                 ports.putAll(service.getPorts());
241             }
242         }
243         return ports;
244     }
245 
246     public Map getSimpleTypeMap() {
247         return simpleTypeMap;
248     }
249 
250     private Map buildSimpleTypeMap() {
251         Map simpleTypeMap = new HashMap();
252         for (Iterator iterator = schemaTypeKeyToSchemaTypeMap.entrySet().iterator(); iterator.hasNext();) {
253             Map.Entry entry = (Map.Entry) iterator.next();
254             SchemaTypeKey key = (SchemaTypeKey) entry.getKey();
255             if (key.isSimpleType() && !key.isAnonymous()) {
256                 QName qName = key.getqName();
257                 SchemaType schemaType = (SchemaType) entry.getValue();
258                 simpleTypeMap.put(qName, schemaType);
259             }
260         }
261         return simpleTypeMap;
262     }
263 
264     public SchemaTypeSystem compileSchemaTypeSystem(Definition definition) throws DeploymentException {
265         List schemaList = new ArrayList();
266         addImportsFromDefinition(definition, schemaList);
267 //        System.out.println("Schemas: " + schemaList);
268         Collection errors = new ArrayList();
269         XmlOptions xmlOptions = new XmlOptions();
270         xmlOptions.setErrorListener(errors);
271         xmlOptions.setEntityResolver(new JarEntityResolver());
272         XmlObject[] schemas = (XmlObject[]) schemaList.toArray(new XmlObject[schemaList.size()]);
273         try {
274             SchemaTypeSystem schemaTypeSystem = XmlBeans.compileXsd(schemas, basicTypeSystem, xmlOptions);
275             if (errors.size() > 0) {
276                 boolean wasError = false;
277                 for (Iterator iterator = errors.iterator(); iterator.hasNext();) {
278                     XmlError xmlError = (XmlError) iterator.next();
279                     if(xmlError.getSeverity() == XmlError.SEVERITY_ERROR) {
280                         log.error(xmlError);
281                         wasError = true;
282                     } else if(xmlError.getSeverity() == XmlError.SEVERITY_WARNING) {
283                         log.warn(xmlError);
284                     } else if(xmlError.getSeverity() == XmlError.SEVERITY_INFO) {
285                         log.debug(xmlError);
286                     }
287                 }
288                 if (wasError) {
289                     throw new DeploymentException("Could not compile schema type system, see log for errors");
290                 }
291             }
292             return schemaTypeSystem;
293         } catch (XmlException e) {
294             throw new DeploymentException("Could not compile schema type system: " + schemaList, e);
295         }
296     }
297 
298     private void addImportsFromDefinition(Definition definition, List schemaList) throws DeploymentException {
299         Map namespaceMap = definition.getNamespaces();
300         Types types = definition.getTypes();
301         if (types != null) {
302             List schemas = types.getExtensibilityElements();
303             for (Iterator iterator = schemas.iterator(); iterator.hasNext();) {
304                 Object o = iterator.next();
305                 if (o instanceof Schema) {
306                     Schema unknownExtensibilityElement = (Schema) o;
307                     QName elementType = unknownExtensibilityElement.getElementType();
308                     if (new QName("http://www.w3.org/2001/XMLSchema", "schema").equals(elementType)) {
309                         Element element = unknownExtensibilityElement.getElement();
310                         addSchemaElement(element, namespaceMap, schemaList);
311                     }
312                 } else if (o instanceof UnknownExtensibilityElement) {
313                     //This is allegedly obsolete as of axis-wsdl4j-1.2-RC3.jar which includes the Schema extension above.
314                     //The change notes imply that imported schemas should end up in Schema elements.  They don't, so this is still needed.
315                     UnknownExtensibilityElement unknownExtensibilityElement = (UnknownExtensibilityElement) o;
316                     Element element = unknownExtensibilityElement.getElement();
317                     String elementNamespace = element.getNamespaceURI();
318                     String elementLocalName = element.getNodeName();
319                     if ("http://www.w3.org/2001/XMLSchema".equals(elementNamespace) && "schema".equals(elementLocalName)) {
320                         addSchemaElement(element, namespaceMap, schemaList);
321                     }
322                 }
323             }
324         }
325         Map imports = definition.getImports();
326         if (imports != null) {
327             for (Iterator iterator = imports.entrySet().iterator(); iterator.hasNext();) {
328                 Map.Entry entry = (Map.Entry) iterator.next();
329                 String namespaceURI = (String) entry.getKey();
330                 List importList = (List) entry.getValue();
331                 for (Iterator iterator1 = importList.iterator(); iterator1.hasNext();) {
332                     Import anImport = (Import) iterator1.next();
333                     //according to the 1.1 jwsdl mr shcema imports are supposed to show up here,
334                     //but according to the 1.0 spec there is supposed to be no Definition.
335                     Definition definition1 = anImport.getDefinition();
336                     if (definition1 != null) {
337                         try {
338                             URI uri = new URI(definition1.getDocumentBaseURI());
339                             uris.push(uri);
340                         } catch (URISyntaxException e) {
341                             throw new DeploymentException("Could not locate definition", e);
342                         }
343                         try {
344                             addImportsFromDefinition(definition1, schemaList);
345                         } finally {
346                             uris.pop();
347                         }
348                     } else {
349                         log.warn("Missing definition in import for namespace " + namespaceURI);
350                     }
351                 }
352             }
353         }
354     }
355 
356     private void addSchemaElement(Element element, Map namespaceMap, List schemaList) throws DeploymentException {
357         try {
358             XmlObject xmlObject = parseWithNamespaces(element, namespaceMap);
359             schemaList.add(xmlObject);
360         } catch (XmlException e) {
361             throw new DeploymentException("Could not parse schema element", e);
362         }
363     }
364 
365     static XmlObject parseWithNamespaces(Element element, Map namespaceMap) throws XmlException {
366         ArrayList errors = new ArrayList();
367         XmlOptions xmlOptions = XmlBeansUtil.createXmlOptions(errors);
368         SchemaDocument parsed = SchemaDocument.Factory.parse(element, xmlOptions);
369         if (errors.size() != 0) {
370             throw new XmlException(errors.toArray().toString());
371         }
372         XmlCursor cursor = parsed.newCursor();
373         try {
374             cursor.toFirstContentToken();
375             for (Iterator namespaces = namespaceMap.entrySet().iterator(); namespaces.hasNext();) {
376                 Map.Entry entry = (Map.Entry) namespaces.next();
377                 cursor.insertNamespace((String) entry.getKey(), (String) entry.getValue());
378             }
379         } finally {
380             cursor.dispose();
381         }
382         return parsed;
383     }
384 
385     /**
386      * builds a map of SchemaTypeKey containing jaxrpc-style fake QName and context info to xmlbeans SchemaType object.
387      *
388      * @param schemaTypeSystem
389      * @return Map of SchemaTypeKey to xmlbeans SchemaType object.
390      */
391     private Map buildSchemaTypeKeyToSchemaTypeMap(SchemaTypeSystem schemaTypeSystem) {
392         Map qnameMap = new HashMap();
393         SchemaType[] globalTypes = schemaTypeSystem.globalTypes();
394         for (int i = 0; i < globalTypes.length; i++) {
395             SchemaType globalType = globalTypes[i];
396             QName typeQName = globalType.getName();
397             addSchemaType(typeQName, globalType, false, qnameMap);
398         }
399         SchemaGlobalElement[] globalElements = schemaTypeSystem.globalElements();
400         for (int i = 0; i < globalElements.length; i++) {
401             SchemaGlobalElement globalElement = globalElements[i];
402             addElement(globalElement, null, qnameMap);
403         }
404         return qnameMap;
405     }
406 
407     private void addElement(SchemaField element, SchemaTypeKey key, Map qnameMap) {
408         //TODO is this null if element is a ref?
409         QName elementName = element.getName();
410         String elementNamespace = elementName.getNamespaceURI();
411         //"" namespace means local element with elementFormDefault="unqualified"
412         if (elementNamespace == null || elementNamespace.equals("")) {
413             elementNamespace = key.getqName().getNamespaceURI();
414         }
415         String elementQNameLocalName;
416         SchemaTypeKey elementKey;
417         if (key == null) {
418             //top level. rule 2.a,
419             elementQNameLocalName = elementName.getLocalPart();
420             elementKey = new SchemaTypeKey(elementName, true, false, false, elementName);
421         } else {
422             //not top level. rule 2.b, key will be for enclosing Type.
423             QName enclosingTypeQName = key.getqName();
424             String enclosingTypeLocalName = enclosingTypeQName.getLocalPart();
425             elementQNameLocalName = enclosingTypeLocalName + ">" + elementName.getLocalPart();
426             QName subElementName = new QName(elementNamespace, elementQNameLocalName);
427             elementKey = new SchemaTypeKey(subElementName, true, false, true, elementName);
428         }
429         SchemaType schemaType = element.getType();
430         qnameMap.put(elementKey, schemaType);
431 //        new Exception("Adding: " + elementKey.getqName().getLocalPart()).printStackTrace();
432         //check if it's an array. maxOccurs is null if unbounded
433         //element should always be a SchemaParticle... this is a workaround for XMLBEANS-137
434         if (element instanceof SchemaParticle) {
435             addArrayForms((SchemaParticle) element, elementKey.getqName(), qnameMap, schemaType);
436         } else {
437             log.warn("element is not a schemaParticle! " + element);
438         }
439         //now, name for type.  Rule 1.b, type inside an element
440         String typeQNameLocalPart = ">" + elementQNameLocalName;
441         QName typeQName = new QName(elementNamespace, typeQNameLocalPart);
442         boolean isAnonymous = true;
443         addSchemaType(typeQName, schemaType, isAnonymous, qnameMap);
444     }
445 
446     private void addSchemaType(QName typeQName, SchemaType schemaType, boolean anonymous, Map qnameMap) {
447         SchemaTypeKey typeKey = new SchemaTypeKey(typeQName, false, schemaType.isSimpleType(), anonymous, null);
448         qnameMap.put(typeKey, schemaType);
449 //        new Exception("Adding: " + typeKey.getqName().getLocalPart()).printStackTrace();
450         //TODO xmlbeans recommends using summary info from getElementProperties and getAttributeProperties instead of traversing the content model by hand.
451         SchemaParticle schemaParticle = schemaType.getContentModel();
452         if (schemaParticle != null) {
453             addSchemaParticle(schemaParticle, typeKey, qnameMap);
454         }
455     }
456 
457 
458     private void addSchemaParticle(SchemaParticle schemaParticle, SchemaTypeKey key, Map qnameMap) {
459         if (schemaParticle.getParticleType() == SchemaParticle.ELEMENT) {
460             SchemaType elementType = schemaParticle.getType();
461             SchemaField element = elementType.getContainerField();
462             //element will be null if the type is defined elsewhere, such as a built in type.
463             if (element != null) {
464                 addElement(element, key, qnameMap);
465             } else {
466                 QName keyQName = key.getqName();
467                 //TODO I can't distinguish between 3.a and 3.b, so generate names both ways.
468                 //3.b
469                 String localPart = schemaParticle.getName().getLocalPart();
470                 QName elementName = new QName(keyQName.getNamespaceURI(), localPart);
471                 addArrayForms(schemaParticle, elementName, qnameMap, elementType);
472                 //3.a
473                 localPart = keyQName.getLocalPart() + ">" + schemaParticle.getName().getLocalPart();
474                 elementName = new QName(keyQName.getNamespaceURI(), localPart);
475                 addArrayForms(schemaParticle, elementName, qnameMap, elementType);
476             }
477         } else {
478             try {
479                 SchemaParticle[] children = schemaParticle.getParticleChildren();
480                 for (int i = 0; i < children.length; i++) {
481                     SchemaParticle child = children[i];
482                     addSchemaParticle(child, key, qnameMap);
483                 }
484             } catch (NullPointerException e) {
485                 //ignore xmlbeans bug
486             }
487         }
488     }
489 
490     private void addArrayForms(SchemaParticle schemaParticle, QName keyName, Map qnameMap, SchemaType elementType) {
491         //it may be a ref or a built in type.  If it's an array (maxOccurs >1) form a type for it.
492         if (schemaParticle.getIntMaxOccurs() > 1) {
493             String maxOccurs = schemaParticle.getMaxOccurs() == null ? "unbounded" : "" + schemaParticle.getIntMaxOccurs();
494             int minOccurs = schemaParticle.getIntMinOccurs();
495             QName elementName = schemaParticle.getName();
496             String arrayQNameLocalName = keyName.getLocalPart() + "[" + minOccurs + "," + maxOccurs + "]";
497             String elementNamespace = elementName.getNamespaceURI();
498             if (elementNamespace == null || elementNamespace.equals("")) {
499                 elementNamespace = keyName.getNamespaceURI();
500             }
501             QName arrayName = new QName(elementNamespace, arrayQNameLocalName);
502             SchemaTypeKey arrayKey = new SchemaTypeKey(arrayName, false, false, true, elementName);
503             //TODO not clear we want the schemaType as the value
504             qnameMap.put(arrayKey, elementType);
505 //            new Exception("Adding: " + arrayKey.getqName().getLocalPart()).printStackTrace();
506             if (minOccurs == 1) {
507                 arrayQNameLocalName = keyName.getLocalPart() + "[," + maxOccurs + "]";
508                 arrayName = new QName(elementNamespace, arrayQNameLocalName);
509                 arrayKey = new SchemaTypeKey(arrayName, false, false, true, elementName);
510                 //TODO not clear we want the schemaType as the value
511                 qnameMap.put(arrayKey, elementType);
512             }
513         }
514     }
515 
516 
517     public Definition readWsdl(JarFile moduleFile, URI wsdlURI) throws DeploymentException {
518         Definition definition;
519         WSDLFactory wsdlFactory;
520         try {
521             wsdlFactory = WSDLFactory.newInstance();
522         } catch (WSDLException e) {
523             throw new DeploymentException("Could not create WSDLFactory", e);
524         }
525         WSDLReader wsdlReaderNoImport = wsdlFactory.newWSDLReader();
526         wsdlReaderNoImport.setFeature("javax.wsdl.importDocuments", false);
527         ExtensionRegistry extensionRegistry = new PopulatedExtensionRegistry();
528         extensionRegistry.mapExtensionTypes(Types.class, SchemaConstants.Q_ELEM_XSD_1999,
529                 UnknownExtensibilityElement.class);
530         extensionRegistry.registerDeserializer(Types.class, SchemaConstants.Q_ELEM_XSD_1999,
531                 extensionRegistry.getDefaultDeserializer());
532         extensionRegistry.registerSerializer(Types.class, SchemaConstants.Q_ELEM_XSD_1999,
533                 extensionRegistry.getDefaultSerializer());
534 
535         extensionRegistry.mapExtensionTypes(Types.class, SchemaConstants.Q_ELEM_XSD_2000,
536                 UnknownExtensibilityElement.class);
537         extensionRegistry.registerDeserializer(Types.class, SchemaConstants.Q_ELEM_XSD_2000,
538                 extensionRegistry.getDefaultDeserializer());
539         extensionRegistry.registerSerializer(Types.class, SchemaConstants.Q_ELEM_XSD_2000,
540                 extensionRegistry.getDefaultSerializer());
541 
542         extensionRegistry.mapExtensionTypes(Types.class, SchemaConstants.Q_ELEM_XSD_2001,
543                 UnknownExtensibilityElement.class);
544         extensionRegistry.registerDeserializer(Types.class, SchemaConstants.Q_ELEM_XSD_2001,
545                 extensionRegistry.getDefaultDeserializer());
546         extensionRegistry.registerSerializer(Types.class, SchemaConstants.Q_ELEM_XSD_2001,
547                 extensionRegistry.getDefaultSerializer());
548         wsdlReaderNoImport.setExtensionRegistry(extensionRegistry);
549 
550         JarWSDLLocator wsdlLocator = new JarWSDLLocator(wsdlURI);
551         WSDLReader wsdlReader = wsdlFactory.newWSDLReader();
552 
553         Thread thread = Thread.currentThread();
554         ClassLoader oldCl = thread.getContextClassLoader();
555         thread.setContextClassLoader(this.getClass().getClassLoader());
556         try {
557             try {
558                 definition = wsdlReader.readWSDL(wsdlLocator);
559             } catch (WSDLException e) {
560                 throw new DeploymentException("Failed to read wsdl document", e);
561             }
562         } finally {
563             thread.setContextClassLoader(oldCl);
564         }
565 
566         return definition;
567     }
568 
569     public static ExtensibilityElement getExtensibilityElement(Class clazz, List extensibilityElements) throws DeploymentException {
570         for (Iterator iterator = extensibilityElements.iterator(); iterator.hasNext();) {
571             ExtensibilityElement extensibilityElement = (ExtensibilityElement) iterator.next();
572             if (clazz.isAssignableFrom(extensibilityElement.getClass())) {
573                 return extensibilityElement;
574             }
575         }
576         throw new DeploymentException("No element of class " + clazz.getName() + " found");
577     }
578 
579     public String movePortLocation(String portComponentName, String servletLocation) throws DeploymentException {
580         DefinitionsDocument doc = (DefinitionsDocument) wsdlMap.get(uris.get(0));
581         TDefinitions definitions = doc.getDefinitions();
582         TService[] services = definitions.getServiceArray();
583         for (int i = 0; i < services.length; i++) {
584             TService service = services[i];
585             TPort[] ports = service.getPortArray();
586             for (int j = 0; j < ports.length; j++) {
587                 TPort port = ports[j];
588                 if (port.getName().trim().equals(portComponentName)) {
589                     XmlCursor portCursor = port.newCursor();
590                     try {
591                         if (portCursor.toChild(ADDRESS_QNAME)) {
592                             if (servletLocation == null) {
593                                 String original = portCursor.getAttributeText(LOCATION_QNAME);
594                                 URI originalURI = new URI(original);
595                                 servletLocation = originalURI.getPath();
596                             }
597                             portCursor.setAttributeText(LOCATION_QNAME, WebServiceContainer.LOCATION_REPLACEMENT_TOKEN + servletLocation);
598                             return servletLocation;
599                         }
600                     } catch (URISyntaxException e) {
601                         throw new DeploymentException("Could not construct URI for ejb location in wsdl", e);
602                     } finally {
603                         portCursor.dispose();
604                     }
605                 }
606             }
607         }
608         throw new DeploymentException("No port found with name " + portComponentName + " expected at " + servletLocation);
609     }
610 
611     private class JarEntityResolver implements EntityResolver {
612 
613         private final static String PROJECT_URL_PREFIX = "project://local/";
614 
615         public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
616             //seems like this must be a bug in xmlbeans...
617             if (systemId.indexOf(PROJECT_URL_PREFIX) > -1) {
618                 systemId = systemId.substring(PROJECT_URL_PREFIX.length());
619             }
620             URI location = ((URI) uris.peek()).resolve(systemId);
621             InputStream wsdlInputStream;
622             try {
623                 ZipEntry entry = moduleFile.getEntry(location.toString());
624                 wsdlInputStream = moduleFile.getInputStream(entry);
625                 XmlObject xmlObject = SchemaDocument.Factory.parse(wsdlInputStream);
626                 wsdlMap.put(location, xmlObject);
627                 wsdlInputStream.close();
628                 wsdlInputStream = moduleFile.getInputStream(entry);
629             } catch (XmlException e) {
630                 throw (IOException) new IOException("Could not parse schema document").initCause(e);
631             }
632             return new InputSource(wsdlInputStream);
633         }
634     }
635 
636     class JarWSDLLocator implements WSDLLocator {
637 
638         private final List streams = new ArrayList();
639         private final URI wsdlURI;
640         private URI latestImportURI;
641 
642         public JarWSDLLocator(URI wsdlURI) {
643             this.wsdlURI = wsdlURI;
644         }
645 
646         public InputSource getBaseInputSource() {
647             InputStream wsdlInputStream;
648             try {
649                 ZipEntry entry = moduleFile.getEntry(wsdlURI.toString());
650                 wsdlInputStream = moduleFile.getInputStream(entry);
651                 DefinitionsDocument definition = DefinitionsDocument.Factory.parse(wsdlInputStream);
652                 wsdlMap.put(wsdlURI, definition);
653                 wsdlInputStream.close();
654                 wsdlInputStream = moduleFile.getInputStream(entry);
655                 streams.add(wsdlInputStream);
656             } catch (Exception e) {
657                 throw new RuntimeException("Could not open stream to wsdl file", e);
658             }
659             return new InputSource(wsdlInputStream);
660         }
661 
662         public String getBaseURI() {
663             return wsdlURI.toString();
664         }
665 
666         public InputSource getImportInputSource(String parentLocation, String relativeLocation) {
667             URI parentURI = URI.create(parentLocation);
668             latestImportURI = parentURI.resolve(relativeLocation);
669             InputStream importInputStream;
670             try {
671                 ZipEntry entry = moduleFile.getEntry(latestImportURI.toString());
672                 importInputStream = moduleFile.getInputStream(entry);
673                 try {
674                     DefinitionsDocument definition = DefinitionsDocument.Factory.parse(importInputStream);
675                     importInputStream.close();
676                     wsdlMap.put(latestImportURI, definition);
677                     importInputStream.close();
678                 } catch (XmlException e) {
679                     //probably was a schema rather than wsdl.  If there are real problems they will show up later.
680                 }
681                 importInputStream = moduleFile.getInputStream(entry);
682                 streams.add(importInputStream);
683             } catch (Exception e) {
684                 throw new RuntimeException("Could not open stream to import file", e);
685             }
686             InputSource inputSource = new InputSource(importInputStream);
687             inputSource.setSystemId(getLatestImportURI());
688             return inputSource;
689         }
690 
691         public String getLatestImportURI() {
692             return latestImportURI.toString();
693         }
694 
695         public void close() {
696             for (Iterator iterator = streams.iterator(); iterator.hasNext();) {
697                 InputStream inputStream = (InputStream) iterator.next();
698                 try {
699                     inputStream.close();
700                 } catch (IOException e) {
701                     //ignore
702                 }
703             }
704             streams.clear();
705         }
706     }
707 }