diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-15 00:26:00 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-15 00:26:00 +0000 |
commit | d5f1d093fe6fa491cdec392dca7137639e98d149 (patch) | |
tree | b98c79d8231a2617ee1dce43b1782d30d93686bc /branches/sca-android/modules/binding-ws-wsdlgen | |
parent | f4e3e383071b6947d56794d9af5e9e6438aa3235 (diff) |
Pulled a recent revision of trunk into the sca-android branch, to apply the android patches from JIRA TUSCANY-2440 to it.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@695318 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-android/modules/binding-ws-wsdlgen')
18 files changed, 2857 insertions, 0 deletions
diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/LICENSE b/branches/sca-android/modules/binding-ws-wsdlgen/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. + + + diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/NOTICE b/branches/sca-android/modules/binding-ws-wsdlgen/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/pom.xml b/branches/sca-android/modules/binding-ws-wsdlgen/pom.xml new file mode 100644 index 0000000000..a06039d1b4 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/pom.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-binding-ws-wsdlgen</artifactId> + <name>Apache Tuscany SCA Web Service binding WSDL Generator</name> + + <dependencies> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-ws</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-wsdl</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-wsdl-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java-jaxws</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-xsd</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-xsd-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-policy-security-ws</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>test</scope> + </dependency> + + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.binding.ws.wsdlgen</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.binding.ws.wsdlgen*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGenerator.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGenerator.java new file mode 100644 index 0000000000..de1cab15d8 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGenerator.java @@ -0,0 +1,345 @@ +/* + * 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.binding.ws.wsdlgen; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.wsdl.Definition; +import javax.wsdl.PortType; +import javax.wsdl.WSDLException; +import javax.wsdl.xml.WSDLWriter; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.builder.BindingBuilderExtension; +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ResolverExtension; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract; +import org.apache.tuscany.sca.interfacedef.wsdl.impl.InvalidWSDLException; +import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLInterfaceIntrospectorImpl; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPoint; +import org.apache.tuscany.sca.xsd.XSDFactory; + +/** + * @version $Rev$ $Date$ + */ +public class BindingWSDLGenerator { + private static final Logger logger = Logger.getLogger(BindingWSDLGenerator.class.getName()); + private static final QName SOAP12_INTENT = new QName("http://www.osoa.org/xmlns/sca/1.0", "SOAP.1_2"); + + public static boolean printWSDL; // external code sets this to print generated WSDL + + private BindingWSDLGenerator() { + // this class has static methods only and cannot be instantiated + } + + /** + * Log a warning message. + * @param problem + */ + private static void logWarning(Problem problem) { + Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName()); + if (problemLogger != null){ + problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams()); + } else { + logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName()); + } + } + + /** + * Report a warning. + * @param message + * @param binding + * @param parameters + */ + private static void warning(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) { + Problem problem = new ProblemImpl(BindingWSDLGenerator.class.getName(), "wsdlgen-validation-messages", Severity.WARNING, wsBinding, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + logWarning(problem); + } + } + + /** + * Report an error. + * @param message + * @param binding + * @param parameters + */ + private static void error(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) { + Problem problem = new ProblemImpl(BindingWSDLGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR, wsBinding, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + throw new WSDLGenerationException(problem.toString(), null, problem); + } + } + + /** + * Report an exception error. + * @param message + * @param binding + * @param exception + */ + private static void error(Monitor monitor, String message, WebServiceBinding wsBinding, Exception ex) { + Problem problem = new ProblemImpl(BindingWSDLGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR, wsBinding, message, ex); + if (monitor != null) { + monitor.problem(problem); + } else { + throw new WSDLGenerationException(problem.toString(), ex, problem); + } + } + + /** + * Report a fatal error. + * @param message + * @param binding + * @param exception + */ + private static void fatal(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) { + Problem problem = new ProblemImpl(BindingWSDLGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR,wsBinding, message, (Object[])messageParameters); + throw new WSDLGenerationException(problem.toString(), null, problem); + } + + /** + * Report a fatal exception error. + * @param message + * @param binding + * @param exception + */ + private static void fatal(Monitor monitor, String message, WebServiceBinding wsBinding, Exception ex) { + Problem problem = new ProblemImpl(BindingWSDLGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR, wsBinding, message, ex); + throw new WSDLGenerationException(problem.toString(), ex, problem); + } + + /** + * This method can be called from the binding builder or from the runtime. + * Report problems and exceptions in the most appropriate way for both + * of these cases. + */ + public static void generateWSDL(Component component, + AbstractContract contract, + WebServiceBinding wsBinding, + ExtensionPointRegistry extensionPoints, + Monitor monitor) { + try { + createWSDLDocument(component, contract, wsBinding, extensionPoints, monitor); + } catch (WSDLGenerationException ex) { + if (ex.getProblem() != null) { + warning(monitor, "WsdlGenProblem", wsBinding, component.getName(), contract.getName()); + if (monitor != null) { + monitor.problem(ex.getProblem()); + } else { + throw ex; + } + } else if (ex.getCause() instanceof Exception) { + warning(monitor, "WsdlGenException", wsBinding, component.getName(), contract.getName()); + error(monitor, "UnexpectedException", wsBinding, (Exception)ex.getCause()); + } else { // should never happen + throw new IllegalStateException(ex); + } + } catch (RuntimeException ex) { + warning(monitor, "WsdlGenException", wsBinding, component.getName(), contract.getName()); + error(monitor, "UnexpectedException", wsBinding, ex); + } + } + + private static void createWSDLDocument(Component component, + AbstractContract contract, + WebServiceBinding wsBinding, + ExtensionPointRegistry extensionPoints, + Monitor monitor) { + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + DataBindingExtensionPoint dataBindings = extensionPoints.getExtensionPoint(DataBindingExtensionPoint.class); + WSDLFactory wsdlFactory = modelFactories.getFactory(WSDLFactory.class); + XSDFactory xsdFactory = modelFactories.getFactory(XSDFactory.class); + + if (((Contract)contract).getInterfaceContract(wsBinding) == null) { + // can happen if incorrect component service name + fatal(monitor, "MissingInterfaceContract", wsBinding, component.getName(), contract.getName()); + } + + InterfaceContract icontract = wsBinding.getBindingInterfaceContract(); + if (icontract == null) { + icontract = ((Contract)contract).getInterfaceContract(wsBinding).makeUnidirectional(false); + if (icontract instanceof JavaInterfaceContract) { + ModelResolver resolver = component instanceof ResolverExtension ? + ((ResolverExtension)component).getModelResolver() : null; + icontract = createWSDLInterfaceContract( + (JavaInterfaceContract)icontract, + requiresSOAP12(wsBinding), + resolver, + dataBindings, + wsdlFactory, + xsdFactory, + monitor); + } else { + try { + //TUSCANY-2316 Cloning the Interface Contract to avoid overriding data binding information + icontract = (InterfaceContract)icontract.clone(); + } catch (Exception e) { + //ignore + } + } + wsBinding.setBindingInterfaceContract(icontract); + } + + // TODO - fix up the conversational flag and operation sequences in case the contract has come from WSDL + // as we don't yet support requires="conversational" or sca:endConversation annotations + // in WSDL interface descriptions (see section 1.5.4 of the Assembly Specification V1.0) + if (contract.getInterfaceContract().getInterface() != null ) { + icontract.getInterface().setConversational(contract.getInterfaceContract().getInterface().isConversational()); + + for (Operation operation : icontract.getInterface().getOperations()){ + Operation serviceOperation = null; + + for (Operation tmpOp : contract.getInterfaceContract().getInterface().getOperations()){ + if (operation.getName().equals(tmpOp.getName())) { + serviceOperation = tmpOp; + break; + } + } + + if (serviceOperation != null ){ + operation.setConversationSequence(serviceOperation.getConversationSequence()); + } + } + } + + /* + // Look at all the Web Service bindings of the SCA service to see if any + // of them have an existing generated WSDL definitions document. If found, + // use it for this binding as well. If not found, generate a new document. + Definition definition = null; + for (Binding binding : contract.getBindings()) { + if (binding instanceof WebServiceBinding) { + definition = ((WebServiceBinding)binding).getWSDLDocument(); + if (definition != null) { + wsBinding.setWSDLDocument(definition); + break; + } + } + } + */ + // The above code is currently not used. Instead, we only look + // for a WSDL definitions document in this binding and don't + // attempt to share the same document across multiple bindings. + + // generate a WSDL definitions document if needed + Definition definition = wsBinding.getWSDLDocument(); + if (definition == null) { + definition = WSDLServiceGenerator.configureWSDLDefinition(wsBinding, component, contract, monitor); + wsBinding.setWSDLDocument(definition); + } + } + + protected static boolean requiresSOAP12(WebServiceBinding wsBinding) { + if (wsBinding instanceof IntentAttachPoint) { + List<Intent> intents = ((IntentAttachPoint)wsBinding).getRequiredIntents(); + for (Intent intent : intents) { + if (SOAP12_INTENT.equals(intent.getName())) { + return true; + } + } + } + return false; + } + + /** + * Create a WSDLInterfaceContract from a JavaInterfaceContract + */ + protected static WSDLInterfaceContract createWSDLInterfaceContract(JavaInterfaceContract contract, + boolean requiresSOAP12, + ModelResolver resolver, + DataBindingExtensionPoint dataBindings, + WSDLFactory wsdlFactory, + XSDFactory xsdFactory, + Monitor monitor) { + + WSDLInterfaceContract wsdlContract = wsdlFactory.createWSDLInterfaceContract(); + WSDLInterface wsdlInterface = wsdlFactory.createWSDLInterface(); + wsdlContract.setInterface(wsdlInterface); + + WSDLDefinition wsdlDefinition = wsdlFactory.createWSDLDefinition(); + JavaInterface iface = (JavaInterface)contract.getInterface(); + + Definition def = null; + try { + Interface2WSDLGenerator wsdlGenerator = + new Interface2WSDLGenerator(requiresSOAP12, resolver, dataBindings, xsdFactory, monitor); + def = wsdlGenerator.generate(iface, wsdlDefinition); + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + + // for debugging + if (printWSDL) { + try { + System.out.println("Generated WSDL for Java interface " + iface.getName() + " class " + iface.getJavaClass().getName()); + WSDLWriter writer = javax.wsdl.factory.WSDLFactory.newInstance().newWSDLWriter(); + writer.writeWSDL(def, System.out); + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + wsdlDefinition.setDefinition(def); + wsdlInterface.setWsdlDefinition(wsdlDefinition); + wsdlInterface.setRemotable(true); + wsdlInterface.setConversational(contract.getInterface().isConversational()); + wsdlInterface.setUnresolved(false); + wsdlInterface.setRemotable(true); + PortType portType = (PortType)def.getAllPortTypes().values().iterator().next(); + wsdlInterface.setPortType(portType); + + try { + for (Operation op : iface.getOperations()) { + javax.wsdl.Operation wsdlOp = portType.getOperation(op.getName(), null, null); + wsdlInterface.getOperations().add(WSDLInterfaceIntrospectorImpl.getOperation( + wsdlOp, wsdlDefinition, resolver, xsdFactory)); + } + } catch (InvalidWSDLException e) { + throw new WSDLGenerationException(e); + } + + return wsdlContract; + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java new file mode 100644 index 0000000000..c84e2e3ebe --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGenerator.java @@ -0,0 +1,840 @@ +/* + * 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.binding.ws.wsdlgen; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.wsdl.Binding; +import javax.wsdl.BindingOperation; +import javax.wsdl.Definition; +import javax.wsdl.Fault; +import javax.wsdl.Input; +import javax.wsdl.Message; +import javax.wsdl.OperationType; +import javax.wsdl.Output; +import javax.wsdl.Part; +import javax.wsdl.PortType; +import javax.wsdl.Types; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.schema.Schema; +import javax.wsdl.factory.WSDLFactory; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.XMLTypeHelper; +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; +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.utils.NamespaceMap; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @version $Rev: 670103 $ $Date: 2008-06-21 01:35:00 +0100 (Sat, 21 Jun 2008) $ + */ +public class Interface2WSDLGenerator { + private static final Logger logger = Logger.getLogger(Interface2WSDLGenerator.class.getName()); + private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema"; + private static final String SCHEMA_NAME = "schema"; + private static final QName SCHEMA_QNAME = new QName(SCHEMA_NS, SCHEMA_NAME); + private static final String XMLNS_NS = "http://www.w3.org/2000/xmlns/"; + + private static final String ANYTYPE_NAME = "anyType"; + private static final QName ANYTYPE_QNAME = new QName(SCHEMA_NS, ANYTYPE_NAME); + + + private WSDLFactory factory; + private DataBindingExtensionPoint dataBindings; + private WSDLDefinitionGenerator definitionGenerator; + private boolean requiresSOAP12; + private ModelResolver resolver; + private XSDFactory xsdFactory; + private Monitor monitor; + + public Interface2WSDLGenerator(boolean requiresSOAP12, + ModelResolver resolver, + DataBindingExtensionPoint dataBindings, + XSDFactory xsdFactory, + Monitor monitor) throws WSDLException { + super(); + this.requiresSOAP12 = requiresSOAP12; + this.resolver = resolver; + definitionGenerator = new WSDLDefinitionGenerator(requiresSOAP12); + this.dataBindings = dataBindings; + this.xsdFactory = xsdFactory; + this.monitor = monitor; + this.factory = WSDLFactory.newInstance(); + } + + /** + * Log a warning message. + * @param problem + */ + private static void logWarning(Problem problem) { + Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName()); + if (problemLogger != null){ + problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams()); + } else { + logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName()); + } + } + + /** + * Report a warning. + * @param message + * @param binding + * @param parameters + */ + private void warning(String message, Interface interfaze, String... messageParameters) { + Problem problem = new ProblemImpl(this.getClass().getName(), "wsdlgen-validation-messages", Severity.WARNING, interfaze, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + logWarning(problem); + } + } + + /** + * Report a fatal error. + * @param message + * @param binding + * @param parameters + */ + private void fatal(String message, Interface interfaze, String... messageParameters) { + Problem problem = new ProblemImpl(this.getClass().getName(), "wsdlgen-validation-messages", Severity.ERROR, interfaze, message, (Object[])messageParameters); + throw new WSDLGenerationException(problem.toString(), null, problem); + } + + private XMLTypeHelper getTypeHelper(DataType type, Map<String, XMLTypeHelper> helpers) { + if (type == null) { + return null; + } + String db = type.getDataBinding(); + if (db == null) { + return null; + } + if ("java:array".equals(db)) { + DataType dt = (DataType)type.getLogical(); + db = dt.getDataBinding(); + } + return helpers.get(db); + } + + private boolean inputTypesCompatible(DataType wrapperType, DataType<List<DataType>> inputType, Map<String, XMLTypeHelper> helpers) { + XMLTypeHelper wrapperHelper = getTypeHelper(wrapperType, helpers); + for (DataType dt : inputType.getLogical()) { + if (getTypeHelper(dt, helpers) != wrapperHelper) { + return false; + } + } + return true; + } + + private boolean outputTypeCompatible(DataType wrapperType, DataType outputType, Map<String, XMLTypeHelper> helpers) { + if (getTypeHelper(outputType, helpers) != getTypeHelper(wrapperType, helpers)) { + return false; + } else { + return true; + } + } + + private void addDataType(Map<XMLTypeHelper, List<DataType>> map, DataType type, Map<String, XMLTypeHelper> helpers) { + if (type == null) { + return; + } + String db = type.getDataBinding(); + if (db == null) { + return; + } + if ("java:array".equals(db)) { + DataType dt = (DataType)type.getLogical(); + db = dt.getDataBinding(); + } + XMLTypeHelper helper = helpers.get(db); + List<DataType> types = map.get(helper); + if (types == null) { + types = new ArrayList<DataType>(); + map.put(helper, types); + } + types.add(type); + } + + private Map<XMLTypeHelper, List<DataType>> getDataTypes(Interface intf, boolean useWrapper, Map<String, XMLTypeHelper> helpers) { + Map<XMLTypeHelper, List<DataType>> dataTypes = new HashMap<XMLTypeHelper, List<DataType>>(); + for (Operation op : intf.getOperations()) { + WrapperInfo wrapper = op.getWrapper(); + DataType dt1 = null; + boolean useInputWrapper = useWrapper & wrapper != null; + if (useInputWrapper) { + dt1 = wrapper.getInputWrapperType(); + useInputWrapper &= inputTypesCompatible(dt1, op.getInputType(), helpers); + } + if (useInputWrapper) { + addDataType(dataTypes, dt1, helpers); + } else { + for (DataType dt : op.getInputType().getLogical()) { + addDataType(dataTypes, dt, helpers); + } + } + + DataType dt2 = null; + boolean useOutputWrapper = useWrapper & wrapper != null; + if (useOutputWrapper) { + dt2 = wrapper.getOutputWrapperType(); + useOutputWrapper &= outputTypeCompatible(dt2, op.getOutputType(), helpers); + } + if (useOutputWrapper) { + addDataType(dataTypes, dt2, helpers); + } else { + dt2 = op.getOutputType(); + addDataType(dataTypes, dt2, helpers); + } + + for (DataType<DataType> dt3 : op.getFaultTypes()) { + DataType dt4 = dt3.getLogical(); + addDataType(dataTypes, dt4, helpers); + } + } + return dataTypes; + } + + + public Definition generate(Interface interfaze, WSDLDefinition wsdlDefinition) throws WSDLException { + if (interfaze == null) { + return null; + } + if (interfaze instanceof WSDLInterface) { + return ((WSDLInterface)interfaze).getWsdlDefinition().getDefinition(); + } + JavaInterface iface = (JavaInterface)interfaze; + if (!interfaze.isRemotable()) { + fatal("InterfaceNotRemotable", interfaze, iface.getName()); + } + QName name = getQName(iface); + Definition definition = factory.newDefinition(); + if (requiresSOAP12) { + definition.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + } else { + definition.addNamespace("SOAP", "http://schemas.xmlsoap.org/wsdl/soap/"); + } + definition.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + definition.addNamespace("xs", SCHEMA_NS); + + String namespaceURI = name.getNamespaceURI(); + definition.setTargetNamespace(namespaceURI); + definition.setQName(new QName(namespaceURI, name.getLocalPart() + "Service", name.getPrefix())); + definition.addNamespace(name.getPrefix(), namespaceURI); + + PortType portType = definition.createPortType(); + portType.setQName(name); + Binding binding = definitionGenerator.createBinding(definition, portType); + Map<String, XMLTypeHelper> helpers = new HashMap<String, XMLTypeHelper>(); + Map<QName, List<ElementInfo>> wrappers = new HashMap<QName, List<ElementInfo>>(); + for (Operation op : interfaze.getOperations()) { + javax.wsdl.Operation operation = generateOperation(definition, op, helpers, wrappers); + portType.addOperation(operation); + String action = ((JavaOperation)op).getAction(); + if ((action == null || "".equals(action)) && !op.isWrapperStyle() && op.getWrapper() == null) { + // Bare style + action = "urn:" + op.getName(); + } + BindingOperation bindingOp = definitionGenerator.createBindingOperation(definition, operation, action); + binding.addBindingOperation(bindingOp); + } + portType.setUndefined(false); + definition.addPortType(portType); + binding.setUndefined(false); + definition.addBinding(binding); + wsdlDefinition.setBinding(binding); + + // call each helper in turn to populate the wsdl.types element + XmlSchemaCollection schemaCollection = new XmlSchemaCollection(); + + for (Map.Entry<XMLTypeHelper, List<DataType>> en: getDataTypes(interfaze, false, helpers).entrySet()) { + XMLTypeHelper helper = en.getKey(); + if (helper == null) { + continue; + } + List<XSDefinition> xsDefinitions = helper.getSchemaDefinitions(xsdFactory, resolver, en.getValue()); + for (XSDefinition xsDef: xsDefinitions) { + addSchemaExtension(xsDef, schemaCollection, wsdlDefinition, definition); + } + } + + // remove global wrapper elements with schema definitions from generation list + for (QName wrapperName: new HashSet<QName>(wrappers.keySet())) { + if (wsdlDefinition.getXmlSchemaElement(wrapperName) != null) { + wrappers.remove(wrapperName); + } + } + + // generate schema elements for wrappers that aren't defined in the schemas + if (wrappers.size() > 0) { + int i = 0; + int index = 0; + Map<String, XSDefinition> wrapperXSDs = new HashMap<String, XSDefinition>(); + Map<Element, Map<String, String>> prefixMaps = new HashMap<Element, Map<String, String>>(); + for (Map.Entry<QName, List<ElementInfo>> entry: wrappers.entrySet()) { + String targetNS = entry.getKey().getNamespaceURI(); + Document schemaDoc = null; + Element schema = null; + XSDefinition xsDef = wrapperXSDs.get(targetNS); + if (xsDef != null) { + schemaDoc = xsDef.getDocument(); + schema = schemaDoc.getDocumentElement(); + } else { + schemaDoc = createDocument(); + schema = schemaDoc.createElementNS(SCHEMA_NS, "xs:schema"); + // The elementFormDefault should be set to unqualified, see TUSCANY-2388 + schema.setAttribute("elementFormDefault", "unqualified"); + schema.setAttribute("attributeFormDefault", "qualified"); + schema.setAttribute("targetNamespace", targetNS); + schema.setAttributeNS(XMLNS_NS, "xmlns:xs", SCHEMA_NS); + schemaDoc.appendChild(schema); + Schema schemaExt = createSchemaExt(definition); + schemaExt.setElement(schema); + prefixMaps.put(schema, new HashMap<String, String>()); + xsDef = xsdFactory.createXSDefinition(); + xsDef.setUnresolved(true); + xsDef.setNamespace(targetNS); + xsDef.setDocument(schemaDoc); + // TUSCANY-2465: Set the system id to avoid schema conflict + xsDef.setLocation(URI.create("xsd_" + index + ".xsd")); + index++; + wrapperXSDs.put(targetNS, xsDef); + } + Element wrapper = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); + schema.appendChild(wrapper); + wrapper.setAttribute("name", entry.getKey().getLocalPart()); + if (entry.getValue().size() == 1 && entry.getValue().get(0).getQName() == null) { + // special case for global fault element + QName typeName = entry.getValue().get(0).getType().getQName(); + String nsURI = typeName.getNamespaceURI(); + if ("".equals(nsURI)) { + wrapper.setAttribute("type", typeName.getLocalPart()); + addSchemaImport(schema, "", schemaDoc); + } else if (targetNS.equals(nsURI)) { + wrapper.setAttribute("type", typeName.getLocalPart()); + } else if (SCHEMA_NS.equals(nsURI)) { + wrapper.setAttribute("type", "xs:" + typeName.getLocalPart()); + } else { + Map<String, String> prefixMap = prefixMaps.get(schema); + String prefix = prefixMap.get(nsURI); + if (prefix == null) { + prefix = "ns" + i++; + prefixMap.put(nsURI, prefix); + schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI); + addSchemaImport(schema, nsURI, schemaDoc); + } + wrapper.setAttribute("type", prefix + ":" + typeName.getLocalPart()); + } + } else { + // normal wrapper containing type definition inline + Element complexType = schemaDoc.createElementNS(SCHEMA_NS, "xs:complexType"); + wrapper.appendChild(complexType); + if (entry.getValue().size() > 0) { + Element sequence = schemaDoc.createElementNS(SCHEMA_NS, "xs:sequence"); + complexType.appendChild(sequence); + for (ElementInfo element: entry.getValue()) { + Element xsElement = schemaDoc.createElementNS(SCHEMA_NS, "xs:element"); + if (element.isMany()) { + xsElement.setAttribute("maxOccurs", "unbounded"); + } + xsElement.setAttribute("minOccurs", "0"); + xsElement.setAttribute("name", element.getQName().getLocalPart()); + if (element.isNillable()) { + xsElement.setAttribute("nillable", "true"); + } + QName typeName = element.getType().getQName(); + String nsURI = typeName.getNamespaceURI(); + if ("".equals(nsURI)) { + xsElement.setAttribute("type", typeName.getLocalPart()); + addSchemaImport(schema, "", schemaDoc); + } else if (targetNS.equals(nsURI)) { + xsElement.setAttribute("type", typeName.getLocalPart()); + } else if (SCHEMA_NS.equals(nsURI)) { + xsElement.setAttribute("type", "xs:" + typeName.getLocalPart()); + } else { + Map<String, String> prefixMap = prefixMaps.get(schema); + String prefix = prefixMap.get(nsURI); + if (prefix == null) { + prefix = "ns" + i++; + prefixMap.put(nsURI, prefix); + schema.setAttributeNS(XMLNS_NS, "xmlns:" + prefix, nsURI); + addSchemaImport(schema, nsURI, schemaDoc); + } + xsElement.setAttribute("type", prefix + ":" + typeName.getLocalPart()); + } + sequence.appendChild(xsElement); + } + } + } + } + + // resolve XSDefinitions containing generated wrappers + for (XSDefinition xsDef: wrapperXSDs.values()) { + loadXSD(schemaCollection, xsDef); + wsdlDefinition.getXmlSchemas().add(xsDef); + } + } + + return definition; + } + + private static void addSchemaImport(Element schema, String nsURI, Document schemaDoc) { + Element imp = schemaDoc.createElementNS(SCHEMA_NS, "xs:import"); + if (!"".equals(nsURI)) { + imp.setAttribute("namespace", nsURI); + } + NodeList childNodes = schema.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node childNode = childNodes.item(i); + if (childNode instanceof Element) { + schema.insertBefore(imp, childNode); + imp = null; + break; + } + } + if (imp != null) { + schema.appendChild(imp); + } + } + + private void addSchemaExtension(XSDefinition xsDef, + XmlSchemaCollection schemaCollection, + WSDLDefinition wsdlDefinition, + Definition definition) throws WSDLException { + if (xsDef.getAggregatedDefinitions() != null) { + for (XSDefinition xsd: xsDef.getAggregatedDefinitions()) { + addSchemaExtension(xsd, schemaCollection, wsdlDefinition, definition); + } + } else { + String nsURI = xsDef.getNamespace(); + Document document = xsDef.getDocument(); + if (document == null) { + try { + NamespaceMap prefixMap = new NamespaceMap(); + prefixMap.add("xs", SCHEMA_NS); + prefixMap.add("tns", nsURI); + XmlSchema schemaDef = xsDef.getSchema(); + schemaDef.setNamespaceContext(prefixMap); + Document[] docs = schemaDef.getAllSchemas(); + document = docs[docs.length-1]; + document.setDocumentURI(xsDef.getLocation().toString()); + xsDef.setDocument(document); + } catch (XmlSchemaException e) { + throw new RuntimeException(e); + } + } + loadXSD(schemaCollection, xsDef); + wsdlDefinition.getXmlSchemas().add(xsDef); + Element schema = document.getDocumentElement(); + Schema schemaExt = createSchemaExt(definition); + schemaExt.setDocumentBaseURI(document.getDocumentURI()); + schemaExt.setElement(schema); + } + } + + private static void loadXSD(XmlSchemaCollection schemaCollection, XSDefinition definition) { + if (definition.getSchema() != null) { + return; + } + if (definition.getDocument() != null) { + String uri = null; + if (definition.getLocation() != null) { + uri = definition.getLocation().toString(); + } + XmlSchema schema = schemaCollection.read(definition.getDocument(), uri, null); + if (definition.getSchemaCollection() == null) { + definition.setSchemaCollection(schemaCollection); + } + if (definition.getSchema() == null) { + definition.setSchema(schema); + } + } + } + + public Schema createSchemaExt(Definition definition) throws WSDLException { + Types types = definition.getTypes(); + if (types == null) { + types = definition.createTypes(); + definition.setTypes(types); + } + + Schema schemaExt = createSchema(definition); + types.addExtensibilityElement(schemaExt); + + return schemaExt; + } + + public Schema createSchema(Definition definition) throws WSDLException { + return (Schema)definition.getExtensionRegistry().createExtension(Types.class, SCHEMA_QNAME); + } + + private DocumentBuilderFactory documentBuilderFactory; + + public Document createDocument() { + Document document; + try { + if (documentBuilderFactory == null) { + documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setNamespaceAware(true); + } + document = documentBuilderFactory.newDocumentBuilder().newDocument(); + } catch (ParserConfigurationException ex) { + throw new WSDLGenerationException(ex); + } + // document.setDocumentURI("http://"); + return document; + } + + protected QName getQName(Interface interfaze) { + JavaInterface iface = (JavaInterface)interfaze; + QName qname = iface.getQName(); + if (qname != null) { + return qname; + } else { + Class<?> javaClass = iface.getJavaClass(); + return new QName(JavaXMLMapper.getNamespace(javaClass), javaClass.getSimpleName(), "tns"); + } + } + + public javax.wsdl.Operation generateOperation(Definition definition, + Operation op, + Map<String, XMLTypeHelper> helpers, + Map<QName, List<ElementInfo>> wrappers) + throws WSDLException { + javax.wsdl.Operation operation = definition.createOperation(); + operation.setName(op.getName()); + operation.setUndefined(false); + + Input input = definition.createInput(); + Message inputMsg = definition.createMessage(); + String namespaceURI = definition.getQName().getNamespaceURI(); + QName inputMsgName = new QName(namespaceURI, op.getName()); + inputMsg.setQName(inputMsgName); + inputMsg.setUndefined(false); + definition.addMessage(inputMsg); + + List<ElementInfo> elements = null; + // FIXME: By default, java interface is mapped to doc-lit-wrapper style WSDL + if (op.getWrapper() != null) { + // Generate doc-lit-wrapper style + inputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, true)); + } else { + // Bare style + int i = 0; + for (DataType d : op.getInputType().getLogical()) { + inputMsg.addPart(generatePart(definition, d, "arg" + i)); + elements = new ArrayList<ElementInfo>(); + ElementInfo element = getElementInfo(d.getPhysical(), d, null, helpers); + elements.add(element); + QName elementName = ((XMLType)d.getLogical()).getElementName(); + wrappers.put(elementName, elements); + i++; + } + } + input.setMessage(inputMsg); + operation.setInput(input); + + if (!op.isNonBlocking()) { + Output output = definition.createOutput(); + Message outputMsg = definition.createMessage(); + QName outputMsgName = new QName(namespaceURI, op.getName() + "Response"); + outputMsg.setQName(outputMsgName); + outputMsg.setUndefined(false); + definition.addMessage(outputMsg); + + if (op.getWrapper() != null) { + outputMsg.addPart(generateWrapperPart(definition, op, helpers, wrappers, false)); + } else { + DataType outputType = op.getOutputType(); + outputMsg.addPart(generatePart(definition, outputType, "return")); + if (outputType != null) { + elements = new ArrayList<ElementInfo>(); + ElementInfo element = getElementInfo(outputType.getPhysical(), outputType, null, helpers); + elements.add(element); + QName elementName = ((XMLType)outputType.getLogical()).getElementName(); + wrappers.put(elementName, elements); + } + } + output.setMessage(outputMsg); + + operation.setOutput(output); + operation.setStyle(OperationType.REQUEST_RESPONSE); + } else { + operation.setStyle(OperationType.ONE_WAY); + } + + for (DataType<DataType> faultType: op.getFaultTypes()) { + Fault fault = definition.createFault(); + QName faultName = ((XMLType)faultType.getLogical().getLogical()).getElementName(); + fault.setName(faultName.getLocalPart()); + Message faultMsg = definition.getMessage(faultName); + if (faultMsg == null) { + faultMsg = definition.createMessage(); + faultMsg.setQName(faultName); + faultMsg.setUndefined(false); + definition.addMessage(faultMsg); + faultMsg.addPart(generatePart(definition, faultType.getLogical(), faultName.getLocalPart())); + } + fault.setMessage(faultMsg); + operation.addFault(fault); + if (faultType.getLogical().getPhysical() != faultType.getPhysical()) { + // create special wrapper for type indirection to real fault bean + DataType logical = faultType.getLogical(); + elements = new ArrayList<ElementInfo>(); + elements.add(getElementInfo(logical.getPhysical(), logical, null, helpers)); + } else { + // convert synthesized fault bean to a wrapper type + for (DataType<XMLType> propDT: op.getFaultBeans().get(faultName)) { + XMLType logical = propDT.getLogical(); + elements = new ArrayList<ElementInfo>(); + elements.add(getElementInfo(propDT.getPhysical(), propDT, logical.getElementName(), helpers)); + } + } + wrappers.put(faultName, elements); + } + + operation.setUndefined(false); + return operation; + } + + public Part generatePart(Definition definition, DataType arg, String partName) { + Part part = definition.createPart(); + part.setName(partName); + if (arg != null && arg.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)arg.getLogical(); + QName elementName = xmlType.getElementName(); + part.setElementName(elementName); + addNamespace(definition, elementName); + if (xmlType.getElementName() == null) { + QName typeName = xmlType.getTypeName(); + part.setTypeName(typeName); + addNamespace(definition, typeName); + } + } + return part; + } + + public Part generateWrapperPart(Definition definition, + Operation operation, + Map<String, XMLTypeHelper> helpers, + Map<QName, List<ElementInfo>> wrappers, + boolean input) throws WSDLException { + Part part = definition.createPart(); + String partName = input ? operation.getName() : (operation.getName() + "Response"); + part.setName(partName); + WrapperInfo opWrapper = operation.getWrapper(); + if (opWrapper != null) { + ElementInfo elementInfo = + input ? opWrapper.getInputWrapperElement() : opWrapper.getOutputWrapperElement(); + List<ElementInfo> elements = + input ? opWrapper.getInputChildElements() : opWrapper.getOutputChildElements(); + QName wrapperName = elementInfo.getQName(); + part.setElementName(wrapperName); + addNamespace(definition, wrapperName); + wrappers.put(wrapperName, elements); + + // FIXME: [rfeng] Ideally, we should try to register the wrappers only. But we are + // expriencing the problem that we cannot handle XSD imports + /* + Class<?> wrapperClass = input ? opWrapper.getInputWrapperClass() : opWrapper.getOutputWrapperClass(); + DataType wrapperDT = input ? opWrapper.getInputWrapperType() : opWrapper.getOutputWrapperType(); + if (wrapperClass != null) { + getElementInfo(wrapperClass, wrapperDT, wrapperName, helpers); + return part; + } + */ + + Method method = ((JavaOperation)operation).getJavaMethod(); + if (input) { + Class<?>[] paramTypes = method.getParameterTypes(); + for (int i = 0; i < paramTypes.length; i++) { + DataType dataType = operation.getInputType().getLogical().get(i); + elements.set(i, getElementInfo(paramTypes[i], dataType, elements.get(i).getQName(), helpers)); + } + } else { + Class<?> returnType = method.getReturnType(); + if (returnType != Void.TYPE) { + DataType dataType = operation.getOutputType(); + elements.set(0, getElementInfo(returnType, dataType, elements.get(0).getQName(), helpers)); + } + } + } + return part; + } + + private ElementInfo getElementInfo(Class javaType, + DataType dataType, + QName name, + Map<String, XMLTypeHelper> helpers) { + String db = dataType.getDataBinding(); + while ("java:array".equals(db)) { + dataType = (DataType)dataType.getLogical(); + db = dataType.getDataBinding(); + } + XMLTypeHelper helper = helpers.get(db); + if (helper == null) { + DataBinding dataBinding = dataBindings.getDataBinding(db); + if (dataBinding == null) { + QName element = name; + if (element == null || dataType.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)dataType.getLogical(); + if (xmlType.getElementName() != null) { + element = xmlType.getElementName(); + } + } + return new ElementInfo(element, new TypeInfo(ANYTYPE_QNAME, false, null)); + // throw new ServiceRuntimeException("No data binding for " + db); + } + + helper = dataBinding.getXMLTypeHelper(); + if (helper == null) { + // Default to JAXB + helper = helpers.get(JAXBDataBinding.NAME); + if (helper == null) { + helper = dataBindings.getDataBinding(JAXBDataBinding.NAME).getXMLTypeHelper(); + helpers.put(JAXBDataBinding.NAME, helper); + } + } + helpers.put(db, helper); + } + TypeInfo typeInfo = helper.getTypeInfo(javaType.isArray() ? javaType.getComponentType() : javaType, + dataType.getLogical()); + ElementInfo element = new ElementInfo(name, typeInfo); + element.setMany(byte[].class != javaType && javaType.isArray()); + element.setNillable(!javaType.isPrimitive()); + return element; + } + + private static void addNamespace(Definition definition, QName name) { + String namespace = name.getNamespaceURI(); + if (definition.getPrefix(namespace) == null) { + definition.addNamespace("ns" + definition.getNamespaces().size(), namespace); + } + } + + /* + // currently not using the next three methods + public XmlSchemaType getXmlSchemaType(DataType type) { + return null; + } + + // FIXME: WE need to add databinding-specific Java2XSD generation + public Element generateXSD(DataType dataType) { + DataBinding dataBinding = dataBindings.getDataBinding(dataType.getDataBinding()); + if (dataBinding != null) { + // return dataBinding.generateSchema(dataType); + } + return null; + } + + public void generateWrapperElements(Operation op) { + XmlSchemaCollection collection = new XmlSchemaCollection(); + String ns = getQName(op.getInterface()).getNamespaceURI(); + XmlSchema schema = new XmlSchema(ns, collection); + schema.setAttributeFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED)); + schema.setElementFormDefault(new XmlSchemaForm(XmlSchemaForm.QUALIFIED)); + + XmlSchemaElement inputElement = new XmlSchemaElement(); + inputElement.setQName(new QName(ns, op.getName())); + XmlSchemaComplexType inputType = new XmlSchemaComplexType(schema); + inputType.setName(""); + XmlSchemaSequence inputSeq = new XmlSchemaSequence(); + inputType.setParticle(inputSeq); + List<DataType> argTypes = op.getInputType().getLogical(); + for (DataType argType : argTypes) { + XmlSchemaElement child = new XmlSchemaElement(); + Object logical = argType.getLogical(); + if (logical instanceof XMLType) { + child.setName(((XMLType)logical).getElementName().getLocalPart()); + XmlSchemaType type = getXmlSchemaType(argType); + child.setType(type); + } + inputSeq.getItems().add(child); + } + inputElement.setType(inputType); + + XmlSchemaElement outputElement = new XmlSchemaElement(); + outputElement.setQName(new QName(ns, op.getName() + "Response")); + XmlSchemaComplexType outputType = new XmlSchemaComplexType(schema); + outputType.setName(""); + XmlSchemaSequence outputSeq = new XmlSchemaSequence(); + outputType.setParticle(outputSeq); + DataType returnType = op.getOutputType(); + XmlSchemaElement child = new XmlSchemaElement(); + Object logical = returnType.getLogical(); + if (logical instanceof XMLType) { + child.setName(((XMLType)logical).getElementName().getLocalPart()); + XmlSchemaType type = getXmlSchemaType(returnType); + child.setType(type); + } + outputSeq.getItems().add(child); + outputElement.setType(outputType); + + schema.getElements().add(inputElement.getQName(), inputElement); + schema.getElements().add(outputElement.getQName(), outputElement); + + } + */ + + public WSDLFactory getFactory() { + return factory; + } + + public void setFactory(WSDLFactory factory) { + this.factory = factory; + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLDefinitionGenerator.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLDefinitionGenerator.java new file mode 100644 index 0000000000..d0b79f9b0e --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLDefinitionGenerator.java @@ -0,0 +1,305 @@ +/* + * 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.binding.ws.wsdlgen; + +import java.util.Iterator; + +import javax.wsdl.Binding; +import javax.wsdl.BindingFault; +import javax.wsdl.BindingInput; +import javax.wsdl.BindingOperation; +import javax.wsdl.BindingOutput; +import javax.wsdl.Definition; +import javax.wsdl.Fault; +import javax.wsdl.Input; +import javax.wsdl.Operation; +import javax.wsdl.Output; +import javax.wsdl.Port; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.Types; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensibilityElement; +import javax.wsdl.extensions.soap.SOAPAddress; +import javax.wsdl.extensions.soap.SOAPBinding; +import javax.wsdl.extensions.soap.SOAPBody; +import javax.wsdl.extensions.soap.SOAPFault; +import javax.wsdl.extensions.soap.SOAPOperation; +import javax.wsdl.extensions.soap12.SOAP12Address; +import javax.wsdl.extensions.soap12.SOAP12Binding; +import javax.wsdl.extensions.soap12.SOAP12Body; +import javax.wsdl.extensions.soap12.SOAP12Fault; +import javax.wsdl.extensions.soap12.SOAP12Operation; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +import org.w3c.dom.Element; + +/** + * + * @version $Rev: 668025 $ $Date: 2008-06-16 01:06:34 +0100 (Mon, 16 Jun 2008) $ + */ +public class WSDLDefinitionGenerator { + private static final String SOAP_NS = "http://schemas.xmlsoap.org/wsdl/soap/"; + public static final QName SOAP_ADDRESS = new QName(SOAP_NS, "address"); + private static final QName SOAP_BINDING = new QName(SOAP_NS, "binding"); + private static final QName SOAP_BODY = new QName(SOAP_NS, "body"); + private static final QName SOAP_FAULT = new QName(SOAP_NS, "fault"); + private static final QName SOAP_OPERATION = new QName(SOAP_NS, "operation"); + private static final String SOAP12_NS = "http://schemas.xmlsoap.org/wsdl/soap12/"; + public static final QName SOAP12_ADDRESS = new QName(SOAP12_NS, "address"); + private static final QName SOAP12_BINDING = new QName(SOAP12_NS, "binding"); + private static final QName SOAP12_BODY = new QName(SOAP12_NS, "body"); + private static final QName SOAP12_FAULT = new QName(SOAP12_NS, "fault"); + private static final QName SOAP12_OPERATION = new QName(SOAP12_NS, "operation"); + + private static final String BINDING_SUFFIX = "Binding"; + private static final String SERVICE_SUFFIX = "Service"; + private static final String PORT_SUFFIX = "Port"; + + private boolean requiresSOAP12; + private QName soapAddress; + private QName soapBinding; + private QName soapBody; + private QName soapFault; + private QName soapOperation; + + public WSDLDefinitionGenerator(boolean requiresSOAP12) { + super(); + this.requiresSOAP12 = requiresSOAP12; + soapAddress = requiresSOAP12 ? SOAP12_ADDRESS : SOAP_ADDRESS; + soapBinding = requiresSOAP12 ? SOAP12_BINDING : SOAP_BINDING; + soapBody = requiresSOAP12 ? SOAP12_BODY : SOAP_BODY; + soapFault = requiresSOAP12 ? SOAP12_FAULT : SOAP_FAULT; + soapOperation = requiresSOAP12 ? SOAP12_OPERATION : SOAP_OPERATION; + } + + public Definition cloneDefinition(WSDLFactory factory, Definition definition) throws WSDLException { + Element root = definition.getDocumentationElement(); + root = (Element)root.cloneNode(true); + WSDLReader reader = factory.newWSDLReader(); + return reader.readWSDL(definition.getDocumentBaseURI(), root); + } + + public Types createTypes(Definition definition) { + Types types = definition.createTypes(); + definition.setTypes(types); + return types; + } + + public Binding createBinding(Definition definition, PortType portType) { + try { + Binding binding = definition.createBinding(); + binding.setPortType(portType); + configureBinding(definition, binding, portType); + ExtensibilityElement bindingExtension = + definition.getExtensionRegistry().createExtension(Binding.class, soapBinding); + if (requiresSOAP12) { + ((SOAP12Binding)bindingExtension).setStyle("document"); + ((SOAP12Binding)bindingExtension).setTransportURI("http://schemas.xmlsoap.org/soap/http"); + } else { + ((SOAPBinding)bindingExtension).setStyle("document"); + ((SOAPBinding)bindingExtension).setTransportURI("http://schemas.xmlsoap.org/soap/http"); + } + binding.addExtensibilityElement(bindingExtension); + return binding; + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + protected void configureBinding(Definition definition, Binding binding, PortType portType) throws WSDLException { + QName portTypeName = portType.getQName(); + if (portTypeName != null) { + // Choose <porttype>Binding if available. If this name is in use, insert + // separating underscores until there is no clash. + for (String suffix = BINDING_SUFFIX; ; suffix = "_" + suffix) { + QName name = new QName(definition.getTargetNamespace(), portTypeName.getLocalPart() + suffix); + if (definition.getBinding(name) == null) { + binding.setQName(name); + break; + } + } + } + } + + @SuppressWarnings("unchecked") + public void createBindingOperations(Definition definition, Binding binding, PortType portType) { + try { + for (Iterator oi = portType.getOperations().iterator(); oi.hasNext();) { + Operation operation = (Operation)oi.next(); + BindingOperation bindingOperation = + createBindingOperation(definition, operation, "urn:" + operation.getName()); + binding.addBindingOperation(bindingOperation); + } + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + @SuppressWarnings("unchecked") + public BindingOperation createBindingOperation(Definition definition, Operation operation, String action) + throws WSDLException { + BindingOperation bindingOperation = definition.createBindingOperation(); + bindingOperation.setOperation(operation); + configureBindingOperation(bindingOperation, operation); + ExtensibilityElement operationExtension = + definition.getExtensionRegistry().createExtension(BindingOperation.class, soapOperation); + if (requiresSOAP12) { + ((SOAP12Operation)operationExtension).setSoapActionURI(action); + } else { + ((SOAPOperation)operationExtension).setSoapActionURI(action); + } + bindingOperation.addExtensibilityElement(operationExtension); + if (operation.getInput() != null) { + BindingInput bindingInput = definition.createBindingInput(); + configureBindingInput(bindingInput, operation.getInput()); + ExtensibilityElement inputExtension = + definition.getExtensionRegistry().createExtension(BindingInput.class, soapBody); + if (requiresSOAP12) { + ((SOAP12Body)inputExtension).setUse("literal"); + } else { + ((SOAPBody)inputExtension).setUse("literal"); + } + bindingInput.addExtensibilityElement(inputExtension); + bindingOperation.setBindingInput(bindingInput); + } + if (operation.getOutput() != null) { + BindingOutput bindingOutput = definition.createBindingOutput(); + configureBindingOutput(bindingOutput, operation.getOutput()); + ExtensibilityElement outputExtension = + definition.getExtensionRegistry().createExtension(BindingOutput.class, soapBody); + if (requiresSOAP12) { + ((SOAP12Body)outputExtension).setUse("literal"); + } else { + ((SOAPBody)outputExtension).setUse("literal"); + } + bindingOutput.addExtensibilityElement(outputExtension); + bindingOperation.setBindingOutput(bindingOutput); + } + for (Iterator fi = operation.getFaults().values().iterator(); fi.hasNext();) { + Fault fault = (Fault)fi.next(); + BindingFault bindingFault = definition.createBindingFault(); + ExtensibilityElement faultExtension = + definition.getExtensionRegistry().createExtension(BindingFault.class, soapFault); + configureBindingFault(bindingFault, faultExtension, fault); + bindingFault.addExtensibilityElement(faultExtension); + bindingOperation.addBindingFault(bindingFault); + } + return bindingOperation; + } + + protected void configureBindingOperation(BindingOperation bindingOperation, Operation operation) + throws WSDLException { + bindingOperation.setName(operation.getName()); + } + + protected void configureBindingInput(BindingInput bindingInput, Input input) throws WSDLException { + bindingInput.setName(input.getName()); + } + + protected void configureBindingOutput(BindingOutput bindingOutput, Output output) throws WSDLException { + bindingOutput.setName(output.getName()); + } + + protected void configureBindingFault(BindingFault bindingFault, + ExtensibilityElement faultExtension, + Fault fault) + throws WSDLException { + String faultName = fault.getName(); + bindingFault.setName(faultName); + if (requiresSOAP12) { + ((SOAP12Fault)faultExtension).setName(faultName); + ((SOAP12Fault)faultExtension).setUse("literal"); + } else { + ((SOAPFault)faultExtension).setName(faultName); + ((SOAPFault)faultExtension).setUse("literal"); + } + } + + public Service createService(Definition definition, PortType portType) { + try { + Service service = definition.createService(); + configureService(definition, service, portType); + // createPort(definition, binding, service); + definition.addService(service); + return service; + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + public Service createService(Definition definition, Binding binding) { + try { + Service service = definition.createService(); + configureService(definition, service, binding.getPortType()); + // createPort(definition, binding, service); + definition.addService(service); + return service; + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + protected void configureService(Definition definition, Service service, PortType portType) throws WSDLException { + QName portTypeName = portType.getQName(); + if (portTypeName != null) { + // Choose <porttype>Service if available. If this name is in use, insert + // separating underscores until there is no clash. + for (String suffix = SERVICE_SUFFIX; ; suffix = "_" + suffix) { + QName name = new QName(definition.getTargetNamespace(), portTypeName.getLocalPart() + suffix); + if (definition.getService(name) == null) { + service.setQName(name); + break; + } + } + } + } + + public Port createPort(Definition definition, Binding binding, Service service, String uri) { + try { + Port port = definition.createPort(); + port.setBinding(binding); + configurePort(port, binding); + if (uri != null) { + ExtensibilityElement portExtension = + definition.getExtensionRegistry().createExtension(Port.class, soapAddress); + if (requiresSOAP12) { + ((SOAP12Address)portExtension).setLocationURI(uri); + } else { + ((SOAPAddress)portExtension).setLocationURI(uri); + } + port.addExtensibilityElement(portExtension); + } + service.addPort(port); + return port; + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + protected void configurePort(Port port, Binding binding) throws WSDLException { + if (binding.getPortType() != null && binding.getPortType().getQName() != null) { + port.setName(binding.getPortType().getQName().getLocalPart() + PORT_SUFFIX); + } + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLGenerationException.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLGenerationException.java new file mode 100644 index 0000000000..bf9e22f645 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLGenerationException.java @@ -0,0 +1,54 @@ +/* + * 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.binding.ws.wsdlgen; + +import org.apache.tuscany.sca.monitor.Problem; +import org.osoa.sca.ServiceRuntimeException; + +public class WSDLGenerationException extends ServiceRuntimeException { + private static final long serialVersionUID = 1L; + private Problem problem; + + public WSDLGenerationException() { + super(); + } + + public WSDLGenerationException(String message, Throwable cause) { + super(message, cause); + } + + public WSDLGenerationException(String message) { + super(message); + } + + public WSDLGenerationException(Throwable cause) { + super(cause); + } + + public WSDLGenerationException(String message, Throwable cause, Problem problem) { + super(message, cause); + this.problem = problem; + } + + public Problem getProblem() { + return problem; + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLServiceGenerator.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLServiceGenerator.java new file mode 100644 index 0000000000..ebfbdc509a --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/java/org/apache/tuscany/sca/binding/ws/wsdlgen/WSDLServiceGenerator.java @@ -0,0 +1,533 @@ +/* + * 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.binding.ws.wsdlgen; + +//FIXME: trim the import list down to what's really needed + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.wsdl.Binding; +import javax.wsdl.BindingOperation; +import javax.wsdl.Definition; +import javax.wsdl.Import; +import javax.wsdl.Port; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.ExtensibilityElement; +import javax.wsdl.extensions.soap.SOAPAddress; +import javax.wsdl.extensions.soap.SOAPBinding; +import javax.wsdl.extensions.soap.SOAPOperation; +import javax.wsdl.extensions.soap12.SOAP12Address; +import javax.wsdl.extensions.soap12.SOAP12Binding; +import javax.wsdl.factory.WSDLFactory; +import javax.wsdl.xml.WSDLWriter; +import javax.xml.namespace.QName; +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.dom.DOMSource; + +import org.apache.tuscany.sca.assembly.AbstractContract; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.binding.ws.WebServiceBinding; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; +import org.apache.tuscany.sca.policy.security.ws.Axis2ConfigParamPolicy; +import org.apache.tuscany.sca.policy.util.PolicyHandler; +import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; +import org.apache.tuscany.sca.policy.util.PolicyHandlerUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; + +/** + * WSDLServiceGenerator generates a binding WSDL service document. + * + * @version $Rev$ $Date$ + */ +public class WSDLServiceGenerator { + // the following switch is temporary for debugging + public static boolean printWSDL; // external code sets this to print generated WSDL + + private static final Logger logger = Logger.getLogger(WSDLServiceGenerator.class.getName()); + private static final QName TRANSPORT_JMS_QUALIFIED_INTENT = + new QName("http://www.osoa.org/xmlns/sca/1.0", "transport.jms"); + private static final String DEFAULT_QUEUE_CONNECTION_FACTORY = "TuscanyQueueConnectionFactory"; + private static final String ADDRESS = "Address"; + + private WSDLServiceGenerator() { + // this class has static methods only and cannot be instantiated + } + + /** + * Log a warning message. + * @param problem + */ + private static void logWarning(Problem problem) { + Logger problemLogger = Logger.getLogger(problem.getSourceClassName(), problem.getBundleName()); + if (problemLogger != null){ + problemLogger.logp(Level.WARNING, problem.getSourceClassName(), null, problem.getMessageId(), problem.getMessageParams()); + } else { + logger.severe("Can't get logger " + problem.getSourceClassName()+ " with bundle " + problem.getBundleName()); + } + } + + /** + * Report a warning. + * @param message + * @param binding + * @param parameters + */ + private static void warning(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) { + Problem problem = new ProblemImpl(WSDLServiceGenerator.class.getName(), "wsdlgen-validation-messages", Severity.WARNING, wsBinding, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + logWarning(problem); + } + } + + /** + * Report an error. + * @param message + * @param binding + * @param parameters + */ + private static void error(Monitor monitor, String message, WebServiceBinding wsBinding, String... messageParameters) { + Problem problem = new ProblemImpl(WSDLServiceGenerator.class.getName(), "wsdlgen-validation-messages", Severity.ERROR, wsBinding, message, (Object[])messageParameters); + if (monitor != null) { + monitor.problem(problem); + } else { + throw new WSDLGenerationException(problem.toString(), null, problem); + } + } + + /** + * Generate a suitably configured WSDL definition + */ + protected static Definition configureWSDLDefinition(WebServiceBinding wsBinding, + Component component, + AbstractContract contract, + Monitor monitor) { + + //[nash] changes to the builder sequence avoid calling this for a CompositeService + assert !(contract instanceof CompositeService); + /* + // For every promoted composite service, the underlying component + // gets a copy of the service with the name prefixed by "$promoted$." + String contractName = (contract instanceof CompositeService ? "$promoted$." : "") + contract.getName(); + */ + String contractName = contract.getName(); + + List<Port> ports = new ArrayList<Port>(); + WSDLDefinition wsdlDefinition = wsBinding.getWSDLDefinition(); + if (wsdlDefinition == null) { + error(monitor, "NoWsdlInterface", wsBinding, component.getName(), contract.getName()); + return null; + } + Definition def = wsdlDefinition.getDefinition(); + if (wsdlDefinition.getBinding() == null) { + // The WSDL document was provided by the user. Generate a new + // WSDL document with imports from the user-provided document. + WSDLFactory factory = null; + try { + factory = WSDLFactory.newInstance(); + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + Definition newDef = factory.newDefinition(); + + // Construct a target namespace from the base URI of the user's + // WSDL document (is this what we should be using?) and a path + // computed according to the SCA Web Service binding spec. + String nsName = component.getName() + "/" + contractName; + String namespaceURI = null; + try { + URI userTNS = new URI(def.getTargetNamespace()); + namespaceURI = userTNS.resolve("/" + nsName).toString(); + } catch (URISyntaxException e1) { + throw new WSDLGenerationException(e1); + } catch (IllegalArgumentException e2) { + throw new WSDLGenerationException(e2); + } + + // set name and targetNamespace attributes on the definition + String defsName = component.getName() + "." + contractName; + newDef.setQName(new QName(namespaceURI, defsName)); + newDef.setTargetNamespace(namespaceURI); + newDef.addNamespace("tns", namespaceURI); + + // set wsdl namespace prefix on the definition + newDef.addNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/"); + + // import the service or reference interface portType + List<WSDLDefinition> imports = new ArrayList<WSDLDefinition>(); + Interface interfaze = wsBinding.getBindingInterfaceContract().getInterface(); + if (interfaze instanceof WSDLInterface) { + PortType portType = ((WSDLInterface)interfaze).getPortType(); + boolean ok = importPortType(portType, wsdlDefinition, newDef, imports); + if (!ok) { + error(monitor, "PortTypeNotFound", wsBinding, portType.getQName().toString(), + component.getName(), contract.getName()); + } + } + + // import an existing binding if specified + Binding binding = wsBinding.getBinding(); + if (binding != null) { + boolean ok = importBinding(binding, wsdlDefinition, newDef, imports); + if (ok) { + boolean ok2 = importPortType(binding.getPortType(), wsdlDefinition, newDef, imports); + if (!ok2) { + error(monitor, "PortTypeNotFound", wsBinding, binding.getPortType().getQName().toString(), + component.getName(), contract.getName()); + } + } else { + error(monitor, "BindingNotFound", wsBinding, binding.getQName().toString(), + component.getName(), contract.getName()); + } + } + + // import bindings and portTypes needed by services and ports + QName serviceQName = wsBinding.getServiceName(); + String portName = wsBinding.getPortName(); + if (serviceQName != null) { + Service service = def.getService(serviceQName); + if (portName != null) { + Port port = service.getPort(portName); + Port newPort = copyPort(newDef, port, wsBinding); + if (newPort != null) { + importBinding(port.getBinding(), wsdlDefinition, newDef, imports); + ports.add(newPort); + } else { + error(monitor, "InvalidPort", wsBinding, serviceQName.toString(), portName, + component.getName(), contract.getName()); + } + } else { + for (Object port : service.getPorts().values()) { + Port newPort = copyPort(newDef, (Port)port, wsBinding); + if (newPort != null) { + importBinding(((Port)port).getBinding(), wsdlDefinition, newDef, imports); + ports.add(newPort); + } else { + // not an error, just ignore the port + warning(monitor, "IgnoringPort", wsBinding, serviceQName.toString(), ((Port)port).getName(), + component.getName(), contract.getName()); + } + } + if (ports.size() == 0) { + error(monitor, "NoValidPorts", wsBinding, serviceQName.toString(), + component.getName(), contract.getName()); + } + } + } + + // replace original WSDL definition by the generated definition + def = newDef; + + } else { + // The WSDL definition was generated by Interface2WSDLGenerator. + // Reuse it instead of creating a new definition here. + } + + // add a service and ports to the generated definition + WSDLDefinitionGenerator helper = + new WSDLDefinitionGenerator(BindingWSDLGenerator.requiresSOAP12(wsBinding)); + WSDLInterface wi = (WSDLInterface)wsBinding.getBindingInterfaceContract().getInterface(); + PortType portType = wi.getPortType(); + Service service = helper.createService(def, portType); + if (wsBinding.getBinding() == null && ports.size() == 0) { + Binding binding = helper.createBinding(def, portType); + if (BindingWSDLGenerator.requiresSOAP12(wsBinding)) { + def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + } else { + def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/"); + } + helper.createBindingOperations(def, binding, portType); + binding.setUndefined(false); + def.addBinding(binding); + + String endpointURI = computeActualURI(wsBinding, null); + Port port = helper.createPort(def, binding, service, endpointURI); + wsBinding.setService(service); + wsBinding.setPort(port); + } else { + if (ports.size() > 0) { + // there are one or more user-specified valid ports + for (Port port : ports) { + service.addPort(port); + } + if (ports.size() == 1) { + // only one port, so use it + wsBinding.setPort(ports.get(0)); + } else { + // multiple ports, make them all available + wsBinding.setPort(null); + } + } else { + // no valid user-specified ports, so create a suitably configured port + String endpointURI = computeActualURI(wsBinding, null); + Port port = helper.createPort(def, wsBinding.getBinding(), service, endpointURI); + if (BindingWSDLGenerator.requiresSOAP12(wsBinding)) { + def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + } else { + def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/"); + } + wsBinding.setPort(port); + } + wsBinding.setService(service); + } + + // for debugging + if (printWSDL) { + try { + System.out.println("Generated WSDL for " + component.getName() + "/" + contractName); + WSDLWriter writer = javax.wsdl.factory.WSDLFactory.newInstance().newWSDLWriter(); + writer.writeWSDL(def, System.out); + } catch (WSDLException e) { + throw new WSDLGenerationException(e); + } + } + + return def; + } + + private static boolean importPortType(PortType portType, + WSDLDefinition wsdlDef, + Definition newDef, + List<WSDLDefinition> imports) { + return addImport(portType.getQName(), PortType.class, wsdlDef, newDef, imports); + } + + private static boolean importBinding(Binding binding, + WSDLDefinition wsdlDef, + Definition newDef, + List<WSDLDefinition> imports) { + boolean ok = addImport(binding.getQName(), Binding.class, wsdlDef, newDef, imports); + if (ok) { + List bindingExtensions = binding.getExtensibilityElements(); + for (final Object extension : bindingExtensions) { + if (extension instanceof SOAPBinding) { + newDef.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/"); + } + if (extension instanceof SOAP12Binding) { + newDef.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + } + } + } + return ok; + } + + private static boolean addImport(QName name, + Class type, + WSDLDefinition wsdlDef, + Definition newDef, + List<WSDLDefinition> imports) { + String namespace = name.getNamespaceURI(); + if (newDef.getImports(namespace) == null) { + WSDLDefinition impDef = findDefinition(wsdlDef, name, type); + if (impDef != null) { + Import imp = newDef.createImport(); + imp.setNamespaceURI(namespace); + imp.setLocationURI(impDef.getURI().toString()); + imp.setDefinition(impDef.getDefinition()); + newDef.addNamespace("ns" + imports.size(), namespace); + newDef.addImport(imp); + imports.add(impDef); + return true; + } else { + // import was not added because element not found + return false; + } + } + return true; + } + + private static WSDLDefinition findDefinition(WSDLDefinition wsdlDef, QName name, Class type) { + if (wsdlDef == null || name == null) { + return wsdlDef; + } + if (wsdlDef.getURI() != null) { // not a facade + Definition def = wsdlDef.getDefinition(); + Map types = type == PortType.class ? def.getPortTypes() : def.getBindings(); + if (types.get(name) != null) { + return wsdlDef; + } + } + for (WSDLDefinition impDef : wsdlDef.getImportedDefinitions()) { + WSDLDefinition d = findDefinition(impDef, name, type); + if (d != null) { + return d; + } + } + return null; + } + + private static Port copyPort(Definition def, Port port, WebServiceBinding wsBinding) { + Port newPort = def.createPort(); + newPort.setName(port.getName()); + newPort.setBinding(port.getBinding()); + List portExtensions = port.getExtensibilityElements(); + for (final Object extension : portExtensions) { + ExtensibilityElement newExt = null; + if (extension instanceof SOAPAddress) { + def.addNamespace("SOAP11", "http://schemas.xmlsoap.org/wsdl/soap/"); + try { + newExt = def.getExtensionRegistry().createExtension( + Port.class, WSDLDefinitionGenerator.SOAP_ADDRESS); + } catch (WSDLException e) { + } + String uri = computeActualURI(wsBinding, port); + ((SOAPAddress)newExt).setLocationURI(uri); + newPort.addExtensibilityElement(newExt); + } else if (extension instanceof SOAP12Address) { + def.addNamespace("SOAP12", "http://schemas.xmlsoap.org/wsdl/soap12/"); + try { + newExt = def.getExtensionRegistry().createExtension( + Port.class, WSDLDefinitionGenerator.SOAP12_ADDRESS); + } catch (WSDLException e) { + } + String uri = computeActualURI(wsBinding, port); + ((SOAP12Address)newExt).setLocationURI(uri); + newPort.addExtensibilityElement(newExt); + } else { + // we don't support ports with other extensibility elements such as HTTPAddress + return null; + } + } + return newPort; + } + + /** + * Compute the endpoint URI based on section 2.1.1 of the WS binding Specification 1. + * The URIs in the endpoint(s) of the referenced WSDL, which may be relative + * 2. The URI specified by the wsa:Address element of the + * wsa:EndpointReference, which may be relative 3. The explicitly stated URI + * in the "uri" attribute of the binding.ws element, which may be relative, + * 4. The implicit URI as defined by in section 1.7 in the SCA Assembly Specification + * If the <binding.ws> has no wsdlElement but does have a uri attribute then + * the uri takes precedence over any implicitly used WSDL. + * + */ + private static String computeActualURI(WebServiceBinding wsBinding, Port port) { + + URI eprURI = null; + if (wsBinding.getEndPointReference() != null) { + eprURI = getEPR(wsBinding); + } + + URI wsdlURI = null; + if (wsBinding.getServiceName() != null && wsBinding.getBindingName() == null) { + // <binding.ws> explicitly points at a WSDL port, may be a relative URI + wsdlURI = getEndpoint(port); + } + + // if the WSDL port/endpoint has an absolute URI use that + if (wsdlURI != null && wsdlURI.isAbsolute()) { + return wsdlURI.toString(); + } + + // if the wsa:EndpointReference has an address element with an absolute URI use that + if (eprURI != null && eprURI.isAbsolute()) { + return eprURI.toString(); + } + + // either there is no WSDL port endpoint URI or that URI is relative + String actualURI = wsBinding.getURI(); + if (eprURI != null && eprURI.toString().length() != 0) { + // there is a relative URI in the binding EPR + actualURI = actualURI + "/" + eprURI; + } + + if (wsdlURI != null && wsdlURI.toString().length() != 0) { + // there is a relative URI in the WSDL port + actualURI = actualURI + "/" + wsdlURI; + } + + if (actualURI != null) { + actualURI = URI.create(actualURI).normalize().toString(); + } + + return actualURI; + } + + private static URI getEPR(WebServiceBinding wsBinding) { + NodeList nodeList = wsBinding.getEndPointReference().getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node childNode = nodeList.item(i); + if (childNode instanceof Element && ADDRESS.equals(childNode.getLocalName())) { + NodeList addrNodes = childNode.getChildNodes(); + for (int j = 0; j < addrNodes.getLength(); j++) { + Node addrNode = addrNodes.item(j); + if (addrNode instanceof Text) { + return URI.create(((Text)addrNode).getWholeText()); + } + } + } + } + return null; + } + + /** + * Returns the endpoint of a given port. + */ + private static URI getEndpoint(Port wsdlPort) { + if (wsdlPort != null) { + List<?> wsdlPortExtensions = wsdlPort.getExtensibilityElements(); + for (Object extension : wsdlPortExtensions) { + if (extension instanceof SOAPAddress) { + String uri = ((SOAPAddress)extension).getLocationURI(); + return (uri == null || "".equals(uri)) ? null : URI.create(uri); + } + if (extension instanceof SOAP12Address) { + SOAP12Address address = (SOAP12Address)extension; + String uri = address.getLocationURI(); + return (uri == null || "".equals(uri)) ? null : URI.create(uri); + } + } + } + return null; + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/main/resources/wsdlgen-validation-messages.properties b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/resources/wsdlgen-validation-messages.properties new file mode 100644 index 0000000000..4bfbdd2901 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/main/resources/wsdlgen-validation-messages.properties @@ -0,0 +1,31 @@ +# +# +# 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. +# +# +WsdlGenProblem = Unable to generate WSDL for {0}/{1} +WsdlGenException = Exception while generating WSDL for {0}/{1} +UnexpectedException = Exception thrown was: {0} +MissingInterfaceContract = No interface contract for {0}/{1} +InterfaceNotRemotable = Interface not remotable: {0} +IgnoringPort = Port {0}/{1} in {2}/{3} is not supported and was ignored +PortTypeNotFound = PortType {0} in {1}/{2} was not found +BindingNotFound = Binding {0} in {1}/{2} was not found +InvalidPort = Port {0}/{1} in {2}/{3} is not supported +NoValidPorts = No valid ports for service {0} in {1}/{2} +NoWsdlInterface = No WSDL interface definition for {1}/{2} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/Other.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/Other.java new file mode 100644 index 0000000000..7e6a1de546 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/Other.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.sca.binding.ws.other; + +/** + * + * @version $Rev$ $Date$ + */ +public class Other { + private String name; + + public String getName() { + return name; + } + public void setName(String name ) { + this.name = name; + } +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/package-info.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/package-info.java new file mode 100644 index 0000000000..5056760366 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/other/package-info.java @@ -0,0 +1,3 @@ +@javax.xml.bind.annotation.XmlSchema(namespace = "http://other.ws.binding.sca.tuscany.apache.org/") +package org.apache.tuscany.sca.binding.ws.other; + diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGeneratorTestCase.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGeneratorTestCase.java new file mode 100644 index 0000000000..e474c7a318 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/BindingWSDLGeneratorTestCase.java @@ -0,0 +1,86 @@ +/* + * 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.binding.ws.wsdlgen; + +import java.util.List; +import java.util.Map; + +import javax.wsdl.Definition; +import javax.wsdl.Operation; +import javax.wsdl.PortType; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.databinding.processor.DataBindingJavaInterfaceProcessor; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSFaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.xml.XSDModelResolver; +import org.osoa.sca.annotations.Remotable; + +/** + * + * @version $Rev$ $Date$ + */ +public class BindingWSDLGeneratorTestCase extends TestCase { + + public void testCreateWSDLInterfaceContract() throws InvalidInterfaceException { + DefaultModelFactoryExtensionPoint modelFactories = new DefaultModelFactoryExtensionPoint(); + WSDLFactory wsdlFactory = modelFactories.getFactory(WSDLFactory.class); + XSDFactory xsdFactory = modelFactories.getFactory(XSDFactory.class); + DefaultJavaInterfaceFactory factory = new DefaultJavaInterfaceFactory(); + JavaInterfaceContract javaIC = factory.createJavaInterfaceContract(); + JavaInterface iface = factory.createJavaInterface(HelloWorld.class); + DefaultDataBindingExtensionPoint dataBindings = new DefaultDataBindingExtensionPoint(); + JAXWSFaultExceptionMapper faultExceptionMapper = new JAXWSFaultExceptionMapper(dataBindings, null); + new JAXWSJavaInterfaceProcessor(dataBindings, faultExceptionMapper, null).visitInterface(iface); + new DataBindingJavaInterfaceProcessor(dataBindings).visitInterface(iface); + javaIC.setInterface(iface); + WSDLInterfaceContract wsdlIC = BindingWSDLGenerator.createWSDLInterfaceContract(javaIC, false, new XSDModelResolver(null, null), dataBindings, wsdlFactory, xsdFactory, null); + assertNotNull(wsdlIC); + WSDLInterface wsdlInterface = (WSDLInterface)wsdlIC.getInterface(); + assertNotNull(wsdlInterface); + assertEquals(1, wsdlInterface.getOperations().size()); + assertEquals("sayHello", wsdlInterface.getOperations().get(0).getName()); + assertNotNull(wsdlInterface.getPortType()); + + JavaInterfaceContract javaIC2 = factory.createJavaInterfaceContract(); + JavaInterface iface2 = factory.createJavaInterface(TestJavaInterface.class); + new JAXWSJavaInterfaceProcessor(dataBindings, faultExceptionMapper, null).visitInterface(iface2); + new DataBindingJavaInterfaceProcessor(dataBindings).visitInterface(iface2); + javaIC2.setInterface(iface2); + WSDLInterfaceContract wsdlIC2 = BindingWSDLGenerator.createWSDLInterfaceContract(javaIC2, false, new XSDModelResolver(null, null), dataBindings, wsdlFactory, xsdFactory, null); + assertNotNull(wsdlIC2); + } + +} + +@Remotable +interface HelloWorld { + String sayHello(String s); +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGeneratorTestCase.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGeneratorTestCase.java new file mode 100644 index 0000000000..f1e12f8ce0 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/Interface2WSDLGeneratorTestCase.java @@ -0,0 +1,66 @@ +/* + * 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.binding.ws.wsdlgen; + +import java.io.StringWriter; + +import javax.wsdl.Definition; +import javax.wsdl.xml.WSDLWriter; + +import org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint; +import org.apache.tuscany.sca.core.databinding.processor.DataBindingJavaInterfaceProcessor; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSFaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor; +import org.apache.tuscany.sca.interfacedef.wsdl.DefaultWSDLFactory; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.xsd.DefaultXSDFactory; +import org.apache.tuscany.sca.xsd.xml.XSDModelResolver; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class Interface2WSDLGeneratorTestCase { + + @Test + public void testGenerate() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(); + JavaInterface iface = iFactory.createJavaInterface(TestJavaInterface.class); + DefaultDataBindingExtensionPoint dataBindings = new DefaultDataBindingExtensionPoint(); + JAXWSFaultExceptionMapper faultExceptionMapper = new JAXWSFaultExceptionMapper(dataBindings, null); + new JAXWSJavaInterfaceProcessor(dataBindings, faultExceptionMapper, null).visitInterface(iface); + new DataBindingJavaInterfaceProcessor(dataBindings).visitInterface(iface); + DefaultModelFactoryExtensionPoint modelFactories = new DefaultModelFactoryExtensionPoint(); + WSDLDefinition wsdlDefinition = new DefaultWSDLFactory(modelFactories).createWSDLDefinition(); + DefaultXSDFactory factory = new DefaultXSDFactory(); + Interface2WSDLGenerator generator = new Interface2WSDLGenerator(false, new XSDModelResolver(null, null), dataBindings, factory, null); + Definition definition = generator.generate(iface, wsdlDefinition); + + // print the generated WSDL file and inline schemas + WSDLWriter writer = generator.getFactory().newWSDLWriter(); + StringWriter sw = new StringWriter(); + writer.writeWSDL(definition, sw); + System.out.println(sw.toString()); + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestException.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestException.java new file mode 100644 index 0000000000..1e4f802e01 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestException.java @@ -0,0 +1,47 @@ +/* + * 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.binding.ws.wsdlgen; + +/** + * + * @version $Rev$ $Date$ + */ +public class TestException extends Exception { + + private String userdata; + + public TestException(String message) { + super(message); + } + + public TestException(String message, String userdata) { + super(message); + this.userdata = userdata; + } + + public String getUserdata() { + return userdata; + } + + public void setUserdata(String userdata) { + this.userdata = userdata; + } + +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFault.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFault.java new file mode 100644 index 0000000000..da2c285bac --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFault.java @@ -0,0 +1,46 @@ +/* + * 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.binding.ws.wsdlgen; + +import javax.xml.ws.WebFault; + +/** + * + * @version $Rev$ $Date$ + */ +@WebFault(faultBean="org.apache.tuscany.sca.binding.ws.wsdlgen.TestFaultBean") +public class TestFault extends Exception { + + private TestFaultBean bean; + + public TestFault(TestFaultBean bean, String message) { + super(message); + this.bean = bean; + } + + public TestFault(TestFaultBean bean, String message, Throwable cause) { + super(message, cause); + this.bean = bean; + } + + public TestFaultBean getFaultInfo() { + return bean; + } +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFaultBean.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFaultBean.java new file mode 100644 index 0000000000..64cce0e49d --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestFaultBean.java @@ -0,0 +1,54 @@ +/* + * 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.binding.ws.wsdlgen; + +/** + * + * @version $Rev$ $Date$ + */ +public class TestFaultBean { + private String lastName; + private String firstName; + private float age; + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public float getAge() { + return age; + } + + public void setAge(float age) { + this.age = age; + } +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaClass.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaClass.java new file mode 100644 index 0000000000..3fd7361ae1 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaClass.java @@ -0,0 +1,32 @@ +/* + * 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.binding.ws.wsdlgen; +import org.apache.tuscany.sca.binding.ws.other.Other; + +/** + * + * @version $Rev$ $Date$ + */ +public class TestJavaClass { + public Other other; + public String name; + public int number; + public float balance; +} diff --git a/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaInterface.java b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaInterface.java new file mode 100644 index 0000000000..9635d65f99 --- /dev/null +++ b/branches/sca-android/modules/binding-ws-wsdlgen/src/test/java/org/apache/tuscany/sca/binding/ws/wsdlgen/TestJavaInterface.java @@ -0,0 +1,57 @@ +/* + * 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.binding.ws.wsdlgen; + +import javax.jws.WebMethod; +import javax.jws.WebService; + +import org.osoa.sca.annotations.OneWay; +import org.osoa.sca.annotations.Remotable; + +/** + * + * @version $Rev$ $Date$ + */ +@Remotable +@WebService +public interface TestJavaInterface { + String m1(String str); + + @OneWay + @WebMethod + void m2(int i); + + @WebMethod + String m3(); + + void m4(); + + @WebMethod + String m5(String str, int i); + + @WebMethod(exclude = true) + void dummy(); + + @WebMethod + void m6(TestJavaClass info) throws TestException; + + @WebMethod + void m7(TestJavaClass info) throws TestFault; +} |