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