diff options
Diffstat (limited to 'branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache')
21 files changed, 2361 insertions, 0 deletions
diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospector.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospector.java new file mode 100644 index 0000000000..1b9326acab --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospector.java @@ -0,0 +1,48 @@ +/* + * 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.idl.wsdl; + +import javax.wsdl.PortType; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; + +/** + * Introspector for creating WSDLServiceContract definitions from WSDL PortTypes. + * + * @version $Rev$ $Date$ + */ +public interface InterfaceWSDLIntrospector { + + /** + * Introspect a WSDL portType and return a service contract definition. + * + * @param type the portType to inspect + * @return a WSDLServiceContract corresponding to the WSDL portType + */ + WSDLServiceContract introspect(PortType portType) throws InvalidServiceContractException; + + /** + * Introspect a WSDL portType and return a service contract definition. + * + * @param type the portType to inspect + * @param callback the callback portType to inspec + * @return a WSDLServiceContract corresponding to the WSDL portType + */ + WSDLServiceContract introspect(PortType type, PortType callback) throws InvalidServiceContractException; +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospectorImpl.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospectorImpl.java new file mode 100644 index 0000000000..b705413fe1 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLIntrospectorImpl.java @@ -0,0 +1,102 @@ +/* + * 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.idl.wsdl; + +import java.util.HashMap; +import java.util.Map; + +import javax.wsdl.Operation; +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.InteractionScope; +import org.osoa.sca.annotations.Constructor; + +/** + * Introspector for creating WSDLServiceContract definitions from WSDL PortTypes. + */ +public class InterfaceWSDLIntrospectorImpl implements InterfaceWSDLIntrospector { + private WSDLDefinitionRegistry wsdlDefinitionRegistry; + + /** + * @param wsdlDefinitionRegistry + */ + @Constructor("wsdlDefinitionRegistry") + public InterfaceWSDLIntrospectorImpl(@Autowire WSDLDefinitionRegistry wsdlDefinitionRegistry) { + super(); + this.wsdlDefinitionRegistry = wsdlDefinitionRegistry; + } + + // FIXME: Do we want to deal with document-literal wrapped style based on the JAX-WS spec? + protected Map<String, org.apache.tuscany.spi.model.Operation<XMLType>> introspectOperations(PortType portType) + throws InvalidServiceContractException { + Map<String, org.apache.tuscany.spi.model.Operation<XMLType>> operations = + new HashMap<String, org.apache.tuscany.spi.model.Operation<XMLType>>(); + for (Object op : portType.getOperations()) { + Operation wsdlOp = (Operation) op; + operations.put(wsdlOp.getName(), introspectOperation(wsdlOp)); + } + return operations; + } + + protected org.apache.tuscany.spi.model.Operation<XMLType> introspectOperation(Operation wsdlOp) + throws InvalidServiceContractException { + + WSDLOperation op = new WSDLOperation(wsdlOp, null, wsdlDefinitionRegistry.getSchemaRegistry()); + return op.getOperation(); + } + + /** + * @see org.apache.tuscany.idl.wsdl.InterfaceWSDLIntrospector#introspect(javax.wsdl.PortType) + */ + public WSDLServiceContract introspect(PortType portType) throws InvalidServiceContractException { + WSDLServiceContract contract = new WSDLServiceContract(); + contract.setPortType(portType); + contract.setInterfaceName(portType.getQName().getLocalPart()); + contract.setOperations(introspectOperations(portType)); + // FIXME: set to Non-conversational for now + contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL); + return contract; + } + + /** + * @see org.apache.tuscany.idl.wsdl.InterfaceWSDLIntrospector#introspect(javax.wsdl.PortType, javax.wsdl.PortType) + */ + public WSDLServiceContract introspect(PortType portType, PortType callbackPortType) + throws InvalidServiceContractException { + assert portType != null : "PortType cannot be null"; + WSDLServiceContract contract = new WSDLServiceContract(); + // FIXME: set to Non-conversational for now + contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL); + contract.setPortType(portType); + contract.setInterfaceName(portType.getQName().getLocalPart()); + contract.setOperations(introspectOperations(portType)); + if (callbackPortType != null) { + contract.setCallbackPortType(callbackPortType); + contract.setCallbackName(callbackPortType.getQName().getLocalPart()); + contract.setCallbackOperations(introspectOperations(callbackPortType)); + } + return contract; + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLLoader.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLLoader.java new file mode 100644 index 0000000000..8ebf086091 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InterfaceWSDLLoader.java @@ -0,0 +1,146 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.wsdl.PortType; +import javax.wsdl.WSDLException; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Constants.SCA_NS; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.ModelObject; + +/** + * Loads a WSDL interface definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class InterfaceWSDLLoader extends LoaderExtension { + public static final QName INTERFACE_WSDL = new QName(SCA_NS, "interface.wsdl"); + + private static final String WSDLI = "http://www.w3.org/2006/01/wsdl-instance"; + + private static final String WSDLI_LOCATION = "wsdlLocation"; + + private WSDLDefinitionRegistry wsdlRegistry; + + private InterfaceWSDLIntrospector introspector; + + @Constructor({"registry", "wsdlRegistry", "introspector"}) + public InterfaceWSDLLoader(@Autowire LoaderRegistry registry, + @Autowire WSDLDefinitionRegistry wsdlRegistry, + @Autowire InterfaceWSDLIntrospector introspector) { + super(registry); + this.wsdlRegistry = wsdlRegistry; + this.introspector = introspector; + } + + public QName getXMLType() { + return INTERFACE_WSDL; + } + + public WSDLServiceContract load( + CompositeComponent parent, + ModelObject object, XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert INTERFACE_WSDL.equals(reader.getName()); + + String interfaceURI = reader.getAttributeValue(null, "interface"); + if (interfaceURI == null) { + throw new InvalidValueException("interface"); + } + + String callbackURI = reader.getAttributeValue(null, "callbackInterface"); + String wsdlLocation = reader.getAttributeValue(WSDLI, WSDLI_LOCATION); + + Map<Class<?>, ModelObject> extensions = new HashMap<Class<?>, ModelObject>(); + while (true) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + ModelObject mo = registry.load(parent, null, reader, deploymentContext); + if (mo != null) { + extensions.put(mo.getClass(), mo); + } + } else if (event == XMLStreamConstants.END_ELEMENT) { + if (reader.getName().equals(INTERFACE_WSDL)) { + break; + } + } + } + // FIXME set the interaction scope + // serviceContract.setInteractionScope(StAXUtil.interactionScope(reader.getAttributeValue(null, "scope"))); + + if (wsdlLocation != null) { + try { + wsdlRegistry.loadDefinition(wsdlLocation, deploymentContext.getClassLoader()); + } catch (IOException e) { + throw new LoaderException(wsdlLocation, e); + } catch (WSDLException e) { + throw new LoaderException(wsdlLocation, e); + } + } + + PortType portType = getPortType(interfaceURI); + if (portType == null) { + throw new MissingResourceException(interfaceURI); + } + PortType callback = null; + if (callbackURI != null) { + callback = getPortType(callbackURI); + } + try { + WSDLServiceContract contract = introspector.introspect(portType, callback); + DataType<?> dataType = (DataType<?>) extensions.get(DataType.class); + if (dataType != null) { + contract.setDataBinding(dataType.getDataBinding()); + } + contract.getExtensions().putAll(extensions); + return contract; + } catch (InvalidServiceContractException e) { + throw new LoaderException(wsdlLocation, e); + } + } + + protected PortType getPortType(String uri) { + // Syntax: <WSDL-namespace-URI>#wsdl.interface(<portTypeOrInterface-name>) + int index = uri.indexOf('#'); + String namespace = uri.substring(0, index); + String name = uri.substring(index + 1); + name = name.substring("wsdl.interface(".length(), name.length() - 1); + QName qname = new QName(namespace, name); + return wsdlRegistry.getPortType(qname); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidFragmentException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidFragmentException.java new file mode 100644 index 0000000000..a629ff4fbb --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidFragmentException.java @@ -0,0 +1,30 @@ +/* + * 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.idl.wsdl; + +/** + * @version $Rev$ $Date$ + */ +public class InvalidFragmentException extends WSDLLoaderException { + + public InvalidFragmentException(String message) { + super(message); + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLContributionException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLContributionException.java new file mode 100644 index 0000000000..dedcf352ef --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLContributionException.java @@ -0,0 +1,36 @@ +/*
+ * 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.idl.wsdl;
+
+import org.apache.tuscany.host.deployment.DeploymentException;
+
+/**
+ * Exception that indicates that the supplied XML Document invalid.
+ *
+ */
+public class InvalidWSDLContributionException extends DeploymentException {
+
+ protected InvalidWSDLContributionException(String componentDefinitionLocatoin) {
+ super(componentDefinitionLocatoin);
+ }
+
+ protected InvalidWSDLContributionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLException.java new file mode 100644 index 0000000000..a22ab92863 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLException.java @@ -0,0 +1,34 @@ +/* + * 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.idl.wsdl; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; + +/** + * An exception to indicate the WSDL definition is invalid + * + * @version $Rev$ $Date$ + */ +public class InvalidWSDLException extends InvalidServiceContractException { + + public InvalidWSDLException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLLocationException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLLocationException.java new file mode 100644 index 0000000000..b2d77bf52f --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/InvalidWSDLLocationException.java @@ -0,0 +1,33 @@ +/* + * 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.idl.wsdl; + +/** + * @version $Rev$ $Date$ + */ +public class InvalidWSDLLocationException extends WSDLLoaderException { + + public InvalidWSDLLocationException(String message) { + super(message); + } + + public InvalidWSDLLocationException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/NotSupportedWSDLException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/NotSupportedWSDLException.java new file mode 100644 index 0000000000..04cea4cefd --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/NotSupportedWSDLException.java @@ -0,0 +1,37 @@ +/* + * 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.idl.wsdl; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; + +/** + * An exception to indicate some WSDL styles that we don't support + * + * @version $Rev$ $Date$ + */ +public class NotSupportedWSDLException extends InvalidServiceContractException { + + public NotSupportedWSDLException(String message) { + super(message); + } + + public NotSupportedWSDLException(String message, String identifier) { + super(message, identifier); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/UnresolveableResourceException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/UnresolveableResourceException.java new file mode 100644 index 0000000000..afb4ed3d40 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/UnresolveableResourceException.java @@ -0,0 +1,34 @@ +/* + * 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.idl.wsdl; + +/** + * @version $Rev$ $Date$ + */ +public class UnresolveableResourceException extends WSDLLoaderException { + + public UnresolveableResourceException(String message) { + super(message); + } + + public UnresolveableResourceException(String message, String identifier) { + super(message, identifier); + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLContributionProcessor.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLContributionProcessor.java new file mode 100644 index 0000000000..e438cd37cf --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLContributionProcessor.java @@ -0,0 +1,263 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.wsdl.Definition; +import javax.wsdl.Import; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensionRegistry; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLLocator; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.ArtifactResolverRegistry; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; +import org.xml.sax.InputSource; + +/** + * The WSDL processor + * @version $Rev$ $Date$ + */ +public class WSDLContributionProcessor extends ContributionProcessorExtension { + + private final WSDLFactory wsdlFactory; + + private final ExtensionRegistry extensionRegistry; + + private final Map<String, List<Definition>> definitionsByNamespace = new HashMap<String, List<Definition>>(); + + private Monitor monitor; + + private XMLSchemaRegistry schemaRegistry; + + private ArtifactResolverRegistry artifactResolverRegistry; + + public WSDLContributionProcessor() throws WSDLException { + wsdlFactory = WSDLFactory.newInstance(); + extensionRegistry = wsdlFactory.newPopulatedExtensionRegistry(); + } + + @Autowire + public void setSchemaRegistry(XMLSchemaRegistry schemaRegistry) { + this.schemaRegistry = schemaRegistry; + } + + @org.apache.tuscany.api.annotation.Monitor + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + public ExtensionRegistry getExtensionRegistry() { + return extensionRegistry; + } + + @SuppressWarnings("unchecked") + public Definition loadDefinition(Contribution contribution, String namespace, URI location, InputStream inputStream) + throws IOException, WSDLException, DeploymentException { + if (monitor != null) { + monitor.readingWSDL(namespace, location); + } + + WSDLReader reader = wsdlFactory.newWSDLReader(); + reader.setFeature("javax.wsdl.verbose", false); + reader.setExtensionRegistry(extensionRegistry); + + WSDLLocatorImpl locator = new WSDLLocatorImpl(contribution, location, inputStream); + Definition definition = reader.readWSDL(locator); + String definitionNamespace = definition.getTargetNamespace(); + if (namespace != null && !namespace.equals(definitionNamespace)) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, namespace + " != " + + definition.getTargetNamespace()); + } + + // Load inline schemas + registry.processModel(contribution, location, definition); + for (Object i : definition.getImports().values()) { + List<Import> imps = (List<Import>)i; + for (Import imp : imps) { + Definition imported = imp.getDefinition(); + if (imported != null) { + // TODO: + registry.processModel(contribution, URI.create(imp.getDefinition().getDocumentBaseURI()), definition); + } + } + } + + if (monitor != null) { + monitor.cachingDefinition(definitionNamespace, location); + } + List<Definition> definitions = definitionsByNamespace.get(definitionNamespace); + if (definitions == null) { + definitions = new ArrayList<Definition>(); + definitionsByNamespace.put(definitionNamespace, definitions); + } + definitions.add(definition); + + DeployedArtifact artifact = contribution.getArtifact(location); + artifact.addModelObject(Definition.class, definition.getTargetNamespace(), definition); + + return definition; + } + + public PortType getPortType(QName name) { + String namespace = name.getNamespaceURI(); + List<Definition> definitions = definitionsByNamespace.get(namespace); + if (definitions == null) { + return null; + } + for (Definition definition : definitions) { + PortType portType = definition.getPortType(name); + if (portType != null) { + return portType; + } + } + return null; + } + + public Service getService(QName name) { + String namespace = name.getNamespaceURI(); + List<Definition> definitions = definitionsByNamespace.get(namespace); + if (definitions == null) { + return null; + } + for (Definition definition : definitions) { + Service service = definition.getService(name); + if (service != null) { + return service; + } + } + return null; + } + + public static interface Monitor { + /** + * Monitor event emitted immediately before an attempt is made to read + * WSDL for the supplied namespace from the supplied location. + * + * @param namespace the target namespace expected in the WSDL; may be + * null + * @param location the location where we will attempt to read the WSDL + * definition from + */ + void readingWSDL(String namespace, URI location); + + /** + * Monitor event emitted immediately before registering a WSDL + * definition in the cache. + * + * @param namespace the target namespace for the WSDL + * @param location the location where the WSDL definition was read from + */ + void cachingDefinition(String namespace, URI location); + } + + public XMLSchemaRegistry getSchemaRegistry() { + if (schemaRegistry == null) { + // Default + schemaRegistry = new XMLSchemaRegistryImpl(); + } + return schemaRegistry; + } + + public class WSDLLocatorImpl implements WSDLLocator { + private Contribution contribution; + private InputStream inputStream; + private String baseURI; + private URI latestImportURI; + + public WSDLLocatorImpl(Contribution contribution, URI baseURI, InputStream is) { + this.contribution = contribution; + this.baseURI = baseURI.toString(); + this.inputStream = is; + } + + public void close() { + // inputStream.close(); + } + + public InputSource getBaseInputSource() { + return new InputSource(inputStream); + } + + public String getBaseURI() { + return baseURI; + } + + public InputSource getImportInputSource(String parentLocation, String importLocation) { + try { + URL url = artifactResolverRegistry.resolve(contribution, null, importLocation, parentLocation); + latestImportURI = url.toURI(); + return new InputSource(url.openStream()); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public String getLatestImportURI() { + return latestImportURI.toString(); + } + + } + + public String getContentType() { + return "application/vnd.tuscany.wsdl"; + } + + /** + * @param artifactResolverRegistry the artifactResolverRegistry to set + */ + @Autowire + public void setArtifactResolverRegistry(ArtifactResolverRegistry artifactResolverRegistry) { + this.artifactResolverRegistry = artifactResolverRegistry; + } + + public void processContent(Contribution contribution, URI source, InputStream inputStream) + throws DeploymentException, IOException { + try { + loadDefinition(contribution, null, source, inputStream); + } catch (WSDLException e) { + throw new InvalidWSDLContributionException(contribution.getArtifact(source).getLocation().toExternalForm(), e); + } + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + // TODO Auto-generated method stub + + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistry.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistry.java new file mode 100644 index 0000000000..f7fd7de5ae --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.net.URL; +import javax.wsdl.Definition; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensionRegistry; +import javax.xml.namespace.QName; + +/** + * A service for caching WSDLs + * + * @version $Rev$ $Date$ + */ +@Deprecated +public interface WSDLDefinitionRegistry { + /** + * Loads and registers a WSDL Definition. + * + * @param namespace the expected namespace, or null if any namespace should be allowed + * @param location the location to load the definition from + * @return the loaded Definition + * @throws IOException if there was a problem reading the document + * @throws WSDLException if there was a problem parsing the definition + */ + Definition loadDefinition(String namespace, URL location) throws IOException, WSDLException; + + /** + * Load and register a WSDL definition as specified in a WSDL2.0 wsdlLocation attribute. + * + * @param wsdlLocation the value of the wsdlLocation attribute + * @param classLoader application classloader used to support relative locations + * @return the loaded Definition + * @throws IOException if there was a problem reading the document + * @throws WSDLException if there was a problem parsing the definition + */ + Definition loadDefinition(String wsdlLocation, ClassLoader classLoader) throws IOException, WSDLException; + + /** + * Returns the PortType with the supplied qualified name, or null if no such port has been defined. + * + * @param name the qualified name of the WSDL portType + * @return the PortType for the supplied name, or null if none has been defined + */ + PortType getPortType(QName name); + + /** + * Returns the ServiceDefinition with the supplied qualified name, or null if no such service has been defined. + * + * @param name the qualified name of the WSDL service + * @return the ServiceDefinition for the supplied name, or null if none has been defined + */ + Service getService(QName name); + + + /** + * Returns the ExtensionRegistry that is used when parsing WSDL documents during the loadDefinition call. + * + * @return the ExtensionRegistry that is used when parsing WSDL documents. + */ + ExtensionRegistry getExtensionRegistry(); + + /** + * Get the XMLSchemaRegistry + * + * @return + */ + XMLSchemaRegistry getSchemaRegistry(); + + Definition getDefinition(String wsdlNamespace); +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistryImpl.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistryImpl.java new file mode 100644 index 0000000000..de0accd459 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLDefinitionRegistryImpl.java @@ -0,0 +1,214 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.wsdl.Definition; +import javax.wsdl.Import; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensionRegistry; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; + +/** + * The default implementation of the runtime WSDL registry + * + * @version $Rev$ $Date$ + */ +public class WSDLDefinitionRegistryImpl implements WSDLDefinitionRegistry { + private final WSDLFactory wsdlFactory; + + private final ExtensionRegistry registry; + + private final Map<URL, Definition> definitionsByLocation = new HashMap<URL, Definition>(); + + private final Map<String, List<Definition>> definitionsByNamespace = new HashMap<String, List<Definition>>(); + + private Monitor monitor; + + private XMLSchemaRegistry schemaRegistry; + + public WSDLDefinitionRegistryImpl() throws WSDLException { + wsdlFactory = WSDLFactory.newInstance(); + registry = wsdlFactory.newPopulatedExtensionRegistry(); + } + + @Autowire + public void setSchemaRegistry(XMLSchemaRegistry schemaRegistry) { + this.schemaRegistry = schemaRegistry; + } + + @org.apache.tuscany.api.annotation.Monitor + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + public ExtensionRegistry getExtensionRegistry() { + return registry; + } + + public Definition loadDefinition(String wsdlLocation, ClassLoader classLoader) throws IOException, WSDLException { + int index = wsdlLocation.indexOf(' '); + if (index == -1) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, "Invalid wsdlLocation: " + wsdlLocation); + } + String namespace = wsdlLocation.substring(0, index).trim(); + URL url; + URI uri; + try { + uri = new URI(wsdlLocation.substring(index + 1).trim()); + } catch (URISyntaxException e) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, "Invalid wsdlLocation: " + wsdlLocation); + } + if (uri.isAbsolute()) { + url = uri.toURL(); + } else { + url = classLoader.getResource(uri.toString()); + if (url == null) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, "Resource not found: " + uri); + } + } + return loadDefinition(namespace, url); + } + + public Definition loadDefinition(String namespace, URL location) throws IOException, WSDLException { + Definition definition = definitionsByLocation.get(location); + if (definition != null) { + // return cached copy + return definition; + } + + if (monitor != null) { + monitor.readingWSDL(namespace, location); + } + WSDLReader reader = wsdlFactory.newWSDLReader(); + reader.setFeature("javax.wsdl.verbose", false); + reader.setExtensionRegistry(registry); + + definition = reader.readWSDL(location.toString()); + String definitionNamespace = definition.getTargetNamespace(); + if (namespace != null && !namespace.equals(definitionNamespace)) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, namespace + " != " + + definition.getTargetNamespace()); + } + + // Load inline schemas + getSchemaRegistry().loadSchemas(definition); + for (Object i : definition.getImports().values()) { + Import imp = (Import) i; + Definition imported = imp.getDefinition(); + if (imported != null) { + getSchemaRegistry().loadSchemas(imported); + } + } + + if (monitor != null) { + monitor.cachingDefinition(definitionNamespace, location); + } + definitionsByLocation.put(location, definition); + List<Definition> definitions = definitionsByNamespace.get(definitionNamespace); + if (definitions == null) { + definitions = new ArrayList<Definition>(); + definitionsByNamespace.put(definitionNamespace, definitions); + } + definitions.add(definition); + + return definition; + } + + public PortType getPortType(QName name) { + String namespace = name.getNamespaceURI(); + List<Definition> definitions = definitionsByNamespace.get(namespace); + if (definitions == null) { + return null; + } + for (Definition definition : definitions) { + PortType portType = definition.getPortType(name); + if (portType != null) { + return portType; + } + } + return null; + } + + public Service getService(QName name) { + String namespace = name.getNamespaceURI(); + List<Definition> definitions = definitionsByNamespace.get(namespace); + if (definitions == null) { + return null; + } + for (Definition definition : definitions) { + Service service = definition.getService(name); + if (service != null) { + return service; + } + } + return null; + } + + public static interface Monitor { + /** + * Monitor event emitted immediately before an attempt is made to read WSDL for the supplied namespace from the + * supplied location. + * + * @param namespace the target namespace expected in the WSDL; may be null + * @param location the location where we will attempt to read the WSDL definition from + */ + void readingWSDL(String namespace, URL location); + + /** + * Monitor event emitted immediately before registering a WSDL definition in the cache. + * + * @param namespace the target namespace for the WSDL + * @param location the location where the WSDL definition was read from + */ + void cachingDefinition(String namespace, URL location); + } + + public XMLSchemaRegistry getSchemaRegistry() { + if (schemaRegistry == null) { + // Default + schemaRegistry = new XMLSchemaRegistryImpl(); + } + return schemaRegistry; + } + + public Definition getDefinition(String wsdlNamespace) { + List<Definition> definitions = definitionsByNamespace.get(wsdlNamespace); + if (definitions == null || definitions.size() < 1) { + return null; + } else { + return definitions.get(0); + } + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoader.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoader.java new file mode 100644 index 0000000000..fb90e839f5 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoader.java @@ -0,0 +1,110 @@ +/* + * 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.idl.wsdl; + +import java.net.URI; +import java.util.Collection; +import javax.wsdl.Definition; +import javax.wsdl.PortType; +import javax.wsdl.WSDLException; +import javax.xml.namespace.QName; + +/** + * Interface for implementations that allow WSDL definitions to be loaded. Currently we do not have a complete solution + * for handling both WSDL2.0 and WSDL1.1 definitions so the current implementation only deals with loading WSDL1.1. This + * will change in the near future (for example when Woden supports both forms) so all WSDL1.1 specific methods are + * deprecated. + * + * @version $Rev$ $Date$ + */ +public interface WSDLLoader { + /** + * Load a WSDL 1.1 Definition for a namespace from one of specified locations. + * + * @param namespace the namespace whose definition should be loaded + * @param locations a set of possible locations to load from + * @return the loaded Definition + * @throws WSDLException if there was a problem loading the definition + */ + @Deprecated + Definition loadDefinition(String namespace, Collection<WSDLLocation> locations) + throws WSDLException, UnresolveableResourceException; + + /** + * Load a WSDL 1.1 Definition from the specified location + * + * @param location the location to load from + * @return the loaded Definition + * @throws WSDLException if there was a problem loading the definition + */ + @Deprecated + Definition loadDefinition(WSDLLocation location) throws WSDLException; + + /** + * Return the WSDL1.1 PortType for the specified interface IRI. + * + * @param interfaceIRI the WSDL2.0 interface IRI + * @param wsdlLocation the location of the WSDL instance + * @param base a Classloader from which to load + * @return the specified port type + */ + @Deprecated + PortType loadPortType(URI interfaceIRI, String wsdlLocation, ClassLoader base) + throws WSDLLoaderException, WSDLException; + + /** + * Parses a WSDL2.0 wsdlLocation attribute definition and returns a Collection of all locations it contains. + * + * @param wsdlLocation a list of namespace/location pairs as specified by WSDL2.0 + * @param base a ClassLoader to use to resolve relative URLs + * @return a collection of locations parsed from the string + * @throws InvalidWSDLLocationException + */ + Collection<WSDLLocation> getLocations(String wsdlLocation, ClassLoader base) throws InvalidWSDLLocationException; + + /** + * Returns the fully qualified name of a WSDL interface parsed from a IRI as defined by WSDL2.0. The value of the + * IRI defines the namespace, the fragment specifies the interface component; for example + * <code>http://example.org/TicketAgent.wsdl20#wsdl.interface(TicketAgent)</code> + * + * @param interfaceIRI the IRI for the interface + * @return the qualified name of the interface + * @throws UnresolveableResourceException if the URI is relative + * @throws InvalidFragmentException if the fragment is incorrectly formed + */ + QName getInterfaceName(URI interfaceIRI) throws UnresolveableResourceException, InvalidFragmentException; + + /** + * Returns an interface parsed from a wsdl.interface fragment. + * + * @param fragment the fragment value + * @return the interface name + * @throws InvalidFragmentException if the fragment is incorrectly formed + */ + String getInterfaceName(String fragment) throws InvalidFragmentException; + + /** + * Returns a namespace parsed from an IRI. This is the URI with any fragment removed. + * + * @param iri the IRI + * @return a namespace created by stripping fragment information from the URI + * @throws UnresolveableResourceException if the URI is relative + */ + String getNamespace(URI iri) throws UnresolveableResourceException; +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderException.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderException.java new file mode 100644 index 0000000000..1fececa62c --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderException.java @@ -0,0 +1,45 @@ +/* + * 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.idl.wsdl; + +import org.apache.tuscany.api.TuscanyException; + +/** + * @version $Rev$ $Date$ + */ +public abstract class WSDLLoaderException extends TuscanyException { + protected WSDLLoaderException() { + } + + protected WSDLLoaderException(String message) { + super(message); + } + + protected WSDLLoaderException(String message, String identifier) { + super(message, identifier); + } + + protected WSDLLoaderException(String message, Throwable cause) { + super(message, cause); + } + + protected WSDLLoaderException(Throwable cause) { + super(cause); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderImpl.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderImpl.java new file mode 100644 index 0000000000..ebf8cafedc --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLoaderImpl.java @@ -0,0 +1,141 @@ +/* + * 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.idl.wsdl; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.wsdl.Definition; +import javax.wsdl.PortType; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensionRegistry; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +/** + * @version $Rev$ $Date$ + */ +public class WSDLLoaderImpl implements WSDLLoader { + private final WSDLFactory wsdlFactory; + + private final ExtensionRegistry registry; + + public WSDLLoaderImpl() throws WSDLException { + wsdlFactory = WSDLFactory.newInstance(); + registry = wsdlFactory.newPopulatedExtensionRegistry(); + } + + public PortType loadPortType(URI interfaceIRI, String wsdlLocation, ClassLoader base) + throws WSDLLoaderException, WSDLException { + Collection<WSDLLocation> locations = getLocations(wsdlLocation, base); + QName interfaceName = getInterfaceName(interfaceIRI); + + Definition definition = loadDefinition(interfaceName.getNamespaceURI(), locations); + return definition.getPortType(interfaceName); + } + + public Definition loadDefinition(String namespace, Collection<WSDLLocation> locations) + throws WSDLException, UnresolveableResourceException { + for (WSDLLocation location : locations) { + if (namespace.equals(location.getNamespace()) && location.getLocation() != null) { + return loadDefinition(location); + } + } + throw new UnresolveableResourceException(namespace); + } + + public Definition loadDefinition(WSDLLocation location) throws WSDLException { + String namespace = location.getNamespace(); + + WSDLReader reader = wsdlFactory.newWSDLReader(); + reader.setFeature("javax.wsdl.verbose", false); + reader.setExtensionRegistry(registry); + + Definition definition = reader.readWSDL(location.getLocation().toString()); + String definitionNamespace = definition.getTargetNamespace(); + if (namespace != null && !namespace.equals(definitionNamespace)) { + throw new WSDLException(WSDLException.CONFIGURATION_ERROR, namespace + " != " + + definition.getTargetNamespace()); + } + return definition; + } + + public Collection<WSDLLocation> getLocations(String wsdlLocation, ClassLoader base) + throws InvalidWSDLLocationException { + String parts[] = wsdlLocation.split("\\s"); + // check the number of parts is a multiple of two + if ((parts.length & 1) != 0) { + throw new InvalidWSDLLocationException(wsdlLocation); + } + List<WSDLLocation> locations = new ArrayList<WSDLLocation>(parts.length >>> 1); + for (int i = 0; i < parts.length; i += 2) { + URL url; + try { + URI uri = new URI(parts[i + 1]); + if (uri.isAbsolute()) { + url = uri.toURL(); + } else { + url = base.getResource(uri.toString()); + } + } catch (MalformedURLException e) { + throw new InvalidWSDLLocationException(e); + } catch (URISyntaxException e) { + throw new InvalidWSDLLocationException(e); + } + WSDLLocation location = new WSDLLocation(parts[i], url); + locations.add(location); + } + return locations; + } + + public QName getInterfaceName(URI interfaceIRI) throws UnresolveableResourceException, InvalidFragmentException { + String namespace = getNamespace(interfaceIRI); + String interfaceName = getInterfaceName(interfaceIRI.getFragment()); + return new QName(namespace, interfaceName); + } + + public String getInterfaceName(String fragment) throws InvalidFragmentException { + if (fragment == null) { + throw new InvalidFragmentException("missing fragment"); + } + String[] parts = fragment.split("\\s"); + for (String part : parts) { + if (part.startsWith("wsdl.interface(") && part.charAt(part.length() - 1) == ')') { + return part.substring(15, part.length() - 1); + } + } + throw new InvalidFragmentException(fragment); + } + + public String getNamespace(URI iri) throws UnresolveableResourceException { + if (!iri.isAbsolute()) { + throw new UnresolveableResourceException("No namespace defined in", iri.toString()); + } + StringBuilder s = new StringBuilder(); + s.append(iri.getScheme()); + s.append(':'); + s.append(iri.getSchemeSpecificPart()); + return s.toString(); + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLocation.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLocation.java new file mode 100644 index 0000000000..a124294c3a --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLLocation.java @@ -0,0 +1,60 @@ +/* + * 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.idl.wsdl; + +import java.net.URL; + +/** + * A location where the WSDL for a namespace can be found. + * + * @version $Rev$ $Date$ + */ +public class WSDLLocation { + private final String namespace; + private final URL location; + + /** + * Constructor specifying a namespace and where its WSDL can be found. + * + * @param namespace the target namespace + * @param location the location of the WSDL + */ + public WSDLLocation(String namespace, URL location) { + this.namespace = namespace; + this.location = location; + } + + /** + * Returns the target namespace. + * + * @return the target namespace + */ + public String getNamespace() { + return namespace; + } + + /** + * Returns the location where the WSDL definition can be found. + * + * @return the location where the WSDL definition can be found + */ + public URL getLocation() { + return location; + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLOperation.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLOperation.java new file mode 100644 index 0000000000..2cc501ac9e --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLOperation.java @@ -0,0 +1,525 @@ +/* + * 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.idl.wsdl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.wsdl.Fault; +import javax.wsdl.Input; +import javax.wsdl.Message; +import javax.wsdl.Operation; +import javax.wsdl.Output; +import javax.wsdl.Part; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.ServiceFaultException; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.WrapperInfo; +import org.apache.tuscany.spi.model.DataType; + +import org.apache.ws.commons.schema.XmlSchemaComplexType; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaObject; +import org.apache.ws.commons.schema.XmlSchemaObjectCollection; +import org.apache.ws.commons.schema.XmlSchemaParticle; +import org.apache.ws.commons.schema.XmlSchemaSequence; +import org.apache.ws.commons.schema.XmlSchemaSimpleType; +import org.apache.ws.commons.schema.XmlSchemaType; + +/** + * Metadata for a WSDL operation + * + * @version $Rev$ $Date$ + */ +public class WSDLOperation { + protected XMLSchemaRegistry schemaRegistry; + protected Operation operation; + protected org.apache.tuscany.spi.model.Operation<XMLType> operationModel; + protected DataType<List<DataType<XMLType>>> inputType; + protected DataType<XMLType> outputType; + protected List<DataType<XMLType>> faultTypes; + private String dataBinding; + + /** + * @param operation The WSDL4J operation + * @param dataBinding The default databinding + * @param schemaRegistry The XML Schema registry + */ + public WSDLOperation(Operation operation, String dataBinding, XMLSchemaRegistry schemaRegistry) { + super(); + this.operation = operation; + this.dataBinding = dataBinding; + this.schemaRegistry = schemaRegistry; + this.wrapper = new Wrapper(); + } + + private Wrapper wrapper; + + private Boolean wrapperStyle; + + /** + * Test if the operation qualifies wrapper style as defined by the JAX-WS + * 2.0 spec + * + * @return true if the operation qualifies wrapper style, otherwise false + */ + public boolean isWrapperStyle() throws InvalidWSDLException { + if (wrapperStyle == null) { + wrapperStyle = + wrapper.getInputChildElements() != null && (operation.getOutput() == null || wrapper + .getOutputChildElements() != null); + } + return wrapperStyle; + } + + public Wrapper getWrapper() throws InvalidWSDLException { + if (!isWrapperStyle()) { + throw new IllegalStateException("The operation is not wrapper style."); + } else { + return wrapper; + } + } + + /** + * @return + * @throws InvalidServiceContractException + */ + public DataType<List<DataType<XMLType>>> getInputType() throws InvalidServiceContractException { + if (inputType == null) { + Input input = operation.getInput(); + Message message = (input == null) ? null : input.getMessage(); + inputType = getMessageType(message); + inputType.setDataBinding(DataBinding.IDL_INPUT); + } + return inputType; + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + public DataType<XMLType> getOutputType() throws InvalidServiceContractException { + if (outputType == null) { + Output output = operation.getOutput(); + Message outputMsg = (output == null) ? null : output.getMessage(); + + List outputParts = (outputMsg == null) ? null : outputMsg.getOrderedParts(null); + if (outputParts != null && outputParts.size() > 0) { + if (outputParts.size() > 1) { + // We don't support output with multiple parts + throw new NotSupportedWSDLException("Multi-part output is not supported"); + } + Part part = (Part)outputParts.get(0); + outputType = new WSDLPart(part, Object.class).getDataType(); + // outputType.setMetadata(WSDLOperation.class.getName(), this); + } + } + return outputType; + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + public List<DataType<XMLType>> getFaultTypes() throws InvalidServiceContractException { + if (faultTypes == null) { + Collection faults = operation.getFaults().values(); + faultTypes = new ArrayList<DataType<XMLType>>(); + for (Object f : faults) { + Fault fault = (Fault)f; + Message faultMsg = fault.getMessage(); + List faultParts = faultMsg.getOrderedParts(null); + if (faultParts.size() != 1) { + throw new NotSupportedWSDLException("The fault message MUST have a single part"); + } + Part part = (Part)faultParts.get(0); + WSDLPart wsdlPart = new WSDLPart(part, ServiceFaultException.class); + faultTypes.add(wsdlPart.getDataType()); + } + } + return faultTypes; + } + + private DataType<List<DataType<XMLType>>> getMessageType(Message message) throws InvalidServiceContractException { + List<DataType<XMLType>> partTypes = new ArrayList<DataType<XMLType>>(); + if (message != null) { + Collection parts = message.getOrderedParts(null); + for (Object p : parts) { + WSDLPart part = new WSDLPart((Part)p, Object.class); + DataType<XMLType> partType = part.getDataType(); + partTypes.add(partType); + } + } + return new DataType<List<DataType<XMLType>>>(dataBinding, Object[].class, partTypes); + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + public org.apache.tuscany.spi.model.Operation<XMLType> getOperation() throws InvalidServiceContractException { + if (operationModel == null) { + boolean oneway = (operation.getOutput() == null); + operationModel = + new org.apache.tuscany.spi.model.Operation<XMLType>( + operation.getName(), + getInputType(), + getOutputType(), + getFaultTypes(), + oneway, + dataBinding, + org.apache.tuscany.spi.model.Operation.NO_CONVERSATION); + operationModel.setWrapperStyle(isWrapperStyle()); + // operationModel.setMetaData(WSDLOperation.class.getName(), this); + if (isWrapperStyle()) { + WrapperInfo wrapperInfo = getWrapper().getWrapperInfo(); + operationModel.setWrapper(wrapperInfo); + // Register the operation with the types + for (DataType<?> d : wrapperInfo.getUnwrappedInputType().getLogical()) { + d.setOperation(operationModel); + } + if (wrapperInfo.getUnwrappedOutputType() != null) { + wrapperInfo.getUnwrappedOutputType().setOperation(operationModel); + } + } + } + inputType.setOperation(operationModel); + if (outputType != null) { + outputType.setOperation(operationModel); + } + return operationModel; + } + + /** + * Metadata for a WSDL part + */ + public class WSDLPart { + private Part part; + + private XmlSchemaElement element; + + private DataType<XMLType> dataType; + + public WSDLPart(Part part, Class javaType) throws InvalidWSDLException { + this.part = part; + QName elementName = part.getElementName(); + if (elementName != null) { + element = schemaRegistry.getElement(elementName); + if (element == null) { + throw new InvalidWSDLException("Element cannot be resolved", elementName.toString()); + } + } else { + // Create an faked XSD element to host the metadata + element = new XmlSchemaElement(); + element.setName(part.getName()); + element.setQName(new QName(null, part.getName())); + QName typeName = part.getTypeName(); + if (typeName != null) { + XmlSchemaType type = schemaRegistry.getType(typeName); + if (type == null) { + throw new InvalidWSDLException("Type cannot be resolved", typeName.toString()); + } + element.setSchemaType(type); + element.setSchemaTypeName(type.getQName()); + } + } + dataType = new DataType<XMLType>(dataBinding, javaType, new XMLType(getElementInfo(element))); + // dataType.setMetadata(WSDLPart.class.getName(), this); + // dataType.setMetadata(ElementInfo.class.getName(), getElementInfo(element)); + } + + /** + * @return the element + */ + public XmlSchemaElement getElement() { + return element; + } + + /** + * @return the part + */ + public Part getPart() { + return part; + } + + /** + * @return the dataType + */ + public DataType<XMLType> getDataType() { + return dataType; + } + } + + /** + * The "Wrapper Style" WSDL operation is defined by The Java API for + * XML-Based Web Services (JAX-WS) 2.0 specification, section 2.3.1.2 + * Wrapper Style. <p/> A WSDL operation qualifies for wrapper style mapping + * only if the following criteria are met: + * <ul> + * <li>(i) The operation’s input and output messages (if present) each + * contain only a single part + * <li>(ii) The input message part refers to a global element declaration + * whose localname is equal to the operation name + * <li>(iii) The output message part refers to a global element declaration + * <li>(iv) The elements referred to by the input and output message parts + * (henceforth referred to as wrapper elements) are both complex types + * defined using the xsd:sequence compositor + * <li>(v) The wrapper elements only contain child elements, they must not + * contain other structures such as wildcards (element or attribute), + * xsd:choice, substitution groups (element references are not permitted) or + * attributes; furthermore, they must not be nillable. + * </ul> + */ + public class Wrapper { + private XmlSchemaElement inputWrapperElement; + + private XmlSchemaElement outputWrapperElement; + + private List<XmlSchemaElement> inputElements; + + private List<XmlSchemaElement> outputElements; + + private DataType<List<DataType<XMLType>>> unwrappedInputType; + + private DataType<XMLType> unwrappedOutputType; + + private transient WrapperInfo wrapperInfo; + + private List<XmlSchemaElement> getChildElements(XmlSchemaElement element) throws InvalidWSDLException { + if (element == null) { + return null; + } + if (element.isNillable()) { + // Wrapper element cannot be nillable + return null; + } + XmlSchemaType type = element.getSchemaType(); + if (type == null) { + String qName = element.getQName().toString(); + throw new InvalidWSDLException("The XML schema element does not have a type", qName); + } + if (!(type instanceof XmlSchemaComplexType)) { + // Has to be a complexType + return null; + } + XmlSchemaComplexType complexType = (XmlSchemaComplexType)type; + if (complexType.getAttributes().getCount() != 0 || complexType.getAnyAttribute() != null) { + // No attributes + return null; + } + XmlSchemaParticle particle = complexType.getParticle(); + if (particle == null) { + // No particle + return Collections.emptyList(); + } + if (!(particle instanceof XmlSchemaSequence)) { + return null; + } + XmlSchemaSequence sequence = (XmlSchemaSequence)complexType.getParticle(); + XmlSchemaObjectCollection items = sequence.getItems(); + List<XmlSchemaElement> childElements = new ArrayList<XmlSchemaElement>(); + for (int i = 0; i < items.getCount(); i++) { + XmlSchemaObject schemaObject = items.getItem(i); + if (!(schemaObject instanceof XmlSchemaElement)) { + return null; + } + XmlSchemaElement childElement = (XmlSchemaElement)schemaObject; + if (childElement.getName() == null || childElement.getRefName() != null) { + return null; + } + // TODO: Do we support maxOccurs >1 ? + if (childElement.getMaxOccurs() > 1) { + return null; + } + childElements.add(childElement); + } + return childElements; + } + + /** + * Return a list of child XSD elements under the wrapped request element + * + * @return a list of child XSD elements or null if if the request + * element is not wrapped + */ + public List<XmlSchemaElement> getInputChildElements() throws InvalidWSDLException { + if (inputElements != null) { + return inputElements; + } + Input input = operation.getInput(); + if (input != null) { + Message inputMsg = input.getMessage(); + Collection parts = inputMsg.getParts().values(); + if (parts.size() != 1) { + return null; + } + Part part = (Part)parts.iterator().next(); + QName elementName = part.getElementName(); + if (elementName == null) { + return null; + } + if (!operation.getName().equals(elementName.getLocalPart())) { + return null; + } + inputWrapperElement = schemaRegistry.getElement(elementName); + if (inputWrapperElement == null) { + throw new InvalidWSDLException("The element is not declared in a XML schema", elementName + .toString()); + } + inputElements = getChildElements(inputWrapperElement); + return inputElements; + } else { + return null; + } + } + + /** + * Return a list of child XSD elements under the wrapped response + * element + * + * @return a list of child XSD elements or null if if the response + * element is not wrapped + */ + public List<XmlSchemaElement> getOutputChildElements() throws InvalidWSDLException { + if (outputElements != null) { + return outputElements; + } + Output output = operation.getOutput(); + if (output != null) { + Message outputMsg = output.getMessage(); + Collection parts = outputMsg.getParts().values(); + if (parts.size() != 1) { + return null; + } + Part part = (Part)parts.iterator().next(); + QName elementName = part.getElementName(); + if (elementName == null) { + throw new InvalidWSDLException("The element is not declared in the XML schema", part.getName()); + } + outputWrapperElement = schemaRegistry.getElement(elementName); + if (outputWrapperElement == null) { + return null; + } + outputElements = getChildElements(outputWrapperElement); + // FIXME: Do we support multiple child elements for the + // response? + return outputElements; + } else { + return null; + } + } + + /** + * @return the inputWrapperElement + */ + public XmlSchemaElement getInputWrapperElement() { + return inputWrapperElement; + } + + /** + * @return the outputWrapperElement + */ + public XmlSchemaElement getOutputWrapperElement() { + return outputWrapperElement; + } + + /* + public DataType<List<DataType<XMLType>>> getUnwrappedInputType() throws InvalidWSDLException { + if (unwrappedInputType == null) { + List<DataType<XMLType>> childTypes = new ArrayList<DataType<XMLType>>(); + for (XmlSchemaElement element : getInputChildElements()) { + DataType<XMLType> type = + new DataType<XMLType>(dataBinding, Object.class, new XMLType(getElementInfo(element))); + // type.setMetadata(ElementInfo.class.getName(), getElementInfo(element)); + childTypes.add(type); + } + unwrappedInputType = + new DataType<List<DataType<XMLType>>>("idl:unwrapped.input", Object[].class, childTypes); + } + return unwrappedInputType; + } + + public DataType<XMLType> getUnwrappedOutputType() throws InvalidServiceContractException { + if (unwrappedOutputType == null) { + List<XmlSchemaElement> elements = getOutputChildElements(); + if (elements != null && elements.size() > 0) { + if (elements.size() > 1) { + // We don't support output with multiple parts + throw new NotSupportedWSDLException("Multi-part output is not supported"); + } + XmlSchemaElement element = elements.get(0); + unwrappedOutputType = + new DataType<XMLType>(dataBinding, Object.class, new XMLType(getElementInfo(element))); + // unwrappedOutputType.setMetadata(ElementInfo.class.getName(), getElementInfo(element)); + } + } + return unwrappedOutputType; + } + */ + + public WrapperInfo getWrapperInfo() throws InvalidServiceContractException { + if (wrapperInfo == null) { + ElementInfo in = getElementInfo(getInputWrapperElement()); + ElementInfo out = getElementInfo(getOutputWrapperElement()); + List<ElementInfo> inChildren = new ArrayList<ElementInfo>(); + for (XmlSchemaElement e : getInputChildElements()) { + inChildren.add(getElementInfo(e)); + } + List<ElementInfo> outChildren = new ArrayList<ElementInfo>(); + if (out != null) { + for (XmlSchemaElement e : getOutputChildElements()) { + outChildren.add(getElementInfo(e)); + } + } + wrapperInfo = + new WrapperInfo(dataBinding, in, out, inChildren, outChildren); + } + return wrapperInfo; + } + } + + private static ElementInfo getElementInfo(XmlSchemaElement element) { + if (element == null) { + return null; + } + return new ElementInfo(element.getQName(), getTypeInfo(element.getSchemaType())); + } + + private static TypeInfo getTypeInfo(XmlSchemaType type) { + if (type == null) { + return null; + } + XmlSchemaType baseType = (XmlSchemaType)type.getBaseSchemaType(); + QName name = type.getQName(); + boolean simple = (type instanceof XmlSchemaSimpleType); + if (baseType == null) { + return new TypeInfo(name, simple, null); + } else { + return new TypeInfo(name, simple, getTypeInfo(baseType)); + } + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLServiceContract.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLServiceContract.java new file mode 100644 index 0000000000..f498dc66ea --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/WSDLServiceContract.java @@ -0,0 +1,60 @@ +/* + * 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.idl.wsdl; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.idl.XMLType; +import org.apache.tuscany.spi.model.ServiceContract; + +/** + * Represents a service contract specified by a WSDL + * + * @version $Rev$ $Date$ + */ +public class WSDLServiceContract extends ServiceContract<XMLType> { + private PortType portType; + private PortType callbackPortType; + + /** + * + */ + public WSDLServiceContract() { + super(); + this.remotable = true; // WSDL interface is always remotable by the SCA spec + } + + + public PortType getPortType() { + return portType; + } + + public void setPortType(PortType portType) { + this.portType = portType; + } + + public PortType getCallbackPortType() { + return callbackPortType; + } + + public void setCallbackPortType(PortType callbackPortType) { + this.callbackPortType = callbackPortType; + } +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistry.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistry.java new file mode 100644 index 0000000000..681e08be4d --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistry.java @@ -0,0 +1,87 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import javax.wsdl.Definition; +import javax.xml.namespace.QName; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaException; +import org.apache.ws.commons.schema.XmlSchemaType; + +/** + * A service for caching XML Schemas + * + * @version $Rev$ $Date$ + */ +public interface XMLSchemaRegistry { + /** + * Load all inline schemas from the WSDL definition + * + * @param definition The WSDL defintion whose types element contains a list of schemas + * @return A list of inline schemas + */ + List<XmlSchema> loadSchemas(Definition definition); + + /** + * Loads and registers a XML schema. + * + * @param namespace the expected namespace, or null if any namespace should be allowed + * @param location the location to load the schema from + * @return the loaded Definition + * @throws IOException if there was a problem reading the document + * @throws XmlSchemaException if there was a problem parsing the schema + */ + XmlSchema loadSchema(String namespace, URL location) throws IOException, XmlSchemaException; + + /** + * Load and register a XML schema as specified in a XSD schemaLocation attribute. + * + * @param schemaLocation the value of the schemaLocation attribute + * @param classLoader application classloader used to support relative locations + * @return the loaded schema + * @throws IOException if there was a problem reading the document + * @throws XmlSchemaException if there was a problem parsing the schema + */ + XmlSchema loadSchema(String schemaLocation, ClassLoader classLoader) throws IOException, XmlSchemaException; + + /** + * Returns the XSD Element with the supplied qualified name, or null if no such element has been defined. + * + * @param name the qualified name of the XSD element + * @return the XSD element for the supplied name, or null if none has been defined + */ + XmlSchemaElement getElement(QName name); + + /** + * Returns the XmlSchemaType with the supplied qualified name, or null if no such type has been defined. + * + * @param name the qualified name of the XSD type + * @return the XSD type for the supplied name, or null if none has been defined + */ + XmlSchemaType getType(QName name); + + + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistryImpl.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistryImpl.java new file mode 100644 index 0000000000..08600e4b7e --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XMLSchemaRegistryImpl.java @@ -0,0 +1,129 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.wsdl.Definition; +import javax.wsdl.Types; +import javax.wsdl.extensions.schema.Schema; +import javax.xml.namespace.QName; + +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaException; +import org.apache.ws.commons.schema.XmlSchemaType; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Element; + +/** + * Default implementation of XMLSchemaRegistry + */ +@Service(XMLSchemaRegistry.class) +public class XMLSchemaRegistryImpl implements XMLSchemaRegistry { + private final XmlSchemaCollection collection; + + /** + * @param collection + */ + public XMLSchemaRegistryImpl(XmlSchemaCollection collection) { + super(); + this.collection = collection; + } + + public XMLSchemaRegistryImpl() { + super(); + this.collection = new XmlSchemaCollection(); + } + + public XmlSchemaElement getElement(QName name) { + return collection.getElementByQName(name); + } + + public XmlSchemaType getType(QName name) { + return collection.getTypeByQName(name); + } + + public List<XmlSchema> loadSchemas(Definition definition) { + Types types = definition.getTypes(); + if (types == null) { + return Collections.emptyList(); + } + List<XmlSchema> schemas = new ArrayList<XmlSchema>(); + for (Object ext : types.getExtensibilityElements()) { + if (ext instanceof Schema) { + Element element = ((Schema) ext).getElement(); + XmlSchema s = collection.read(element, element.getBaseURI()); + schemas.add(s); + } + } + return schemas; + } + + public XmlSchema loadSchema(String namespace, URL location) throws IOException, XmlSchemaException { + XmlSchema schema; + XmlSchema[] schemaList = collection.getXmlSchema(location.toExternalForm()); + if (schemaList != null && schemaList.length > 0) { + schema = schemaList[0]; + } else { + InputStream is = location.openStream(); + schema = collection.read(new InputStreamReader(is), null); + is.close(); + } + if (namespace != null && schema != null && !namespace.equals(schema.getTargetNamespace())) { + throw new XmlSchemaException(namespace + " != " + schema.getTargetNamespace()); + } + return schema; + } + + public XmlSchema loadSchema(String schemaLocation, ClassLoader classLoader) throws IOException, XmlSchemaException { + int index = schemaLocation.indexOf(' '); + if (index == -1) { + throw new XmlSchemaException("Invalid schemaLocation: " + schemaLocation); + } + String namespace = schemaLocation.substring(0, index).trim(); + URL url; + URI uri; + try { + uri = new URI(schemaLocation.substring(index + 1).trim()); + } catch (URISyntaxException e) { + throw new XmlSchemaException("Invalid schemaLocation: " + schemaLocation); + } + if (uri.isAbsolute()) { + url = uri.toURL(); + } else { + url = classLoader.getResource(uri.toString()); + if (url == null) { + throw new XmlSchemaException("Resource cannot be resolved: schemaLocation: " + schemaLocation); + } + } + return loadSchema(namespace, url); + } + +} diff --git a/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XSDContributionProcessor.java b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XSDContributionProcessor.java new file mode 100644 index 0000000000..43c5c05ea4 --- /dev/null +++ b/branches/sca-java-integration/sca/services/idl/wsdl/src/main/java/org/apache/tuscany/idl/wsdl/XSDContributionProcessor.java @@ -0,0 +1,136 @@ +/* + * 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.idl.wsdl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URL; + +import javax.wsdl.Definition; +import javax.wsdl.Types; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.schema.Schema; + +import org.apache.tuscany.host.deployment.DeploymentException; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.deployer.ArtifactResolverRegistry; +import org.apache.tuscany.spi.extension.ContributionProcessorExtension; +import org.apache.tuscany.spi.model.Contribution; +import org.apache.tuscany.spi.model.DeployedArtifact; +import org.apache.ws.commons.schema.XmlSchema; +import org.apache.ws.commons.schema.XmlSchemaCollection; +import org.apache.ws.commons.schema.XmlSchemaException; +import org.apache.ws.commons.schema.resolver.URIResolver; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; + +/** + * The XSD processor + * + * @version $Rev$ $Date$ + */ +public class XSDContributionProcessor extends ContributionProcessorExtension { + + private ArtifactResolverRegistry artifactResolverRegistry; + + public XSDContributionProcessor() throws WSDLException { + } + + /** + * URI resolver implementation for xml schema + */ + protected class URIResolverImpl implements URIResolver { + private Contribution contribution; + + public URIResolverImpl(Contribution contriution) { + this.contribution = contriution; + } + + public org.xml.sax.InputSource resolveEntity(java.lang.String targetNamespace, + java.lang.String schemaLocation, + java.lang.String baseUri) { + try { + URL url = artifactResolverRegistry.resolve(contribution, targetNamespace, schemaLocation, baseUri); + return new InputSource(url.openStream()); + } catch (IOException e) { + return null; + } + } + + } + + @SuppressWarnings("unchecked") + public XmlSchema loadSchema(Contribution contribution, String namespace, URI location, InputStream inputStream) + throws IOException, DeploymentException { + XmlSchemaCollection collection = new XmlSchemaCollection(); + collection.setSchemaResolver(new URIResolverImpl(contribution)); + XmlSchema schema = collection.read(new InputStreamReader(inputStream), null); + + if (namespace != null && schema != null && !namespace.equals(schema.getTargetNamespace())) { + throw new XmlSchemaException(namespace + " != " + schema.getTargetNamespace()); + } + + DeployedArtifact artifact = contribution.getArtifact(location); + artifact.addModelObject(XmlSchema.class, schema.getTargetNamespace(), schema); + return schema; + } + + public void loadSchemas(Contribution contribution, URI source, Definition definition) { + Types types = definition.getTypes(); + if (types != null) { + DeployedArtifact artifact = contribution.getArtifact(source); + XmlSchemaCollection collection = new XmlSchemaCollection(); + for (Object ext : types.getExtensibilityElements()) { + if (ext instanceof Schema) { + Element element = ((Schema)ext).getElement(); + XmlSchema s = collection.read(element, element.getBaseURI()); + artifact.addModelObject(XmlSchema.class, s.getTargetNamespace(), s); + } + } + } + } + + public String getContentType() { + return "application/vnd.tuscany.xsd"; + } + + /** + * @param artifactResolverRegistry the artifactResolverRegistry to set + */ + @Autowire + public void setArtifactResolverRegistry(ArtifactResolverRegistry artifactResolverRegistry) { + this.artifactResolverRegistry = artifactResolverRegistry; + } + + public void processContent(Contribution contribution, URI source, InputStream inputStream) + throws DeploymentException, IOException { + loadSchema(contribution, null, source, inputStream); + } + + public void processModel(Contribution contribution, URI source, Object modelObject) throws DeploymentException, + IOException { + if (modelObject instanceof Definition) { + loadSchemas(contribution, source, (Definition)modelObject); + } + } + +} |