001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.server.axis.assembler;
018:
019: import com.ibm.wsdl.extensions.PopulatedExtensionRegistry;
020: import com.ibm.wsdl.extensions.schema.SchemaConstants;
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.apache.openejb.OpenEJBException;
024: import org.apache.ws.commons.schema.XmlSchemaCollection;
025: import org.w3c.dom.Element;
026: import org.xml.sax.InputSource;
027:
028: import javax.wsdl.Definition;
029: import javax.wsdl.Import;
030: import javax.wsdl.Types;
031: import javax.wsdl.WSDLException;
032: import javax.wsdl.extensions.ExtensionRegistry;
033: import javax.wsdl.extensions.UnknownExtensibilityElement;
034: import javax.wsdl.extensions.schema.Schema;
035: import javax.wsdl.factory.WSDLFactory;
036: import javax.wsdl.xml.WSDLLocator;
037: import javax.wsdl.xml.WSDLReader;
038: import javax.xml.namespace.QName;
039: import java.io.IOException;
040: import java.io.InputStream;
041: import java.net.URI;
042: import java.util.ArrayList;
043: import java.util.List;
044: import java.util.Map;
045: import java.util.jar.JarFile;
046: import java.util.zip.ZipEntry;
047:
048: public class CommonsSchemaLoader {
049: private static final Log log = LogFactory
050: .getLog(CommonsSchemaLoader.class);
051:
052: private final URI wsdlUri;
053: private final JarFile moduleFile;
054: private final XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();
055:
056: public CommonsSchemaLoader(URI wsdlUri, JarFile moduleFile) {
057: this .wsdlUri = wsdlUri;
058: this .moduleFile = moduleFile;
059: }
060:
061: public XmlSchemaCollection loadSchema() throws OpenEJBException {
062: Definition definition = readWsdl(wsdlUri);
063: addImportsFromDefinition(definition);
064: return xmlSchemaCollection;
065: }
066:
067: private void addImportsFromDefinition(Definition definition)
068: throws OpenEJBException {
069: Types types = definition.getTypes();
070: if (types != null) {
071: for (Object extensibilityElement : types
072: .getExtensibilityElements()) {
073: if (extensibilityElement instanceof Schema) {
074: Schema unknownExtensibilityElement = (Schema) extensibilityElement;
075: QName elementType = unknownExtensibilityElement
076: .getElementType();
077: if (new QName("http://www.w3.org/2001/XMLSchema",
078: "schema").equals(elementType)) {
079: Element element = unknownExtensibilityElement
080: .getElement();
081: xmlSchemaCollection.read(element);
082: }
083: } else if (extensibilityElement instanceof UnknownExtensibilityElement) {
084: //This is allegedly obsolete as of axis-wsdl4j-1.2-RC3.jar which includes the Schema extension above.
085: //The change notes imply that imported schemas should end up in Schema elements. They don't, so this is still needed.
086: UnknownExtensibilityElement unknownExtensibilityElement = (UnknownExtensibilityElement) extensibilityElement;
087: Element element = unknownExtensibilityElement
088: .getElement();
089: String elementNamespace = element.getNamespaceURI();
090: String elementLocalName = element.getNodeName();
091: if ("http://www.w3.org/2001/XMLSchema"
092: .equals(elementNamespace)
093: && "schema".equals(elementLocalName)) {
094: xmlSchemaCollection.read(element);
095: }
096: }
097: }
098: }
099:
100: //noinspection unchecked
101: Map<String, List<Import>> imports = definition.getImports();
102: if (imports != null) {
103: for (Map.Entry<String, List<Import>> entry : imports
104: .entrySet()) {
105: String namespaceURI = entry.getKey();
106: List<Import> importList = entry.getValue();
107: for (Import anImport : importList) {
108: //according to the 1.1 jwsdl mr shcema imports are supposed to show up here,
109: //but according to the 1.0 spec there is supposed to be no Definition.
110: Definition importedDef = anImport.getDefinition();
111: if (importedDef != null) {
112: addImportsFromDefinition(importedDef);
113: } else {
114: log
115: .warn("Missing definition in import for namespace "
116: + namespaceURI);
117: }
118: }
119: }
120: }
121: }
122:
123: private Definition readWsdl(URI wsdlURI) throws OpenEJBException {
124: Definition definition;
125: WSDLFactory wsdlFactory;
126: try {
127: wsdlFactory = WSDLFactory.newInstance();
128: } catch (WSDLException e) {
129: throw new OpenEJBException("Could not create WSDLFactory",
130: e);
131: }
132: WSDLReader wsdlReaderNoImport = wsdlFactory.newWSDLReader();
133: wsdlReaderNoImport.setFeature("javax.wsdl.importDocuments",
134: false);
135: ExtensionRegistry extensionRegistry = new PopulatedExtensionRegistry();
136: extensionRegistry.mapExtensionTypes(Types.class,
137: SchemaConstants.Q_ELEM_XSD_1999,
138: UnknownExtensibilityElement.class);
139: extensionRegistry.registerDeserializer(Types.class,
140: SchemaConstants.Q_ELEM_XSD_1999, extensionRegistry
141: .getDefaultDeserializer());
142: extensionRegistry.registerSerializer(Types.class,
143: SchemaConstants.Q_ELEM_XSD_1999, extensionRegistry
144: .getDefaultSerializer());
145:
146: extensionRegistry.mapExtensionTypes(Types.class,
147: SchemaConstants.Q_ELEM_XSD_2000,
148: UnknownExtensibilityElement.class);
149: extensionRegistry.registerDeserializer(Types.class,
150: SchemaConstants.Q_ELEM_XSD_2000, extensionRegistry
151: .getDefaultDeserializer());
152: extensionRegistry.registerSerializer(Types.class,
153: SchemaConstants.Q_ELEM_XSD_2000, extensionRegistry
154: .getDefaultSerializer());
155:
156: extensionRegistry.mapExtensionTypes(Types.class,
157: SchemaConstants.Q_ELEM_XSD_2001,
158: UnknownExtensibilityElement.class);
159: extensionRegistry.registerDeserializer(Types.class,
160: SchemaConstants.Q_ELEM_XSD_2001, extensionRegistry
161: .getDefaultDeserializer());
162: extensionRegistry.registerSerializer(Types.class,
163: SchemaConstants.Q_ELEM_XSD_2001, extensionRegistry
164: .getDefaultSerializer());
165: wsdlReaderNoImport.setExtensionRegistry(extensionRegistry);
166:
167: JarWSDLLocator wsdlLocator = new JarWSDLLocator(wsdlURI);
168: WSDLReader wsdlReader = wsdlFactory.newWSDLReader();
169:
170: Thread thread = Thread.currentThread();
171: ClassLoader oldCl = thread.getContextClassLoader();
172: thread.setContextClassLoader(this .getClass().getClassLoader());
173: try {
174: try {
175: definition = wsdlReader.readWSDL(wsdlLocator);
176: } catch (WSDLException e) {
177: throw new OpenEJBException(
178: "Failed to read wsdl document", e);
179: } catch (RuntimeException e) {
180: throw new OpenEJBException(e.getMessage(), e);
181: }
182: } finally {
183: thread.setContextClassLoader(oldCl);
184: }
185:
186: return definition;
187: }
188:
189: class JarWSDLLocator implements WSDLLocator {
190:
191: private final List<InputStream> streams = new ArrayList<InputStream>();
192: private final URI wsdlURI;
193: private URI latestImportURI;
194:
195: public JarWSDLLocator(URI wsdlURI) {
196: this .wsdlURI = wsdlURI;
197: }
198:
199: public InputSource getBaseInputSource() {
200: ZipEntry entry = moduleFile.getEntry(wsdlURI.toString());
201: if (entry == null) {
202: throw new RuntimeException(
203: "The webservices.xml file points to a non-existant WSDL file "
204: + wsdlURI.toString());
205: }
206:
207: InputStream wsdlInputStream;
208: try {
209: wsdlInputStream = moduleFile.getInputStream(entry);
210: streams.add(wsdlInputStream);
211: } catch (Exception e) {
212: throw new RuntimeException(
213: "Could not open stream to wsdl file", e);
214: }
215: return new InputSource(wsdlInputStream);
216: }
217:
218: public String getBaseURI() {
219: return wsdlURI.toString();
220: }
221:
222: public InputSource getImportInputSource(String parentLocation,
223: String relativeLocation) {
224: URI parentURI = URI.create(parentLocation);
225: latestImportURI = parentURI.resolve(relativeLocation);
226:
227: InputStream importInputStream;
228: try {
229: ZipEntry entry = moduleFile.getEntry(latestImportURI
230: .toString());
231: importInputStream = moduleFile.getInputStream(entry);
232: streams.add(importInputStream);
233: } catch (Exception e) {
234: throw new RuntimeException(
235: "Could not open stream to import file", e);
236: }
237:
238: InputSource inputSource = new InputSource(importInputStream);
239: inputSource.setSystemId(getLatestImportURI());
240: return inputSource;
241: }
242:
243: public String getLatestImportURI() {
244: return latestImportURI.toString();
245: }
246:
247: public void close() {
248: for (InputStream inputStream : streams) {
249: try {
250: inputStream.close();
251: } catch (IOException e) {
252: //ignore
253: }
254: }
255: streams.clear();
256: }
257: }
258: }
|