| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.tuscany.sca.interfacedef.wsdl.xml; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.wsdl.Binding; |
| import javax.wsdl.Definition; |
| import javax.wsdl.Operation; |
| import javax.wsdl.PortType; |
| import javax.wsdl.Service; |
| import javax.wsdl.Types; |
| import javax.wsdl.WSDLException; |
| import javax.wsdl.extensions.AttributeExtensible; |
| import javax.wsdl.extensions.ExtensibilityElement; |
| import javax.wsdl.extensions.ExtensionDeserializer; |
| import javax.wsdl.extensions.ExtensionRegistry; |
| import javax.wsdl.extensions.ExtensionSerializer; |
| import javax.wsdl.extensions.UnknownExtensibilityElement; |
| import javax.wsdl.extensions.UnknownExtensionDeserializer; |
| import javax.wsdl.extensions.UnknownExtensionSerializer; |
| import javax.wsdl.extensions.schema.Schema; |
| import javax.wsdl.xml.WSDLLocator; |
| import javax.wsdl.xml.WSDLReader; |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLInputFactory; |
| import javax.xml.stream.XMLStreamConstants; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamReader; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.apache.tuscany.sca.common.java.io.IOHelper; |
| import org.apache.tuscany.sca.common.xml.XMLDocumentHelper; |
| import org.apache.tuscany.sca.contribution.Artifact; |
| import org.apache.tuscany.sca.contribution.Contribution; |
| import org.apache.tuscany.sca.contribution.ContributionFactory; |
| import org.apache.tuscany.sca.contribution.DefaultImport; |
| import org.apache.tuscany.sca.contribution.Import; |
| import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; |
| import org.apache.tuscany.sca.contribution.processor.ContributionReadException; |
| import org.apache.tuscany.sca.contribution.processor.ContributionRuntimeException; |
| import org.apache.tuscany.sca.contribution.processor.ProcessorContext; |
| import org.apache.tuscany.sca.contribution.resolver.ModelResolver; |
| import org.apache.tuscany.sca.core.FactoryExtensionPoint; |
| import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; |
| import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; |
| import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLDefinitionImpl; |
| import org.apache.tuscany.sca.xsd.XSDFactory; |
| import org.apache.tuscany.sca.xsd.XSDefinition; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.xml.sax.InputSource; |
| |
| /** |
| * A Model Resolver for WSDL models. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class WSDLModelResolver implements ModelResolver { |
| //Schema element names |
| public static final String ELEM_SCHEMA = "schema"; |
| public static final QName WSDL11_IMPORT = new QName("http://schemas.xmlsoap.org/wsdl/", "import"); |
| |
| //Schema URI |
| public static final String NS_URI_XSD_1999 = "http://www.w3.org/1999/XMLSchema"; |
| public static final String NS_URI_XSD_2000 = "http://www.w3.org/2000/10/XMLSchema"; |
| public static final String NS_URI_XSD_2001 = "http://www.w3.org/2001/XMLSchema"; |
| |
| //Schema QNames |
| public static final QName Q_ELEM_XSD_1999 = new QName(NS_URI_XSD_1999, ELEM_SCHEMA); |
| public static final QName Q_ELEM_XSD_2000 = new QName(NS_URI_XSD_2000, ELEM_SCHEMA); |
| public static final QName Q_ELEM_XSD_2001 = new QName(NS_URI_XSD_2001, ELEM_SCHEMA); |
| public static final List<QName> XSD_QNAME_LIST = |
| Arrays.asList(new QName[] {Q_ELEM_XSD_1999, Q_ELEM_XSD_2000, Q_ELEM_XSD_2001}); |
| |
| // ---- SCA Policy WSDL Attachments |
| public static final QName Q_POLICY_ATTRIBUTE_EXTENSION = new QName("http://docs.oasis-open.org/ns/opencsa/sca/200912", "requires"); |
| public static final QName Q_POLICY_ELEMENT_EXTENSION = new QName("http://docs.oasis-open.org/ns/opencsa/sca/200912", "requires"); |
| public static final QName Q_POLICY_END_CONVERSATION_ATTRIBUTE_EXTENSION = new QName("http://docs.oasis-open.org/ns/opencsa/sca/200912", "endsConversation"); |
| // ---- SCA Callback WSDL Extension |
| public static final QName Q_CALLBACK_ATTRIBUTE_EXTENSION = new QName("http://docs.oasis-open.org/ns/opencsa/sca/200912", "callback" ); |
| |
| // ---- BPEL extension elements --- Mike Edwards 01/05/2008 |
| public static final String ELEM_PLINKTYPE = "partnerLinkType"; |
| public static final String NS_BPEL_1_1 = "http://schemas.xmlsoap.org/ws/2004/03/partner-link/"; |
| public static final QName BPEL_PLINKTYPE = new QName( NS_BPEL_1_1, ELEM_PLINKTYPE ); |
| public static final String NS_BPEL_2_0 = "http://docs.oasis-open.org/wsbpel/2.0/plnktype"; |
| public static final QName BPEL_PLINKTYPE_2_0 = new QName( NS_BPEL_2_0, ELEM_PLINKTYPE ); |
| // ---- end of BPEL extension elements |
| |
| private Contribution contribution; |
| private Map<String, List<WSDLDefinition>> map = new HashMap<String, List<WSDLDefinition>>(); |
| |
| private ExtensionRegistry wsdlExtensionRegistry; |
| |
| private WSDLFactory wsdlFactory; |
| private javax.wsdl.factory.WSDLFactory wsdl4jFactory; |
| private ContributionFactory contributionFactory; |
| private XSDFactory xsdFactory; |
| |
| public WSDLModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) { |
| this.contribution = contribution; |
| |
| this.wsdlFactory = modelFactories.getFactory(WSDLFactory.class); |
| this.wsdl4jFactory = modelFactories.getFactory(javax.wsdl.factory.WSDLFactory.class); |
| this.contributionFactory = modelFactories.getFactory(ContributionFactory.class); |
| this.xsdFactory = modelFactories.getFactory(XSDFactory.class); |
| |
| wsdlExtensionRegistry = this.wsdl4jFactory.newPopulatedExtensionRegistry(); |
| |
| // REVIEW: [rfeng] Disable the schema extension for WSDL4J to avoid aggressive loading |
| ExtensionDeserializer deserializer = new UnknownExtensionDeserializer(); |
| ExtensionSerializer serializer = new UnknownExtensionSerializer(); |
| for (QName schema : XSD_QNAME_LIST) { |
| wsdlExtensionRegistry.registerSerializer(Types.class, schema, serializer); |
| wsdlExtensionRegistry.registerDeserializer(Types.class, schema, deserializer); |
| } |
| |
| // ---- Policy WSDL Extensions |
| try { |
| wsdlExtensionRegistry.registerExtensionAttributeType(PortType.class, Q_POLICY_ATTRIBUTE_EXTENSION, AttributeExtensible.LIST_OF_QNAMES_TYPE); |
| wsdlExtensionRegistry.registerExtensionAttributeType(Operation.class, Q_POLICY_END_CONVERSATION_ATTRIBUTE_EXTENSION, AttributeExtensible.STRING_TYPE); |
| wsdlExtensionRegistry.registerExtensionAttributeType(PortType.class, Q_CALLBACK_ATTRIBUTE_EXTENSION, AttributeExtensible.QNAME_TYPE); |
| |
| serializer = new PolicyExtensionHandler(); |
| deserializer = new PolicyExtensionHandler(); |
| wsdlExtensionRegistry.registerSerializer(PortType.class, Q_POLICY_ELEMENT_EXTENSION, serializer); |
| wsdlExtensionRegistry.registerDeserializer(PortType.class, Q_POLICY_ELEMENT_EXTENSION, deserializer); |
| } catch (NoSuchMethodError e) { |
| // That method does not exist on older WSDL4J levels |
| } |
| |
| // ---- BPEL additions |
| serializer = new BPELExtensionHandler(); |
| deserializer = new BPELExtensionHandler(); |
| wsdlExtensionRegistry.registerSerializer(Definition.class, BPEL_PLINKTYPE, serializer); |
| wsdlExtensionRegistry.registerDeserializer(Definition.class, BPEL_PLINKTYPE, deserializer); |
| wsdlExtensionRegistry.registerSerializer(Definition.class, BPEL_PLINKTYPE_2_0, serializer); |
| wsdlExtensionRegistry.registerDeserializer(Definition.class, BPEL_PLINKTYPE_2_0, deserializer); |
| // ---- end of BPEL additions |
| } |
| |
| /** |
| * Implementation of a WSDL locator. |
| */ |
| private class WSDLLocatorImpl implements WSDLLocator { |
| private ProcessorContext context; |
| private InputStream inputStream; |
| private URL base; |
| private String latestImportURI; |
| private Map<String, String> wsdlImports; |
| |
| public WSDLLocatorImpl(ProcessorContext context, URL base, InputStream is, Map<String, String> imports) { |
| this.context = context; |
| this.base = base; |
| this.inputStream = is; |
| this.wsdlImports = imports; |
| } |
| |
| public void close() { |
| try { |
| inputStream.close(); |
| } catch (IOException e) { |
| // Ignore |
| } |
| } |
| |
| public InputSource getBaseInputSource() { |
| try { |
| return XMLDocumentHelper.getInputSource(base, inputStream); |
| } catch (IOException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| |
| public String getBaseURI() { |
| return base.toString(); |
| } |
| |
| public InputSource getImportInputSource(String parentLocation, String importLocation) { |
| try { |
| if (importLocation == null) { |
| throw new IllegalArgumentException("Required attribute 'location' is missing."); |
| } |
| if (importLocation.trim().equals("")) |
| throw new IllegalArgumentException("Required attribute 'location' is empty."); |
| |
| URL url = null; |
| if (importLocation.startsWith("/")) { |
| // The URI is relative to the contribution |
| String uri = importLocation.substring(1); |
| |
| Artifact proxyArtifact = contributionFactory.createArtifact(); |
| proxyArtifact.setURI(uri); |
| |
| //use contribution resolution (this supports import/export) |
| Artifact importedArtifact = |
| contribution.getModelResolver().resolveModel(Artifact.class, proxyArtifact, context); |
| if (importedArtifact.getLocation() != null) { |
| //get the artifact URL |
| url = new URL(importedArtifact.getLocation()); |
| } |
| } else { |
| url = new URL(new URL(parentLocation), importLocation); |
| } |
| if (url == null) { |
| return null; |
| } |
| latestImportURI = url.toString(); |
| return XMLDocumentHelper.getInputSource(url); |
| } catch (IOException e) { |
| // If we are not able to resolve the imports using location, then |
| // try resolving them using the namespace. |
| try { |
| if (! wsdlImports.isEmpty()) { |
| for (Artifact artifact : contribution.getArtifacts()) { |
| if (artifact.getModel() instanceof WSDLDefinitionImpl) { |
| String namespace = ((WSDLDefinitionImpl)artifact.getModel()).getNamespace(); |
| for (Map.Entry<String, String> entry : ((Map<String, String>)wsdlImports).entrySet()) { |
| if (entry.getKey().equals(namespace)) { |
| URL url = ((WSDLDefinitionImpl)artifact.getModel()).getLocation().toURL(); |
| return XMLDocumentHelper.getInputSource(url); |
| } |
| } |
| } |
| } |
| } |
| } catch (IOException ex) { |
| throw new ContributionRuntimeException(ex); |
| } |
| throw new ContributionRuntimeException(e); |
| } |
| } |
| |
| public String getLatestImportURI() { |
| return latestImportURI; |
| } |
| |
| } |
| |
| public void addModel(Object resolved, ProcessorContext context) { |
| WSDLDefinition definition = (WSDLDefinition)resolved; |
| for (XSDefinition d : definition.getXmlSchemas()) { |
| if (contribution != null) { |
| contribution.getModelResolver().addModel(d, context); |
| } |
| } |
| List<WSDLDefinition> list = map.get(definition.getNamespace()); |
| if (list == null) { |
| list = new ArrayList<WSDLDefinition>(); |
| map.put(definition.getNamespace(), list); |
| } |
| list.add(definition); |
| } |
| |
| public Object removeModel(Object resolved, ProcessorContext context) { |
| WSDLDefinition definition = (WSDLDefinition)resolved; |
| List<WSDLDefinition> list = map.get(definition.getNamespace()); |
| if (list == null) { |
| return null; |
| } else { |
| return list.remove(definition); |
| } |
| } |
| |
| /** |
| * Create a facade Definition which imports all the definitions |
| * |
| * @param definitions A list of the WSDL definitions under the same target namespace |
| * @param context |
| * @return The aggregated WSDL definition |
| */ |
| @SuppressWarnings("unchecked") |
| private WSDLDefinition aggregate(List<WSDLDefinition> definitions, ProcessorContext context) throws ContributionReadException { |
| if (definitions == null || definitions.size() == 0) { |
| return null; |
| } |
| if (definitions.size() == 1) { |
| WSDLDefinition d = definitions.get(0); |
| loadDefinition(d, context); |
| return d; |
| } |
| WSDLDefinition aggregated = wsdlFactory.createWSDLDefinition(); |
| for (WSDLDefinition d : definitions) { |
| loadDefinition(d, context); |
| } |
| Definition facade = wsdl4jFactory.newDefinition(); |
| String ns = definitions.get(0).getNamespace(); |
| facade.setQName(new QName(ns, "$aggregated$")); |
| facade.setTargetNamespace(ns); |
| |
| for (WSDLDefinition d : definitions) { |
| if (d.getDefinition() != null) { |
| javax.wsdl.Import imp = facade.createImport(); |
| imp.setNamespaceURI(d.getNamespace()); |
| imp.setDefinition(d.getDefinition()); |
| imp.setLocationURI(d.getDefinition().getDocumentBaseURI()); |
| facade.addImport(imp); |
| // aggregated.getXmlSchemas().addAll(d.getXmlSchemas()); |
| aggregated.getImportedDefinitions().add(d); |
| // Deal with extensibility elements in the imported Definitions... |
| List<ExtensibilityElement> extElements = (List<ExtensibilityElement>) d.getDefinition().getExtensibilityElements(); |
| for( ExtensibilityElement extElement : extElements ) { |
| facade.addExtensibilityElement(extElement); |
| } // end for |
| } |
| } |
| aggregated.setDefinition(facade); |
| definitions.clear(); |
| definitions.add(aggregated); |
| return aggregated; |
| } |
| |
| public <T> T resolveModel(Class<T> modelClass, T unresolved, ProcessorContext context) { |
| |
| WSDLDefinition resolved = null; |
| String namespace = ((WSDLDefinition)unresolved).getNamespace(); |
| if (namespace == null) { |
| return modelClass.cast(unresolved); |
| } |
| |
| // Lookup based on wsdli:location |
| if (((WSDLDefinition)unresolved).getWsdliLocations().containsKey(namespace)) { |
| try { |
| loadDefinition(((WSDLDefinition)unresolved), context); |
| } catch (ContributionReadException e) { |
| context.getMonitor().error(context.getMonitor(), this, "interface-wsdlxml-validation-messages", "wsdliLocationException", e, ((WSDLDefinition)unresolved).getNamespace()); |
| } |
| return modelClass.cast((WSDLDefinition)unresolved); |
| } |
| |
| |
| // Lookup a definition for the given namespace, from imports |
| for (Import import_ : this.contribution.getImports()) { |
| if (import_ instanceof NamespaceImport) { |
| NamespaceImport namespaceImport = (NamespaceImport)import_; |
| if (namespaceImport.getNamespace().equals(namespace)) { |
| // Delegate the resolution to the namespace import resolver |
| resolved = |
| namespaceImport.getModelResolver().resolveModel(WSDLDefinition.class, |
| (WSDLDefinition)unresolved, context); |
| if (!resolved.isUnresolved()) { |
| return modelClass.cast(resolved); |
| } |
| } |
| } else if (import_ instanceof DefaultImport) { |
| // Delegate the resolution to the default import resolver |
| resolved = |
| import_.getModelResolver().resolveModel(WSDLDefinition.class, |
| (WSDLDefinition)unresolved, context); |
| if (!resolved.isUnresolved()) { |
| return modelClass.cast(resolved); |
| } |
| } |
| } |
| |
| |
| // Not found, lookup a definition for the given namespace, within contribution |
| List<WSDLDefinition> list = map.get(namespace); |
| try { |
| resolved = aggregate(list, context); |
| } catch (ContributionReadException e) { |
| throw new RuntimeException(e); |
| } |
| if (resolved != null && !resolved.isUnresolved()) { |
| // check that the WSDL we just found has the requisite |
| // port type, binding and/or service. If not return |
| // the input WSDL to force the resolution process to continue |
| WSDLDefinition inputWSDL = (WSDLDefinition)unresolved; |
| WSDLDefinition outputWSDL = (WSDLDefinition)resolved; |
| |
| if (inputWSDL.getNameOfPortTypeToResolve() != null){ |
| if (outputWSDL.getWSDLObject(PortType.class, inputWSDL.getNameOfPortTypeToResolve()) == null){ |
| return modelClass.cast(unresolved); |
| } |
| } |
| |
| if (inputWSDL.getNameOfBindingToResolve() != null){ |
| if (outputWSDL.getWSDLObject(Binding.class, inputWSDL.getNameOfBindingToResolve()) == null){ |
| return modelClass.cast(unresolved); |
| } |
| } |
| |
| if (inputWSDL.getNameOfServiceToResolve() != null){ |
| if (outputWSDL.getWSDLObject(Service.class, inputWSDL.getNameOfServiceToResolve()) == null){ |
| return modelClass.cast(unresolved); |
| } |
| } |
| |
| return modelClass.cast(resolved); |
| } |
| |
| return modelClass.cast(unresolved); |
| } |
| |
| /** |
| * Use non-sca mechanism to resolve the import location, |
| * if not found then use the sca mechanism |
| * |
| * @param modelClass |
| * @param unresolved |
| * @param context |
| * @throws ContributionReadException |
| */ |
| private <T> T resolveImports (Class<T> modelClass, WSDLDefinition unresolved, ProcessorContext context) throws ContributionReadException { |
| |
| WSDLDefinition resolved = null; |
| if (unresolved.getDefinition() == null && unresolved.getLocation() != null) { |
| try { |
| // Load the definition using non-sca mechanism. |
| List<WSDLDefinition> list = new ArrayList<WSDLDefinition>(); |
| list.add(unresolved); |
| map.put(unresolved.getNamespace(), list); |
| resolved = aggregate(list, context); |
| // if no exception then its resolved. |
| if (unresolved.getNamespace().equals(resolved.getDefinition().getTargetNamespace())) { |
| resolved.setNamespace(resolved.getDefinition().getTargetNamespace()); |
| resolved.setUnresolved(false); |
| resolved.setURI(unresolved.getURI()); |
| return modelClass.cast(resolved); |
| } |
| } catch (ContributionReadException e) { |
| // Resolve the wsdl definition using the namespace, by searching the |
| // contribution artifacts for wsdl definition for the given namespace. |
| for (Artifact artifact : contribution.getArtifacts()) { |
| if (artifact.getModel() instanceof WSDLDefinitionImpl) { |
| String namespace = ((WSDLDefinitionImpl)artifact.getModel()).getNamespace(); |
| if (unresolved.getNamespace().equals(namespace)) { |
| WSDLDefinition wsdlDefinition = (WSDLDefinition)artifact.getModel(); |
| if (wsdlDefinition.getDefinition() == null) { |
| loadDefinition(wsdlDefinition, context); |
| } |
| return modelClass.cast(wsdlDefinition); |
| } |
| } |
| } |
| } |
| } |
| |
| return modelClass.cast(unresolved); |
| } |
| |
| |
| /** |
| * Load the WSDL definition and inline schemas |
| * |
| * @param wsdlDef |
| * @param context |
| * @throws ContributionReadException |
| */ |
| private void loadDefinition(WSDLDefinition wsdlDef, ProcessorContext context) throws ContributionReadException { |
| if (wsdlDef.getDefinition() != null) { |
| return; |
| } |
| try { |
| URL artifactURL; |
| String loc = wsdlDef.getWsdliLocations().get(wsdlDef.getNamespace()); |
| if (loc != null) { |
| artifactURL = new URL(loc); |
| } else { |
| if (wsdlDef.getLocation() == null) { |
| return; |
| } |
| artifactURL = wsdlDef.getLocation().toURL(); |
| } |
| // Read a WSDL document |
| InputStream is = IOHelper.openStream(artifactURL); |
| WSDLReader reader = wsdl4jFactory.newWSDLReader(); |
| reader.setFeature("javax.wsdl.verbose", false); |
| reader.setFeature("javax.wsdl.importDocuments", true); |
| // FIXME: We need to decide if we should disable the import processing by WSDL4J |
| // reader.setFeature("javax.wsdl.importDocuments", false); |
| reader.setExtensionRegistry(wsdlExtensionRegistry); // use a custom registry |
| |
| // Collection of namespace,location for wsdl:import definition |
| Map<String, String> wsdlImports = indexRead(artifactURL); |
| wsdlImports.putAll(wsdlDef.getWsdliLocations()); |
| WSDLLocatorImpl locator = new WSDLLocatorImpl(context, artifactURL, is, wsdlImports); |
| Definition definition = reader.readWSDL(locator); |
| wsdlDef.setDefinition(definition); |
| |
| // If this definition imports any definitions from other namespaces, |
| // set the correct WSDLDefinition import relationships. |
| for (Map.Entry<String, List<javax.wsdl.Import>> entry : |
| ((Map<String, List<javax.wsdl.Import>>)definition.getImports()).entrySet()) { |
| if (!entry.getKey().equals(definition.getTargetNamespace())) { |
| // TUSCANY-4004 - This looks a bit dodgy as the wsdlDefinition object will be the same |
| // for multiple imports. |
| WSDLDefinition wsdlDefinition = wsdlFactory.createWSDLDefinition(); |
| wsdlDefinition.setUnresolved(true); |
| wsdlDefinition.setNamespace(entry.getKey()); |
| WSDLDefinition resolved = null; |
| for (javax.wsdl.Import imp : entry.getValue()) { |
| if (imp.getDefinition() == null) |
| throw new IllegalArgumentException("Required attribute 'location' is missing."); |
| |
| try { |
| wsdlDefinition.setLocation(new URI(imp.getDefinition().getDocumentBaseURI())); |
| // TUSCANY-4004 - set the URI of the imported definition to be based on the |
| // location that the user typed in the import. This will |
| // usually be a contribution relative URI so it's consistent |
| // with the URI of the top level WSDL which is set from the |
| // relative location of the artifact that represents the WSDL |
| wsdlDefinition.setURI(new URI(imp.getLocationURI())); |
| indexRead(wsdlDefinition.getLocation().toURL(), context); |
| resolved = resolveImports(WSDLDefinition.class, wsdlDefinition, context); |
| if (!resolved.isUnresolved()) { |
| if (resolved.getImportedDefinitions().isEmpty()) { |
| if (resolved.getDefinition().getTargetNamespace().equals(imp.getDefinition().getTargetNamespace())) { |
| // this WSDLDefinition contains the imported document |
| wsdlDef.getImportedDefinitions().add(resolved); |
| imp.setLocationURI(resolved.getURI().toString()); |
| } |
| } else { |
| // this is a facade, so look in its imported definitions |
| for (WSDLDefinition def : resolved.getImportedDefinitions()) { |
| if (def.getDefinition().getTargetNamespace().equals(imp.getDefinition().getTargetNamespace())) { |
| wsdlDef.getImportedDefinitions().add(def); |
| imp.setLocationURI(def.getURI().toString()); |
| break; |
| } |
| } |
| } |
| } |
| } catch (Exception e) { |
| throw new ContributionReadException(e); |
| } |
| } |
| } |
| } |
| //Read inline schemas |
| readInlineSchemas(wsdlDef, definition, context); |
| } catch (WSDLException e) { |
| throw new ContributionReadException(e); |
| } catch (XMLStreamException e) { |
| throw new ContributionReadException(e); |
| } catch (IOException e) { |
| throw new ContributionReadException(e); |
| } |
| } |
| |
| private Document promote(Element element) { |
| Document doc = (Document)element.getOwnerDocument().cloneNode(false); |
| Element schema = (Element)doc.importNode(element, true); |
| doc.appendChild(schema); |
| Node parent = element.getParentNode(); |
| while (parent instanceof Element) { |
| Element root = (Element)parent; |
| NamedNodeMap nodeMap = root.getAttributes(); |
| if (nodeMap != null) { |
| for (int i = 0; i < nodeMap.getLength(); i++) { |
| Attr attr = (Attr)nodeMap.item(i); |
| String name = attr.getName(); |
| if ("xmlns".equals(name) || name.startsWith("xmlns:")) { |
| if (schema.getAttributeNode(name) == null) { |
| schema.setAttributeNodeNS((Attr)doc.importNode(attr, true)); |
| } |
| } |
| } |
| } |
| parent = parent.getParentNode(); |
| } |
| doc.setDocumentURI(element.getOwnerDocument().getDocumentURI()); |
| return doc; |
| } |
| |
| /** |
| * Populate the inline schemas including those from the imported definitions |
| * |
| * @param definition |
| * @param context |
| * @param schemaCollection |
| */ |
| private void readInlineSchemas(WSDLDefinition wsdlDefinition, Definition definition, ProcessorContext context) { |
| if (contribution == null) { |
| // Check null for test cases |
| return; |
| } |
| Types types = definition.getTypes(); |
| if (types != null) { |
| int index = 0; |
| for (Object ext : types.getExtensibilityElements()) { |
| ExtensibilityElement extElement = (ExtensibilityElement)ext; |
| Element element = null; |
| if (XSD_QNAME_LIST.contains(extElement.getElementType())) { |
| if (extElement instanceof Schema) { |
| element = ((Schema)extElement).getElement(); |
| } else if (extElement instanceof UnknownExtensibilityElement) { |
| element = ((UnknownExtensibilityElement)extElement).getElement(); |
| } |
| } |
| if (element != null) { |
| Document doc = promote(element); |
| XSDefinition xsDefinition = xsdFactory.createXSDefinition(); |
| xsDefinition.setUnresolved(true); |
| xsDefinition.setNamespace(element.getAttribute("targetNamespace")); |
| xsDefinition.setDocument(doc); |
| xsDefinition.setLocation(URI.create(doc.getDocumentURI() + "#" + index)); |
| XSDefinition resolved = |
| contribution.getModelResolver().resolveModel(XSDefinition.class, xsDefinition, context); |
| if (resolved != null && !resolved.isUnresolved()) { |
| if (!wsdlDefinition.getXmlSchemas().contains(resolved)) { |
| // Don't add resolved because it may be an aggregate that |
| // contains more than we need. The resolver will have |
| // set the specific schema we need into unresolved. |
| wsdlDefinition.getXmlSchemas().add(xsDefinition); |
| } |
| } |
| index++; |
| } |
| } |
| } |
| for (Object imports : definition.getImports().values()) { |
| List impList = (List)imports; |
| for (Object i : impList) { |
| javax.wsdl.Import anImport = (javax.wsdl.Import)i; |
| // Read inline schemas |
| if (anImport.getDefinition() != null) { |
| readInlineSchemas(wsdlDefinition, anImport.getDefinition(), context); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Read the namespace and location for the WSDL imports |
| * |
| * @param doc |
| * @return |
| * @throws IOException |
| * @throws XMLStreamException |
| */ |
| protected Map<String, String> indexRead(URL doc) throws IOException, XMLStreamException { |
| |
| Map<String, String> wsdlImports = new HashMap<String, String>(); |
| InputStream is = doc.openStream(); |
| try { |
| // Set up a StreamSource for the composite file, since this has an associated URL that |
| // can be used by the parser to find references to other files such as DTDs |
| XMLInputFactory inputFactory = XMLInputFactory.newInstance(); |
| StreamSource wsdlSource = new StreamSource(is, doc.toString()); |
| XMLStreamReader reader = inputFactory.createXMLStreamReader(wsdlSource); |
| |
| int eventType = reader.getEventType(); |
| while (true) { |
| if (eventType == XMLStreamConstants.START_ELEMENT) { |
| if (WSDL11_IMPORT.equals(reader.getName())) { |
| String ns = reader.getAttributeValue(null, "namespace"); |
| String loc = reader.getAttributeValue(null, "location"); |
| wsdlImports.put(ns, loc); |
| } |
| } |
| if (reader.hasNext()) { |
| eventType = reader.next(); |
| } else { |
| break; |
| } |
| } |
| return wsdlImports; |
| } finally { |
| is.close(); |
| } |
| } |
| |
| protected Map<String, String> indexRead(URL doc, ProcessorContext context) throws IOException, XMLStreamException { |
| |
| Map<String, String> wsdlImports = new HashMap<String, String>(); |
| InputStream is = doc.openStream(); |
| try { |
| // Set up a StreamSource for the composite file, since this has an associated URL that |
| // can be used by the parser to find references to other files such as DTDs |
| XMLInputFactory inputFactory = XMLInputFactory.newInstance(); |
| StreamSource wsdlSource = new StreamSource(is, doc.toString()); |
| XMLStreamReader reader = inputFactory.createXMLStreamReader(wsdlSource); |
| |
| int eventType = reader.getEventType(); |
| int index = 0; |
| while (true) { |
| if (eventType == XMLStreamConstants.START_ELEMENT) { |
| if (WSDLDocumentProcessor.XSD.equals(reader.getName())) { |
| String tns = reader.getAttributeValue(null, "targetNamespace"); |
| XSDefinition xsd = xsdFactory.createXSDefinition(); |
| xsd.setUnresolved(true); |
| xsd.setNamespace(tns); |
| try { |
| xsd.setLocation(URI.create(doc.toURI() + "#" + index)); |
| } catch (URISyntaxException e) { |
| //TODO |
| e.printStackTrace(); |
| } |
| index ++; |
| // The definition is marked as resolved but not loaded |
| xsd.setUnresolved(false); |
| xsd.setSchema(null); |
| if (contribution != null) { |
| contribution.getModelResolver().addModel(xsd, context); |
| } |
| } |
| } |
| if (reader.hasNext()) { |
| eventType = reader.next(); |
| } else { |
| break; |
| } |
| } |
| return wsdlImports; |
| } finally { |
| is.close(); |
| } |
| } |
| |
| } |