diff options
Diffstat (limited to '')
147 files changed, 16090 insertions, 0 deletions
diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/LICENSE b/branches/trunk-20080910/modules/interface-java-jaxws/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/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/trunk-20080910/modules/interface-java-jaxws/NOTICE b/branches/trunk-20080910/modules/interface-java-jaxws/NOTICE new file mode 100644 index 0000000000..94481d6cfa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/pom.xml b/branches/trunk-20080910/modules/interface-java-jaxws/pom.xml new file mode 100644 index 0000000000..1a738e0f16 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/pom.xml @@ -0,0 +1,274 @@ +<?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-interface-java-jaxws</artifactId> + <name>Apache Tuscany Java Interface for JAXWS</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding-jaxb</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.2</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>javax.xml.ws</groupId> + <artifactId>jaxws-api</artifactId> + <version>2.1</version> + <exclusions> + <exclusion> + <groupId>javax.xml.soap</groupId> + <artifactId>saaj-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>asm</groupId> + <artifactId>asm-all</artifactId> + <version>3.1</version> + <scope>compile</scope> + </dependency> + + </dependencies> + + <repositories> + <repository> + <id>java.net</id> + <name>java.net Maven 1.x Repository</name> + <url>http://download.java.net/maven/1</url> + <layout>legacy</layout> + </repository> + <repository> + <id>java.net2</id> + <name>java.net Maven 2.x Repository</name> + <url>http://download.java.net/maven/2</url> + </repository> + </repositories> + + <pluginRepositories> + <pluginRepository> + <id>java.net2</id> + <name>java.net Maven 2.x Repository</name> + <url>http://download.java.net/maven/2</url> + </pluginRepository> + </pluginRepositories> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Djava.endorsed.dirs=target/endorsed</argLine> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy</id> + <phase>generate-sources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>javax.xml.ws</groupId> + <artifactId>jaxws-api</artifactId> + <version>2.1</version> + <type>jar</type> + </artifactItem> + <artifactItem> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.1</version> + <type>jar</type> + </artifactItem> + </artifactItems> + <outputDirectory>${project.build.directory}/endorsed</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.0</version> + <executions> + <execution> + <id>add-test-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>target/jaxws-source</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>jaxws-maven-plugin</artifactId> + <version>1.9</version> + <executions> + <execution> + <id>wsimport</id> + <phase>generate-test-sources</phase> + <goals> + <goal>wsimport</goal> + </goals> + <configuration> + <packageName>com.example.stock</packageName> + <wsdlDirectory>${basedir}/src/test/resources/wsdl</wsdlDirectory> + <wsdlFiles> + <wsdlFile>StockExceptionTest.wsdl</wsdlFile> + </wsdlFiles> + <sourceDestDir>${project.build.directory}/jaxws-source</sourceDestDir> + <verbose>false</verbose> + <xnocompile>true</xnocompile> + </configuration> + </execution> + + <!-- + <execution> + <id>wsgen</id> + <phase>process-test-classes</phase> + <goals> + <goal>wsgen-test</goal> + </goals> + <configuration> + <sei>org.apache.tuscany.sca.interfacedef.java.jaxws.MyServiceImpl</sei> + <genWsdl>true</genWsdl> + <keep>true</keep> + <resourceDestDir>${project.build.directory}/jaxws-source</resourceDestDir> + <sourceDestDir>${project.build.directory}/jaxws-source</sourceDestDir> + </configuration> + </execution> + --> + </executions> + + </plugin> + + <!-- + wsimport cannot handle WSDL files without a service/binding element. + CXF wsdl2java plugin does support that. I had to override the default + value of wsdlRoot/testWsdlRoot to a non-existent file to avoid NPE --> + <!-- + <plugin> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-codegen-plugin</artifactId> + <version>2.1</version> + <executions> + <execution> + <id>generate-sources</id> + <phase>generate-sources</phase> + + <configuration> + <sourceRoot>${basedir}/target/jaxws-source</sourceRoot> + <wsdlRoot>NONE</wsdlRoot> + <testWsdlRoot>NONE</testWsdlRoot> + <wsdlOptions> + <wsdlOption> + <wsdl>${basedir}/src/test/resources/wsdl/Stock.wsdl</wsdl> + <outputDir>${basedir}/target/jaxws-source</outputDir> + <packagenames> + <packagename>com.example.stock.cxf</packagename> + </packagenames> + </wsdlOption> + </wsdlOptions> + </configuration> + <goals> + <goal>wsdl2java</goal> + </goals> + </execution> + </executions> + </plugin> + --> + + <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.interface.java.jaxws</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef.java.jaxws*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>default-tools.jar</id> + <activation> + <property> + <name>java.vendor</name> + <value>Sun Microsystems Inc.</value> + </property> + </activation> + <dependencies> + <dependency> + <groupId>com.sun</groupId> + <artifactId>tools</artifactId> + <version>1.5.0</version> + <scope>system</scope> + <systemPath>${java.home}/../lib/tools.jar</systemPath> + </dependency> + </dependencies> + </profile> + </profiles> + +</project> diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java new file mode 100644 index 0000000000..4cf56fed0c --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java @@ -0,0 +1,539 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.xml.bind.annotation.XmlAttachmentRef; +import javax.xml.bind.annotation.XmlList; +import javax.xml.bind.annotation.XmlMimeType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.ws.Holder; + +import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public abstract class BaseBeanGenerator implements Opcodes { + private static final Map<String, String> COLLECTION_CLASSES = new HashMap<String, String>(); + static { + COLLECTION_CLASSES.put("Ljava/util/Collection;", "java/util/ArrayList"); + COLLECTION_CLASSES.put("Ljava/util/List;", "java/util/ArrayList"); + COLLECTION_CLASSES.put("Ljava/util/Set;", "java/util/HashSet"); + COLLECTION_CLASSES.put("Ljava/util/Queue;", "java/util/LinkedList"); + } + private final static Class[] KNOWN_JAXB_ANNOTATIONS = + {XmlAttachmentRef.class, XmlMimeType.class, XmlJavaTypeAdapter.class, XmlList.class}; + private static final Map<String, String> JAVA_KEYWORDS = new HashMap<String, String>(); + + static { + JAVA_KEYWORDS.put("abstract", "_abstract"); + JAVA_KEYWORDS.put("assert", "_assert"); + JAVA_KEYWORDS.put("boolean", "_boolean"); + JAVA_KEYWORDS.put("break", "_break"); + JAVA_KEYWORDS.put("byte", "_byte"); + JAVA_KEYWORDS.put("case", "_case"); + JAVA_KEYWORDS.put("catch", "_catch"); + JAVA_KEYWORDS.put("char", "_char"); + JAVA_KEYWORDS.put("class", "_class"); + JAVA_KEYWORDS.put("const", "_const"); + JAVA_KEYWORDS.put("continue", "_continue"); + JAVA_KEYWORDS.put("default", "_default"); + JAVA_KEYWORDS.put("do", "_do"); + JAVA_KEYWORDS.put("double", "_double"); + JAVA_KEYWORDS.put("else", "_else"); + JAVA_KEYWORDS.put("extends", "_extends"); + JAVA_KEYWORDS.put("false", "_false"); + JAVA_KEYWORDS.put("final", "_final"); + JAVA_KEYWORDS.put("finally", "_finally"); + JAVA_KEYWORDS.put("float", "_float"); + JAVA_KEYWORDS.put("for", "_for"); + JAVA_KEYWORDS.put("goto", "_goto"); + JAVA_KEYWORDS.put("if", "_if"); + JAVA_KEYWORDS.put("implements", "_implements"); + JAVA_KEYWORDS.put("import", "_import"); + JAVA_KEYWORDS.put("instanceof", "_instanceof"); + JAVA_KEYWORDS.put("int", "_int"); + JAVA_KEYWORDS.put("interface", "_interface"); + JAVA_KEYWORDS.put("long", "_long"); + JAVA_KEYWORDS.put("native", "_native"); + JAVA_KEYWORDS.put("new", "_new"); + JAVA_KEYWORDS.put("null", "_null"); + JAVA_KEYWORDS.put("package", "_package"); + JAVA_KEYWORDS.put("private", "_private"); + JAVA_KEYWORDS.put("protected", "_protected"); + JAVA_KEYWORDS.put("public", "_public"); + JAVA_KEYWORDS.put("return", "_return"); + JAVA_KEYWORDS.put("short", "_short"); + JAVA_KEYWORDS.put("static", "_static"); + JAVA_KEYWORDS.put("strictfp", "_strictfp"); + JAVA_KEYWORDS.put("super", "_super"); + JAVA_KEYWORDS.put("switch", "_switch"); + JAVA_KEYWORDS.put("synchronized", "_synchronized"); + JAVA_KEYWORDS.put("this", "_this"); + JAVA_KEYWORDS.put("throw", "_throw"); + JAVA_KEYWORDS.put("throws", "_throws"); + JAVA_KEYWORDS.put("transient", "_transient"); + JAVA_KEYWORDS.put("true", "_true"); + JAVA_KEYWORDS.put("try", "_try"); + JAVA_KEYWORDS.put("void", "_void"); + JAVA_KEYWORDS.put("volatile", "_volatile"); + JAVA_KEYWORDS.put("while", "_while"); + JAVA_KEYWORDS.put("enum", "_enum"); + } + + protected static final Map<Object, Class<?>> generatedClasses = + Collections.synchronizedMap(new WeakHashMap<Object, Class<?>>()); + + protected XMLAdapterExtensionPoint xmlAdapters; + + public byte[] defineClass(ClassWriter cw, + String classDescriptor, + String classSignature, + String namespace, + String name, + BeanProperty[] properties) { + // Declare the class + declareClass(cw, classDescriptor); + + // Compute the propOrder + String[] propOrder = null; + if (properties != null && properties.length > 0) { + int size = properties.length; + propOrder = new String[size]; + for (int i = 0; i < size; i++) { + propOrder[i] = getFieldName(properties[i].getName()); + } + } + // Annotate the class + annotateClass(cw, name, namespace, propOrder); + + // Decalre the default constructor + declareConstructor(cw, classSignature); + if (properties != null) { + for (BeanProperty p : properties) { + boolean isElement = p.isElement() && (!Map.class.isAssignableFrom(p.getType())); + String xmlAdapterClassSignature = null; + if (xmlAdapters != null) { + Class<?> adapterClass = xmlAdapters.getAdapter(p.getType()); + if (adapterClass != null) { + xmlAdapterClassSignature = CodeGenerationHelper.getSignature(adapterClass); + } + } + declareProperty(cw, classDescriptor, classSignature, p.getName(), p.getSignature(), p + .getGenericSignature(), isElement, p.isNillable(), xmlAdapterClassSignature, p.getJaxbAnnotaions()); + } + } + + // Close the generation + cw.visitEnd(); + return cw.toByteArray(); + } + + protected static boolean isHolder(java.lang.reflect.Type type) { + if (type instanceof ParameterizedType) { + Class<?> cls = CodeGenerationHelper.getErasure(type); + return cls == Holder.class; + } + return false; + } + + protected static java.lang.reflect.Type getHolderValueType(java.lang.reflect.Type paramType) { + if (paramType instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType)paramType; + Class<?> cls = CodeGenerationHelper.getErasure(p); + if (cls == Holder.class) { + return p.getActualTypeArguments()[0]; + } + } + return paramType; + } + + protected void declareProperty(ClassWriter cw, + String classDescriptor, + String classSignature, + String propName, + String propClassSignature, + String propTypeSignature, + boolean isElement, + boolean isNillable, + String xmlAdapterClassSignature, + List<Annotation> jaxbAnnotations) { + if (propClassSignature.equals(propTypeSignature)) { + propTypeSignature = null; + } + declareField(cw, + propName, + propClassSignature, + propTypeSignature, + isElement, + isNillable, + xmlAdapterClassSignature, + jaxbAnnotations); + decalreGetter(cw, classDescriptor, classSignature, propName, propClassSignature, propTypeSignature); + declareSetter(cw, classDescriptor, classSignature, propName, propClassSignature, propTypeSignature); + } + + protected String getFieldName(String propName) { + String name = JAVA_KEYWORDS.get(propName); + return name != null ? name : propName; + } + + protected void declareField(ClassWriter cw, + String propName, + String propClassSignature, + String propTypeSignature, + boolean isElement, + boolean isNillable, + String xmlAdapterClassSignature, + List<Annotation> jaxbAnnotations) { + FieldVisitor fv; + AnnotationVisitor av0; + fv = cw.visitField(ACC_PROTECTED, getFieldName(propName), propClassSignature, propTypeSignature, null); + + // For Map property, we cannot have the XmlElement annotation + if (isElement) { + av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlElement;", true); + av0.visit("name", propName); + av0.visit("namespace", ""); + if (isNillable) { + av0.visit("nillable", Boolean.TRUE); + } + // FIXME: + // av0.visit("required", Boolean.FALSE); + av0.visitEnd(); + } + + if (xmlAdapterClassSignature != null) { + av0 = fv.visitAnnotation("Ljavax/xml/bind/annotation/adapters/XmlJavaTypeAdapter;", true); + av0.visit("value", org.objectweb.asm.Type.getType(xmlAdapterClassSignature)); + av0.visitEnd(); + } + + for (Annotation ann : jaxbAnnotations) { + if (ann instanceof XmlMimeType) { + AnnotationVisitor mime = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlMimeType;", true); + mime.visit("value", ((XmlMimeType)ann).value()); + mime.visitEnd(); + } else if (ann instanceof XmlJavaTypeAdapter) { + AnnotationVisitor ada = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlJavaTypeAdapter;", true); + ada.visit("value", ((XmlJavaTypeAdapter)ann).value()); + ada.visit("type", ((XmlJavaTypeAdapter)ann).type()); + ada.visitEnd(); + } else if (ann instanceof XmlAttachmentRef) { + AnnotationVisitor att = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlAttachmentRef;", true); + att.visitEnd(); + } else if (ann instanceof XmlList) { + AnnotationVisitor list = fv.visitAnnotation("Ljavax/xml/bind/annotation/XmlList;", true); + list.visitEnd(); + } + } + + fv.visitEnd(); + } + + protected void declareSetter(ClassWriter cw, + String classDescriptor, + String classSignature, + String propName, + String propClassSignature, + String propTypeSignature) { + if ("Ljava/util/List;".equals(propClassSignature)) { + return; + } + MethodVisitor mv = + cw.visitMethod(ACC_PUBLIC, + "set" + capitalize(propName), + "(" + propClassSignature + ")V", + propTypeSignature == null ? null : "(" + propTypeSignature + ")V", + null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + // mv.visitLineNumber(57, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(CodeGenerationHelper.getLoadOPCode(propClassSignature), 1); + mv.visitFieldInsn(PUTFIELD, classDescriptor, getFieldName(propName), propClassSignature); + Label l1 = new Label(); + mv.visitLabel(l1); + // mv.visitLineNumber(58, l1); + mv.visitInsn(RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLocalVariable("this", classSignature, null, l0, l2, 0); + mv.visitLocalVariable(getFieldName(propName), propClassSignature, propTypeSignature, l0, l2, 1); + mv.visitMaxs(3, 3); + mv.visitEnd(); + + } + + protected void decalreGetter(ClassWriter cw, + String classDescriptor, + String classSignature, + String propName, + String propClassSignature, + String propTypeSignature) { + String collectionImplClass = COLLECTION_CLASSES.get(propClassSignature); + if (collectionImplClass != null) { + decalreCollectionGetter(cw, + classDescriptor, + classSignature, + propName, + propClassSignature, + propTypeSignature, + collectionImplClass); + return; + } + + String getterName = ("Z".equals(propClassSignature) ? "is" : "get") + capitalize(propName); + MethodVisitor mv = + cw.visitMethod(ACC_PUBLIC, getterName, "()" + propClassSignature, propTypeSignature == null ? null + : "()" + propTypeSignature, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + // mv.visitLineNumber(48, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, classDescriptor, getFieldName(propName), propClassSignature); + mv.visitInsn(CodeGenerationHelper.getReturnOPCode(propClassSignature)); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", classSignature, null, l0, l1, 0); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + + protected void decalreCollectionGetter(ClassWriter cw, + String classDescriptor, + String classSignature, + String propName, + String propClassSignature, + String propTypeSignature, + String collectionImplClass) { + String getterName = "get" + capitalize(propName); + String fieldName = getFieldName(propName); + MethodVisitor mv = + cw.visitMethod(ACC_PUBLIC, getterName, "()" + propClassSignature, propTypeSignature == null ? null + : "()" + propTypeSignature, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitLineNumber(63, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, classDescriptor, fieldName, propClassSignature); + Label l1 = new Label(); + mv.visitJumpInsn(IFNONNULL, l1); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitLineNumber(64, l2); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(NEW, collectionImplClass); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, collectionImplClass, "<init>", "()V"); + mv.visitFieldInsn(PUTFIELD, classDescriptor, fieldName, propClassSignature); + mv.visitLabel(l1); + mv.visitLineNumber(66, l1); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, classDescriptor, fieldName, propClassSignature); + mv.visitInsn(ARETURN); + Label l3 = new Label(); + mv.visitLabel(l3); + mv.visitLocalVariable("this", classSignature, null, l0, l3, 0); + mv.visitMaxs(3, 1); + mv.visitEnd(); + } + + protected static String capitalize(String name) { + if (name == null || name.length() == 0) { + return name; + } else { + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + } + + protected void declareConstructor(ClassWriter cw, String classSignature) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + // mv.visitLineNumber(37, l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", classSignature, null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + protected void declareClass(ClassWriter cw, String classDescriptor) { + cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, classDescriptor, null, "java/lang/Object", null); + } + + protected void annotateClass(ClassWriter cw, String name, String namespace, String[] propOrder) { + AnnotationVisitor av0; + // @XmlRootElement + av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlRootElement;", true); + av0.visit("name", name); + av0.visit("namespace", namespace); + av0.visitEnd(); + // @XmlAccessorType + av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlAccessorType;", true); + av0.visitEnum("value", "Ljavax/xml/bind/annotation/XmlAccessType;", "FIELD"); + av0.visitEnd(); + // @XmlType + av0 = cw.visitAnnotation("Ljavax/xml/bind/annotation/XmlType;", true); + av0.visit("name", name); + av0.visit("namespace", namespace); + if (propOrder != null) { + AnnotationVisitor pv = av0.visitArray("propOrder"); + for (String p : propOrder) { + pv.visit(null, p); + } + pv.visitEnd(); + } + av0.visitEnd(); + } + + public Class<?> generate(String classDescriptor, + String classSignature, + String namespace, + String name, + BeanProperty[] properties, + GeneratedClassLoader classLoader) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + byte[] byteCode = defineClass(cw, classDescriptor, classSignature, namespace, name, properties); + String className = classDescriptor.replace('/', '.'); + Class<?> generated = classLoader.getGeneratedClass(className, byteCode); + return generated; + } + + public static class BeanProperty { + private Class<?> type; + private String namespace; + private String name; + private String signature; + private String genericSignature; + private List<Annotation> jaxbAnnotaions = new ArrayList<Annotation>(); + private boolean element; + private boolean nillable; + + public BeanProperty(String namespace, String name, Class<?> javaClass, Type type, boolean isElement) { + super(); + this.namespace = namespace; + this.name = name; + this.signature = CodeGenerationHelper.getJAXWSSignature(javaClass); + this.type = javaClass; + this.genericSignature = CodeGenerationHelper.getJAXWSSignature(type); + this.element = isElement; + // FIXME: How to test nillable? + // this.nillable = (type instanceof GenericArrayType) || Collection.class.isAssignableFrom(javaClass) || javaClass.isArray(); + // TUSCANY-2389: Set the nillable consistent with what wsgen produces + this.nillable = javaClass.isArray(); + } + + public String getName() { + return name; + } + + public String getSignature() { + return signature; + } + + public String getGenericSignature() { + return genericSignature; + } + + public Class<?> getType() { + return type; + } + + public List<Annotation> getJaxbAnnotaions() { + return jaxbAnnotaions; + } + + public String getNamespace() { + return namespace; + } + + public boolean isElement() { + return element; + } + + public boolean isNillable() { + return nillable; + } + } + + public XMLAdapterExtensionPoint getXmlAdapters() { + return xmlAdapters; + } + + public void setXmlAdapters(XMLAdapterExtensionPoint xmlAdapters) { + this.xmlAdapters = xmlAdapters; + } + + protected static <T extends Annotation> T findAnnotation(Annotation[] anns, Class<T> annotationClass) { + for (Annotation a : anns) { + if (a.annotationType() == annotationClass) { + return annotationClass.cast(a); + } + } + return null; + } + + protected static List<Annotation> findJAXBAnnotations(Annotation[] anns) { + List<Annotation> jaxbAnnotation = new ArrayList<Annotation>(); + for (Class<? extends Annotation> c : KNOWN_JAXB_ANNOTATIONS) { + Annotation a = findAnnotation(anns, c); + if (a != null) { + jaxbAnnotation.add(a); + } + } + return jaxbAnnotation; + } + + protected List<Annotation> findJAXBAnnotations(Method method) { + List<Annotation> anns = new ArrayList<Annotation>(); + for (Class<? extends Annotation> c : KNOWN_JAXB_ANNOTATIONS) { + Annotation ann = method.getAnnotation(c); + if (ann != null) { + anns.add(ann); + } + } + return anns; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/CodeGenerationHelper.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/CodeGenerationHelper.java new file mode 100644 index 0000000000..b05715b54e --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/CodeGenerationHelper.java @@ -0,0 +1,280 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.Opcodes; + +/** + * @version $Rev$ $Date$ + */ +public class CodeGenerationHelper { + /** + * @param type + * @return + */ + public static Class<?> getErasure(Type type) { + if (type instanceof Class) { + return (Class<?>)type; + } else if (type instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType)type; + Class<?> componentType = getErasure(arrayType.getGenericComponentType()); + return Array.newInstance(componentType, 0).getClass(); + } else if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + return getErasure(pType.getRawType()); + } else if (type instanceof WildcardType) { + WildcardType wType = (WildcardType)type; + Type[] types = wType.getUpperBounds(); + if (types.length == 0) { + return Object.class; + } + return getErasure(types[0]); + } else if (type instanceof TypeVariable) { + TypeVariable<?> var = (TypeVariable<?>)type; + Type[] types = var.getBounds(); + if (types.length == 0) { + return Object.class; + } + return getErasure(types[0]); + } + return null; + } + + /** + * @param type + * @return + */ + public static String getJAXWSSignature(Type type) { + Class<?> cls = getErasure(type); + if (Collection.class.isAssignableFrom(cls) && (type instanceof ParameterizedType)) { + ParameterizedType pType = (ParameterizedType)type; + Type p = pType.getActualTypeArguments()[0]; + StringBuffer sb = new StringBuffer(); + sb.append(getSignature(cls)); + sb.deleteCharAt(sb.length() - 1); // Remove ; + sb.append('<').append(getSignature(getErasure(p))).append(">;"); + return sb.toString(); + } else if (Map.class.isAssignableFrom(cls) && (type instanceof ParameterizedType)) { + ParameterizedType pType = (ParameterizedType)type; + Type key = pType.getActualTypeArguments()[0]; + Type value = pType.getActualTypeArguments()[1]; + StringBuffer sb = new StringBuffer(); + sb.append(getSignature(cls)); + sb.deleteCharAt(sb.length() - 1); // Remove ; + sb.append('<').append(getSignature(getErasure(key))).append(getSignature(getErasure(value))).append(">;"); + return sb.toString(); + } else { + return getSignature(cls); + } + } + + /** + * @param type + * @return + */ + public static String getSignature(Type type) { + if (!(type instanceof Class)) { + if (type instanceof ParameterizedType) { + ParameterizedType pType = (ParameterizedType)type; + StringBuffer sb = new StringBuffer(); + String rawType = getSignature(pType.getRawType()); + sb.append(rawType.substring(0, rawType.length() - 1)); + sb.append('<'); + for (Type t : pType.getActualTypeArguments()) { + String argType = getSignature(t); + sb.append(argType); + } + sb.append('>'); + sb.append(rawType.substring(rawType.length() - 1)); + return sb.toString(); + } + if (type instanceof TypeVariable) { + return "T" + ((TypeVariable<?>)type).getName() + ";"; + } + if (type instanceof GenericArrayType) { + GenericArrayType arrayType = (GenericArrayType)type; + return "[" + getSignature(arrayType.getGenericComponentType()); + } + if (type instanceof WildcardType) { + WildcardType wType = (WildcardType)type; + Type[] types = wType.getUpperBounds(); + StringBuffer sb = new StringBuffer(); + if (types.length == 0 || !(types.length == 1 && types[0] == Object.class)) { + sb.append('+'); + for (Type t : types) { + sb.append(getSignature(t)); + } + } + types = wType.getLowerBounds(); + if (types.length != 0) { + sb.append('-'); + for (Type t : wType.getLowerBounds()) { + sb.append(getSignature(t)); + } + } + if (sb.length() == 0) { + return "*"; + } + return sb.toString(); + } + } + Class<?> cls = (Class<?>)type; + return org.objectweb.asm.Type.getDescriptor(cls); + } + + /** + * Get the actual type arguments a child class has used to extend a generic base class. + * + * @param baseClass the base class + * @param childClass the child class + * @return a list of the raw classes for the actual type arguments. + */ + public static <T> List<Class<?>> resovleTypeArguments(Class<T> baseClass, Class<? extends T> childClass) { + Map<Type, Type> resolvedTypes = new HashMap<Type, Type>(); + Type type = childClass; + // start walking up the inheritance hierarchy until we hit baseClass + while (!getErasure(type).equals(baseClass)) { + if (type instanceof Class) { + // there is no useful information for us in raw types, so just keep going. + type = ((Class<?>)type).getGenericSuperclass(); + } else { + ParameterizedType parameterizedType = (ParameterizedType)type; + Class<?> rawType = getErasure(parameterizedType.getRawType()); + + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + TypeVariable<?>[] typeParameters = rawType.getTypeParameters(); + for (int i = 0; i < actualTypeArguments.length; i++) { + resolvedTypes.put(typeParameters[i], actualTypeArguments[i]); + } + + if (!rawType.equals(baseClass)) { + type = rawType.getGenericSuperclass(); + } + } + } + + // finally, for each actual type argument provided to baseClass, determine (if possible) + // the raw class for that type argument. + Type[] actualTypeArguments; + if (type instanceof Class) { + actualTypeArguments = ((Class<?>)type).getTypeParameters(); + } else { + actualTypeArguments = ((ParameterizedType)type).getActualTypeArguments(); + } + List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>(); + // resolve types by chasing down type variables. + for (Type baseType : actualTypeArguments) { + while (resolvedTypes.containsKey(baseType)) { + baseType = resolvedTypes.get(baseType); + } + typeArgumentsAsClasses.add(getErasure(baseType)); + } + return typeArgumentsAsClasses; + } + + /* + signatures.put(boolean.class, "Z"); + signatures.put(byte.class, "B"); + signatures.put(char.class, "C"); + signatures.put(short.class, "S"); + signatures.put(int.class, "I"); + signatures.put(long.class, "J"); + signatures.put(float.class, "F"); + signatures.put(double.class, "D"); + */ + public static int getLoadOPCode(String signature) { + if ("Z".equals(signature) || "B".equals(signature) + || "C".equals(signature) + || "S".equals(signature) + || "I".equals(signature)) { + return Opcodes.ILOAD; + } + + if ("J".equals(signature)) { + return Opcodes.LLOAD; + } + + if ("F".equals(signature)) { + return Opcodes.FLOAD; + } + + if ("D".equals(signature)) { + return Opcodes.DLOAD; + } + + return Opcodes.ALOAD; + + } + + public static int getReturnOPCode(String signature) { + if ("Z".equals(signature) || "B".equals(signature) + || "C".equals(signature) + || "S".equals(signature) + || "I".equals(signature)) { + return Opcodes.IRETURN; + } + + if ("J".equals(signature)) { + return Opcodes.LRETURN; + } + + if ("F".equals(signature)) { + return Opcodes.FRETURN; + } + + if ("D".equals(signature)) { + return Opcodes.DRETURN; + } + if ("V".equals(signature)) { + return Opcodes.RETURN; + } + + return Opcodes.ARETURN; + + } + + /** + * Get the package prefix for generated JAXWS artifacts + * @param cls + * @return + */ + public static String getPackagePrefix(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + if (index == -1) { + return "jaxws."; + } else { + return name.substring(0, index) + ".jaxws."; + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java new file mode 100644 index 0000000000..40fbefa3ed --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import javax.xml.namespace.QName; +import javax.xml.ws.WebFault; + +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.objectweb.asm.ClassWriter; + +public class FaultBeanGenerator extends BaseBeanGenerator { + public FaultBeanGenerator() { + super(); + } + + protected BeanProperty[] getProperties(Class<? extends Throwable> exceptionClass) { + BeanInfo beanInfo; + try { + beanInfo = Introspector.getBeanInfo(exceptionClass); + } catch (IntrospectionException e) { + throw new IllegalArgumentException(e); + } + List<BeanProperty> props = new ArrayList<BeanProperty>(); + for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { + if (pd.getReadMethod() != null) { + String name = pd.getReadMethod().getName(); + if ("getClass".equals(name) || "getStackTrace".equals(name) + || "getCause".equals(name) + || "getLocalizedMessage".equals(name)) { + continue; + } + // Add the field + String field = pd.getName(); + Method getter = pd.getReadMethod(); + props.add(new BeanProperty("", field, getter.getReturnType(), getter.getGenericReturnType(), false)); + } + } + Collections.sort(props, new Comparator<BeanProperty>() { + public int compare(BeanProperty o1, BeanProperty o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + return props.toArray(new BeanProperty[0]); + } + + public byte[] generate(Class<? extends Throwable> exceptionClass) { + String className = getFaultBeanName(exceptionClass); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + String classDescriptor = className.replace('.', '/'); + String classSignature = "L" + classDescriptor + ";"; + QName element = getElementName(exceptionClass); + String namespace = element.getNamespaceURI(); + String name = element.getLocalPart(); + return defineClass(cw, classDescriptor, classSignature, namespace, name, getProperties(exceptionClass)); + } + + public Class<?> generate(Class<? extends Throwable> exceptionClass, GeneratedClassLoader cl) { + synchronized (exceptionClass) { + Class<?> faultBeanClass = generatedClasses.get(exceptionClass); + if (faultBeanClass == null) { + String className = getFaultBeanName(exceptionClass); + String classDescriptor = className.replace('.', '/'); + String classSignature = "L" + classDescriptor + ";"; + QName element = getElementName(exceptionClass); + String namespace = element.getNamespaceURI(); + String name = element.getLocalPart(); + faultBeanClass = + generate(classDescriptor, classSignature, namespace, name, getProperties(exceptionClass), cl); + generatedClasses.put(exceptionClass, faultBeanClass); + } + return faultBeanClass; + } + } + + private static String getFaultBeanName(Class<?> exceptionClass) { + String faultBeanName = null; + WebFault webFault = exceptionClass.getAnnotation(WebFault.class); + if (webFault != null) { + faultBeanName = webFault.faultBean(); + if (!"".equals(faultBeanName)) { + return faultBeanName; + } + } + + String name = exceptionClass.getName(); + int index = name.lastIndexOf('.'); + String pkg = name.substring(0, index); + String clsName = name.substring(index + 1); + + // FIXME: [rfeng] This is a workaround to avoid "Prohibited package name: java.lang.jaxws" + if (pkg.startsWith("java.") || pkg.startsWith("javax.")) { + pkg = "tuscany"; + } + faultBeanName = (pkg + ".jaxws." + clsName + "Bean"); + return faultBeanName; + } + + public static QName getElementName(Class<? extends Throwable> exceptionClass) { + WebFault webFault = exceptionClass.getAnnotation(WebFault.class); + String namespace = null; + String name = null; + if (webFault != null) { + namespace = webFault.targetNamespace(); + name = webFault.name(); + } + if (namespace == null) { + namespace = JavaInterfaceUtil.getNamespace(exceptionClass); + } + if (name == null) { + name = exceptionClass.getSimpleName(); + } + return new QName(namespace, name); + } + + public static Class<?> generateFaultBeanClass(Class<? extends Throwable> exceptionClass) { + FaultBeanGenerator generator = new FaultBeanGenerator(); + GeneratedClassLoader cl = new GeneratedClassLoader(exceptionClass.getClassLoader()); + return generator.generate(exceptionClass, cl); + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedClassLoader.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedClassLoader.java new file mode 100644 index 0000000000..f36dd3a443 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedClassLoader.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.security.SecureClassLoader; +import java.util.HashMap; +import java.util.Map; + +public class GeneratedClassLoader extends SecureClassLoader { + private class GeneratedClass { + private String className; + private byte[] byteCode; + private Class<?> cls; + + public GeneratedClass(String className, byte[] byteCode) { + super(); + this.className = className; + this.byteCode = byteCode; + } + + public synchronized Class<?> getGeneratedClass() { + if (cls == null) { + cls = defineClass(className, byteCode, 0, byteCode.length); + } + return cls; + } + } + + private Map<String, GeneratedClass> generatedClasses = new HashMap<String, GeneratedClass>(); + + public GeneratedClassLoader(ClassLoader parentLoader) { + super(parentLoader); + } + + @Override + protected Class<?> findClass(String className) throws ClassNotFoundException { + GeneratedClass cls = generatedClasses.get(className); + if (cls != null) { + return cls.getGeneratedClass(); + } + return super.findClass(className); + } + + public synchronized Class<?> getGeneratedClass(String className, byte[] byteCode) { + GeneratedClass cls = generatedClasses.get(className); + if (cls == null) { + cls = new GeneratedClass(className, byteCode); + generatedClasses.put(className, cls); + } + return cls.getGeneratedClass(); + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedDataTypeImpl.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedDataTypeImpl.java new file mode 100644 index 0000000000..c3f568ef48 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/GeneratedDataTypeImpl.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * A special data type that generate the class on demand + * @version $Rev$ $Date$ + */ +public class GeneratedDataTypeImpl implements DataType<XMLType> { + private XMLAdapterExtensionPoint xmlAdapters; + + private Class<?> physical; + private XMLType logical; + + private Map<Class<?>, Object> metaDataMap; + private Method method; + private String wrapperClassName; + private String wrapperNamespace; + private String wrapperName; + private boolean request; + private GeneratedClassLoader classLoader; + + private Class<? extends Throwable> exceptionClass; + + public GeneratedDataTypeImpl(XMLAdapterExtensionPoint xmlAdapters, Class<? extends Throwable> exceptionClass, GeneratedClassLoader cl) { + super(); + this.exceptionClass = exceptionClass; + this.classLoader = cl; + QName name = FaultBeanGenerator.getElementName(exceptionClass); + this.logical = new XMLType(name, name); + this.xmlAdapters = xmlAdapters; + } + + public GeneratedDataTypeImpl(XMLAdapterExtensionPoint xmlAdapters, + Method m, + String wrapperClassName, + String wrapperNamespace, + String wrapperName, + boolean request, + GeneratedClassLoader cl) { + super(); + this.method = m; + this.wrapperClassName = wrapperClassName; + this.wrapperNamespace = wrapperNamespace; + this.wrapperName = wrapperName; + this.classLoader = cl; + this.request = request; + QName name = new QName(wrapperNamespace, wrapperName); + this.logical = new XMLType(name, name); + this.xmlAdapters = xmlAdapters; + } + + public String getDataBinding() { + return JAXBDataBinding.NAME; + } + + public Type getGenericType() { + return getPhysical(); + } + + public XMLType getLogical() { + return logical; + } + + public synchronized Class<?> getPhysical() { + if (physical == null) { + if (method != null) { + WrapperBeanGenerator generator = new WrapperBeanGenerator(); + generator.setXmlAdapters(xmlAdapters); + physical = + request ? generator.generateRequestWrapper(method, wrapperClassName, wrapperNamespace, wrapperName, classLoader) + : generator.generateResponseWrapper(method, wrapperClassName, wrapperNamespace, wrapperName, classLoader); + ; + } else if (exceptionClass != null) { + FaultBeanGenerator faultBeanGenerator = new FaultBeanGenerator(); + faultBeanGenerator.setXmlAdapters(xmlAdapters); + physical = faultBeanGenerator.generate(exceptionClass, classLoader); + } + } + return physical; + } + + public void setDataBinding(String dataBinding) { + // NOP + } + + public void setGenericType(Type genericType) { + // NOP + } + + public void setLogical(XMLType logical) { + this.logical = logical; + } + + public void setPhysical(Class<?> cls) { + // NOP + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public <T> T getMetaData(Class<T> type) { + return metaDataMap == null ? null : type.cast(metaDataMap.get(type)); + } + + public <T> void setMetaData(Class<T> type, T metaData) { + if (metaDataMap == null) { + metaDataMap = new ConcurrentHashMap<Class<?>, Object>(); + } + metaDataMap.put(type, metaData); + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java new file mode 100644 index 0000000000..75a0aa8131 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSFaultExceptionMapper.java @@ -0,0 +1,370 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.xml.namespace.QName; +import javax.xml.ws.WebFault; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.util.FaultException; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.ServiceRuntimeException; + +/** + * JAX-WS ExceptionHandler + * + * @version $Rev$ $Date$ + */ +public class JAXWSFaultExceptionMapper implements FaultExceptionMapper { + public static final String GETCAUSE = "getCause"; + public static final String GETLOCALIZEDMESSAGE = "getLocalizedMessage"; + public static final String GETSTACKTRACE = "getStackTrace"; + public static final String GETCLASS = "getClass"; + + private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0]; + private DataBindingExtensionPoint dataBindingExtensionPoint; + private XMLAdapterExtensionPoint xmlAdapterExtensionPoint; + + + public JAXWSFaultExceptionMapper(DataBindingExtensionPoint dataBindingExtensionPoint, XMLAdapterExtensionPoint xmlAdapters) { + super(); + this.dataBindingExtensionPoint = dataBindingExtensionPoint; + this.xmlAdapterExtensionPoint = xmlAdapters; + } + + /** + * The following is quoted from the JAX-WS Specification v2.1 + * <ul> + * <li>WrapperException(String message, FaultBean faultInfo) <br> + * A constructor where WrapperException is replaced with the name of the + * generated wrapper exception and FaultBean is replaced by the name of the + * generated fault bean. + * <li> WrapperException(String message, FaultBean faultInfo, Throwable + * cause) <br> + * A constructor where WrapperException is replaced with the name of the + * generated wrapper exception and FaultBean is replaced by the name of the + * generated fault bean. The last argument, cause, may be used to convey + * protocol specific fault information + * </ul> + */ + @SuppressWarnings("unchecked") + public Throwable wrapFaultInfo(DataType<DataType> exceptionType, String message, Object faultInfo, Throwable cause, Operation operation) { + Class<?> exceptionClass = exceptionType.getPhysical(); + if (exceptionClass.isInstance(faultInfo)) { + return (Throwable)faultInfo; + } + DataType<?> faultBeanType = exceptionType.getLogical(); + Class<?> faultBeanClass = faultBeanType.getPhysical(); + try { + Throwable exc = + newInstance((Class<? extends Throwable>)exceptionClass, message, faultBeanClass, faultInfo, cause); + // Include the elem name into the FaultException we build so it can be used for matching in the DataTransformationInterceptor + // + // Note this may happen even if we find a constructor above, that is the type of the non-generic fault exc may be an instance + // of FaultException + // + if ((exc instanceof FaultException) && (faultBeanType.getLogical() instanceof XMLType)) { + FaultException faultExc = (FaultException)exc; + DataType<XMLType> faultBeanXMLType = (DataType<XMLType>)faultBeanType; + XMLType faultLogical = faultBeanXMLType.getLogical(); + faultExc.setFaultName(faultLogical.getElementName()); + } + return exc; + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + private Throwable newInstance(Class<? extends Throwable> exceptionClass, + String message, + Class<?> faultBeanClass, + Object faultInfo, + Throwable cause) throws Exception { + Throwable ex = null; + Constructor<? extends Throwable> ctor = null; + try { + // Get the message property + Method getMessage = faultBeanClass.getMethod("getMessage"); + message = (String)getMessage.invoke(faultInfo); + } catch (Throwable e) { + // Ignore + } + try { + // FIXME: What about if the faultBeanClass is a subclass of the argument type? + ctor = exceptionClass.getConstructor(String.class, faultBeanClass, Throwable.class); + ex = ctor.newInstance(message, faultInfo, cause); + } catch (NoSuchMethodException e1) { + try { + ctor = exceptionClass.getConstructor(String.class, faultInfo.getClass()); + ex = ctor.newInstance(message, faultInfo); + } catch (NoSuchMethodException e2) { + try { + ctor = exceptionClass.getConstructor(String.class, Throwable.class); + ex = ctor.newInstance(message, cause); + populateException(ex, faultInfo); + } catch (NoSuchMethodException e3) { + try { + ctor = exceptionClass.getConstructor(String.class); + ex = ctor.newInstance(message); + populateException(ex, faultInfo); + } catch (NoSuchMethodException e4) { + ctor = exceptionClass.getConstructor(); + if (ctor != null) { + ex = ctor.newInstance(); + populateException(ex, faultInfo); + } else { + ex = new FaultException(message, faultInfo, cause); + } + } + } + } + } + return ex; + } + + /** + * Populate the java exception from the fault bean + * @param ex + * @param faultBean + * @throws Exception + */ + private void populateException(Throwable ex, Object faultBean) throws Exception { + PropertyDescriptor props[] = Introspector.getBeanInfo(faultBean.getClass()).getPropertyDescriptors(); + for (PropertyDescriptor p : props) { + Method getter = p.getReadMethod(); + Method setter = p.getWriteMethod(); + if (getter == null || setter == null) { + continue; + } + try { + Method m = ex.getClass().getMethod(setter.getName(), setter.getParameterTypes()); + Object pv = getter.invoke(faultBean); + m.invoke(ex, pv); + } catch (Exception e) { + // Ignore; + } + } + } + + public Object getFaultInfo(Throwable exception, Class<?> faultBeanClass, Operation operation) { + if (exception == null) { + return null; + } + + // Check if it's the generic FaultException + if (exception instanceof FaultException) { + return ((FaultException)exception).getFaultInfo(); + } + + try { + Method method = exception.getClass().getMethod("getFaultInfo", EMPTY_CLASS_ARRAY); + return method.invoke(exception, (Object[])null); + } catch (NoSuchMethodException e) { + // Follow the JAX-WS v2.1 Specification section 3.7 + return createFaultBean(exception, faultBeanClass); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + private Object createFaultBean(Throwable exception, Class<?> faultBeanClass) { + /** + * For each getter in the exception and its superclasses, a property of the same + * type and name is added to the bean. The getCause, getLocalizedMessage and + * getStackTrace getters from java.lang.Throwable and the getClass getter from + * java.lang.Object are excluded from the list of getters to be mapped. + */ + // Return the exception as-is if it's already the fault bean + if (faultBeanClass.isInstance(exception)) { + return exception; + } + try { + Object faultBean = null; + for (Constructor<?> ctor : faultBeanClass.getConstructors()) { + Class<?>[] params = ctor.getParameterTypes(); + if (params.length == 1 && String.class == params[0]) { + faultBean = ctor.newInstance(exception.getMessage()); + } else if (params.length == 2 && String.class == params[0] + && Throwable.class.isAssignableFrom(params[1])) { + faultBean = ctor.newInstance(exception.getMessage(), exception); + } else if (params.length == 0) { + faultBean = ctor.newInstance(); + } + if (faultBean != null) { + break; + } + } + if (faultBean == null) { + return exception; + } + BeanInfo beanInfo = Introspector.getBeanInfo(exception.getClass()); + for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) { + Method getter = pd.getReadMethod(); + String name = getter.getName(); + if (!isMappedGetter(name)) { + continue; + } + Method setter = null; + try { + setter = faultBeanClass.getMethod("set" + capitalize(pd.getName()), getter.getReturnType()); + } catch (NoSuchMethodException e) { + continue; + } + Object prop = getter.invoke(exception); + setter.invoke(faultBean, prop); + } + return faultBean; + } catch (Throwable ex) { + throw new IllegalArgumentException(ex); + } + } + + @SuppressWarnings("unchecked") + public boolean introspectFaultDataType(DataType<DataType> exceptionType, final Operation operation, final boolean generatingFaultBean) { + QName faultName = null; + boolean result = false; + + final Class<?> cls = exceptionType.getPhysical(); + if (cls == FaultException.class) { + return true; + } + DataType faultType = (DataType)exceptionType.getLogical(); + Class<?> faultBean = null; + final WebFault fault = cls.getAnnotation(WebFault.class); + if (fault != null) { + if (!"".equals(fault.name()) || !"".equals(fault.targetNamespace())) { + QName faultQName = ((XMLType)faultType.getLogical()).getElementName(); + String faultNS = + "".equals(fault.targetNamespace()) ? faultQName.getNamespaceURI() : fault.targetNamespace(); + String faultLocal = "".equals(fault.name()) ? faultQName.getLocalPart() : fault.name(); + faultName = new QName(faultNS, faultLocal); + XMLType xmlType = new XMLType(faultName, null); + faultType.setLogical(xmlType); + } + if (!"".equals(fault.faultBean())) { + faultBean = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { + public Class<?> run() { + try { + return Class.forName(fault.faultBean(), false, cls.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new ServiceRuntimeException(e); + } + } + }); + } else { + Method m; + try { + m = cls.getMethod("getFaultInfo", (Class[])null); + faultBean = m.getReturnType(); + } catch (NoSuchMethodException e) { + // Ignore + } + } + } + + if (faultBean == null) { + final String faultBeanClassName = CodeGenerationHelper.getPackagePrefix(cls) + cls.getSimpleName() + "Bean"; + final QName qname = faultName; + faultType = AccessController.doPrivileged(new PrivilegedAction<DataType<XMLType>>() { + public DataType<XMLType> run() { + try { + Class<?> faultBean = Class.forName(faultBeanClassName, false, cls.getClassLoader()); + return new DataTypeImpl<XMLType>(faultBean, new XMLType(qname, qname)); + } catch (ClassNotFoundException e) { + if (generatingFaultBean) { + Class<? extends Throwable> t = (Class<? extends Throwable>)cls; + ClassLoader parent = + operation == null ? t.getClassLoader() : ((JavaInterface)operation.getInterface()) + .getJavaClass().getClassLoader(); + GeneratedClassLoader cl = new GeneratedClassLoader(parent); + GeneratedDataTypeImpl dt = new GeneratedDataTypeImpl(xmlAdapterExtensionPoint, t, cl); + return dt; + } else { + return new DataTypeImpl<XMLType>(cls, new XMLType(qname, qname)); + } + } + } + }); + } else { + faultType.setDataBinding(null); + faultType.setGenericType(faultBean); + faultType.setPhysical(faultBean); + } + + // TODO: Use the databinding framework to introspect the fault bean class + if (faultType.getDataBinding() == null && dataBindingExtensionPoint != null) { + faultBean = faultType.getPhysical(); + result = + dataBindingExtensionPoint.introspectType(faultType, operation); + } + ((DataType) exceptionType).setLogical(faultType); + + /* + The introspection of the fault DT may not have calculated the correct element name, + though we may have already done this in this method. Let's look at the DataType now + that introspection is done, and, if it has an XMLType, let's set the element to the + 'faultName' if we calculated one. + */ + if ((faultName != null) && (faultType.getLogical() instanceof XMLType)) { + XMLType faultTypeXML = (XMLType)faultType.getLogical(); + // The element name (if set) should match the fault name + faultTypeXML.setElementName(faultName); + } + + return result; + } + + public static boolean isMappedGetter(String methodName) { + if (GETCAUSE.equals(methodName) || GETLOCALIZEDMESSAGE.equals(methodName) + || GETSTACKTRACE.equals(methodName) + || GETCLASS.equals(methodName)) { + return false; + } else { + return true; + } + } + + private static String capitalize(String name) { + if (name == null || name.length() == 0) { + return name; + } else { + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + } + + public void setDataBindingExtensionPoint(DataBindingExtensionPoint dataBindingExtensionPoint) { + this.dataBindingExtensionPoint = dataBindingExtensionPoint; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java new file mode 100644 index 0000000000..d1b36fa17c --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java @@ -0,0 +1,379 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.jws.Oneway; +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.jws.soap.SOAPBinding.Style; +import javax.xml.namespace.QName; +import javax.xml.ws.RequestWrapper; +import javax.xml.ws.ResponseWrapper; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.javabeans.JavaExceptionDataBinding; +import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; +import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * Introspect the java class/interface with JSR-181 and JAXWS annotations + * + * @version $Rev$ $Date$ + */ +public class JAXWSJavaInterfaceProcessor implements JavaInterfaceVisitor { + private static final String JAXB_DATABINDING = JAXBDataBinding.NAME; + private static final String GET = "get"; + private DataBindingExtensionPoint dataBindingExtensionPoint; + private FaultExceptionMapper faultExceptionMapper; + private XMLAdapterExtensionPoint xmlAdapterExtensionPoint; + + + public JAXWSJavaInterfaceProcessor(DataBindingExtensionPoint dataBindingExtensionPoint, + FaultExceptionMapper faultExceptionMapper, + XMLAdapterExtensionPoint xmlAdapters) { + super(); + this.dataBindingExtensionPoint = dataBindingExtensionPoint; + this.faultExceptionMapper = faultExceptionMapper; + this.xmlAdapterExtensionPoint = xmlAdapters; + } + + public JAXWSJavaInterfaceProcessor() { + super(); + } + + private static String capitalize(String name) { + if (name == null || name.length() == 0) { + return name; + } else { + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + } + + public void visitInterface(JavaInterface contract) throws InvalidInterfaceException { + + final Class<?> clazz = contract.getJavaClass(); + WebService webService = clazz.getAnnotation(WebService.class); + String tns = JavaXMLMapper.getNamespace(clazz); + String localName = clazz.getSimpleName(); + if (webService != null) { + tns = getValue(webService.targetNamespace(), tns); + localName = getValue(webService.name(), localName); + contract.setQName(new QName(tns, localName)); + // Mark SEI as Remotable + contract.setRemotable(true); + } + if (!contract.isRemotable()) { + return; + } + + // SOAP binding (doc/lit/wrapped|bare or rpc/lit) + SOAPBinding soapBinding = clazz.getAnnotation(SOAPBinding.class); + + for (Iterator<Operation> it = contract.getOperations().iterator(); it.hasNext();) { + final JavaOperation operation = (JavaOperation)it.next(); + final Method method = operation.getJavaMethod(); + introspectFaultTypes(operation); + + // SOAP binding (doc/lit/wrapped|bare or rpc/lit) + SOAPBinding methodSOAPBinding = method.getAnnotation(SOAPBinding.class); + if (methodSOAPBinding == null) { + methodSOAPBinding = soapBinding; + } + + boolean documentStyle = true; + boolean bare = false; + if (methodSOAPBinding != null) { + bare = methodSOAPBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE; + if(bare) { + // For BARE parameter style, the data won't be unwrapped + // The wrapper should be null + operation.setWrapperStyle(false); + } + documentStyle = methodSOAPBinding.style() == Style.DOCUMENT; + } + + String operationName = operation.getName(); + // WebMethod + WebMethod webMethod = method.getAnnotation(WebMethod.class); + if (webMethod != null) { + if (webMethod.exclude()) { + // Exclude the method + it.remove(); + continue; + } + operationName = getValue(webMethod.operationName(), operationName); + operation.setName(operationName); + operation.setAction(webMethod.action()); + } + + // Is one way? + Oneway oneway = method.getAnnotation(Oneway.class); + if (oneway != null) { + // JSR 181 + assert method.getReturnType() == void.class; + operation.setNonBlocking(true); + } + + // Handle BARE mapping + if (bare) { + for (int i = 0; i < method.getParameterTypes().length; i++) { + WebParam param = getAnnotation(method, i, WebParam.class); + if (param != null) { + String ns = getValue(param.targetNamespace(), tns); + // Default to <operationName> for doc-bare + String name = getValue(param.name(), documentStyle ? operationName : "arg" + i); + QName element = new QName(ns, name); + Object logical = operation.getInputType().getLogical().get(i).getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + } + } + WebResult result = method.getAnnotation(WebResult.class); + if (result != null) { + String ns = getValue(result.targetNamespace(), tns); + // Default to <operationName>Response for doc-bare + String name = getValue(result.name(), documentStyle ? operationName + "Response" : "return"); + QName element = new QName(ns, name); + Object logical = operation.getOutputType().getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + } + // FIXME: [rfeng] For the BARE mapping, do we need to create a Wrapper? + // it's null at this point + } else { + + RequestWrapper requestWrapper = method.getAnnotation(RequestWrapper.class); + String ns = requestWrapper == null ? tns : getValue(requestWrapper.targetNamespace(), tns); + String name = + requestWrapper == null ? operationName : getValue(requestWrapper.localName(), operationName); + String wrapperBeanName = requestWrapper == null ? "" : requestWrapper.className(); + if ("".equals(wrapperBeanName)) { + wrapperBeanName = CodeGenerationHelper.getPackagePrefix(clazz) + capitalize(method.getName()); + } + + DataType<XMLType> inputWrapperDT = null; + + final String inputWrapperClassName = wrapperBeanName; + final String inputNS = ns; + final String inputName = name; + inputWrapperDT = AccessController.doPrivileged(new PrivilegedAction<DataType<XMLType>>() { + public DataType<XMLType> run() { + try { + Class<?> wrapperClass = Class.forName(inputWrapperClassName, false, clazz.getClassLoader()); + QName qname = new QName(inputNS, inputName); + DataType dt = new DataTypeImpl<XMLType>(wrapperClass, new XMLType(qname, qname)); + dataBindingExtensionPoint.introspectType(dt, operation); + // TUSCANY-2505 + if (dt.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)dt.getLogical(); + xmlType.setElementName(qname); + } + return dt; + } catch (ClassNotFoundException e) { + GeneratedClassLoader cl = new GeneratedClassLoader(clazz.getClassLoader()); + return new GeneratedDataTypeImpl(xmlAdapterExtensionPoint, method, inputWrapperClassName, inputNS, inputName, true, + cl); + } + } + }); + + QName inputWrapper = inputWrapperDT.getLogical().getElementName(); + + ResponseWrapper responseWrapper = method.getAnnotation(ResponseWrapper.class); + ns = responseWrapper == null ? tns : getValue(responseWrapper.targetNamespace(), tns); + name = + responseWrapper == null ? operationName + "Response" : getValue(responseWrapper.localName(), + operationName + "Response"); + wrapperBeanName = responseWrapper == null ? "" : responseWrapper.className(); + if ("".equals(wrapperBeanName)) { + wrapperBeanName = + CodeGenerationHelper.getPackagePrefix(clazz) + capitalize(method.getName()) + "Response"; + } + + DataType<XMLType> outputWrapperDT = null; + final String outputWrapperClassName = wrapperBeanName; + final String outputNS = ns; + final String outputName = name; + + outputWrapperDT = AccessController.doPrivileged(new PrivilegedAction<DataType<XMLType>>() { + public DataType<XMLType> run() { + try { + Class<?> wrapperClass = + Class.forName(outputWrapperClassName, false, clazz.getClassLoader()); + QName qname = new QName(outputNS, outputName); + DataType dt = new DataTypeImpl<XMLType>(wrapperClass, new XMLType(qname, qname)); + dataBindingExtensionPoint.introspectType(dt, operation); + // TUSCANY-2505 + if (dt.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)dt.getLogical(); + xmlType.setElementName(qname); + } + return dt; + } catch (ClassNotFoundException e) { + GeneratedClassLoader cl = new GeneratedClassLoader(clazz.getClassLoader()); + return new GeneratedDataTypeImpl(xmlAdapterExtensionPoint, method, outputWrapperClassName, outputNS, outputName, + false, cl); + } + } + }); + QName outputWrapper = outputWrapperDT.getLogical().getElementName(); + + List<ElementInfo> inputElements = new ArrayList<ElementInfo>(); + for (int i = 0; i < method.getParameterTypes().length; i++) { + WebParam param = getAnnotation(method, i, WebParam.class); + ns = param != null ? param.targetNamespace() : ""; + // Default to "" for doc-lit-wrapped && non-header + ns = getValue(ns, documentStyle && (param == null || !param.header()) ? "" : tns); + name = param != null ? param.name() : ""; + name = getValue(name, "arg" + i); + QName element = new QName(ns, name); + Object logical = operation.getInputType().getLogical().get(i).getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + inputElements.add(new ElementInfo(element, null)); + } + + List<ElementInfo> outputElements = new ArrayList<ElementInfo>(); + WebResult result = method.getAnnotation(WebResult.class); + // Default to "" for doc-lit-wrapped && non-header + ns = result != null ? result.targetNamespace() : ""; + ns = getValue(ns, documentStyle && (result == null || !result.header()) ? "" : tns); + name = result != null ? result.name() : ""; + name = getValue(name, "return"); + QName element = new QName(ns, name); + + if (operation.getOutputType() != null) { + Object logical = operation.getOutputType().getLogical(); + if (logical instanceof XMLType) { + ((XMLType)logical).setElementName(element); + } + outputElements.add(new ElementInfo(element, null)); + } + + String db = inputWrapperDT != null ? inputWrapperDT.getDataBinding() : JAXB_DATABINDING; + WrapperInfo wrapperInfo = + new WrapperInfo(db, new ElementInfo(inputWrapper, null), new ElementInfo(outputWrapper, null), + inputElements, outputElements); + + wrapperInfo.setInputWrapperType(inputWrapperDT); + wrapperInfo.setOutputWrapperType(outputWrapperDT); + + operation.setWrapper(wrapperInfo); + } + } + } + + @SuppressWarnings("unchecked") + private void introspectFaultTypes(Operation operation) { + if (operation != null && operation.getFaultTypes() != null) { + for (DataType exceptionType : operation.getFaultTypes()) { + faultExceptionMapper.introspectFaultDataType(exceptionType, operation, true); + DataType faultType = (DataType)exceptionType.getLogical(); + if (faultType.getDataBinding() == JavaExceptionDataBinding.NAME) { + // The exception class doesn't have an associated bean class, so + // synthesize a virtual bean by introspecting the exception class. + createSyntheticBean(operation, exceptionType); + } + } + } + } + + private void createSyntheticBean(Operation operation, DataType exceptionType) { + DataType faultType = (DataType)exceptionType.getLogical(); + QName faultBeanName = ((XMLType)faultType.getLogical()).getElementName(); + List<DataType<XMLType>> beanDataTypes = new ArrayList<DataType<XMLType>>(); + for (Method aMethod : exceptionType.getPhysical().getMethods()) { + if (Modifier.isPublic(aMethod.getModifiers()) && aMethod.getName().startsWith(GET) + && aMethod.getParameterTypes().length == 0 + && JAXWSFaultExceptionMapper.isMappedGetter(aMethod.getName())) { + String propName = resolvePropertyFromMethod(aMethod.getName()); + QName propQName = new QName(faultBeanName.getNamespaceURI(), propName); + Class propType = aMethod.getReturnType(); + XMLType xmlPropType = new XMLType(propQName, null); + DataType<XMLType> propDT = new DataTypeImpl<XMLType>(propType, xmlPropType); + org.apache.tuscany.sca.databinding.annotation.DataType dt = + aMethod.getAnnotation(org.apache.tuscany.sca.databinding.annotation.DataType.class); + if (dt != null) { + propDT.setDataBinding(dt.value()); + } + dataBindingExtensionPoint.introspectType(propDT, operation); + + // sort the list lexicographically as specified in JAX-WS spec section 3.7 + int i = 0; + for (; i < beanDataTypes.size(); i++) { + if (beanDataTypes.get(i).getLogical().getElementName().getLocalPart().compareTo(propName) > 0) { + break; + } + } + beanDataTypes.add(i, propDT); + } + } + operation.getFaultBeans().put(faultBeanName, beanDataTypes); + } + + private String resolvePropertyFromMethod(String methodName) { + StringBuffer propName = new StringBuffer(); + propName.append(Character.toLowerCase(methodName.charAt(GET.length()))); + propName.append(methodName.substring(GET.length() + 1)); + return propName.toString(); + } + + private <T extends Annotation> T getAnnotation(Method method, int index, Class<T> annotationType) { + Annotation[] annotations = method.getParameterAnnotations()[index]; + for (Annotation annotation : annotations) { + if (annotation.annotationType() == annotationType) { + return annotationType.cast(annotation); + } + } + return null; + } + + private static String getValue(String value, String defaultValue) { + return "".equals(value) ? defaultValue : value; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java new file mode 100644 index 0000000000..764c10ff00 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java @@ -0,0 +1,238 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import javax.jws.WebParam; +import javax.jws.WebResult; + +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; + +public class WrapperBeanGenerator extends BaseBeanGenerator { + + public List<Class<?>> generateWrapperBeans(Class<?> sei) { + GeneratedClassLoader cl = new GeneratedClassLoader(sei.getClassLoader()); + List<Class<?>> classes = new ArrayList<Class<?>>(); + for (Method m : sei.getMethods()) { + if (m.getDeclaringClass() == Object.class) { + continue; + } + classes.add(generateRequestWrapper(sei, m, cl)); + classes.add(generateResponseWrapper(sei, m, cl)); + } + return classes; + + } + + public Class<?> generateRequestWrapper(Class<?> sei, Method m, GeneratedClassLoader cl) { + String wrapperNamespace = JavaInterfaceUtil.getNamespace(sei); + String wrapperName = m.getName(); + String wrapperBeanName = capitalize(wrapperName); + String wrapperClassName = CodeGenerationHelper.getPackagePrefix(sei) + wrapperBeanName; + + return generateRequestWrapper(m, wrapperClassName, wrapperNamespace, wrapperName, cl); + } + + public Class<?> generateRequestWrapper(Method m, + String wrapperClassName, + String wrapperNamespace, + String wrapperName, + GeneratedClassLoader cl) { + synchronized (m.getDeclaringClass()) { + MethodKey key = new MethodKey(m, true); + Class<?> wrapperClass = generatedClasses.get(key); + if (wrapperClass == null) { + String wrapperClassDescriptor = wrapperClassName.replace('.', '/'); + String wrapperClassSignature = "L" + wrapperClassDescriptor + ";"; + + Class<?>[] paramTypes = m.getParameterTypes(); + Type[] genericParamTypes = m.getGenericParameterTypes(); + Annotation[][] paramAnnotations = m.getParameterAnnotations(); + List<BeanProperty> properties = new ArrayList<BeanProperty>(); + for (int i = 0; i < paramTypes.length; i++) { + String propNS = ""; + String propName = "arg" + i; + + WebParam webParam = findAnnotation(paramAnnotations[i], WebParam.class); + if (webParam != null && webParam.header()) { + continue; + } + WebParam.Mode mode = WebParam.Mode.IN; + if (webParam != null) { + mode = webParam.mode(); + if (webParam.name().length() > 0) { + propName = webParam.name(); + } + propNS = webParam.targetNamespace(); + } + if (mode.equals(WebParam.Mode.IN) || mode.equals(WebParam.Mode.INOUT)) { + java.lang.reflect.Type genericParamType = getHolderValueType(genericParamTypes[i]); + Class<?> paramType = CodeGenerationHelper.getErasure(genericParamType); + BeanProperty prop = new BeanProperty(propNS, propName, paramType, genericParamType, true); + prop.getJaxbAnnotaions().addAll(findJAXBAnnotations(paramAnnotations[i])); + properties.add(prop); + } + } + + wrapperClass = + generate(wrapperClassDescriptor, wrapperClassSignature, wrapperNamespace, wrapperName, properties + .toArray(new BeanProperty[properties.size()]), cl); + generatedClasses.put(key, wrapperClass); + } + return wrapperClass; + + } + } + + public Class<?> generateResponseWrapper(Class<?> sei, Method m, GeneratedClassLoader cl) { + String wrapperNamespace = JavaInterfaceUtil.getNamespace(sei); + + String wrapperName = m.getName() + "Response"; + String wrapperBeanName = capitalize(wrapperName); + String wrapperClassName = CodeGenerationHelper.getPackagePrefix(sei) + wrapperBeanName; + return generateResponseWrapper(m, wrapperClassName, wrapperNamespace, wrapperName, cl); + + } + + public Class<?> generateResponseWrapper(Method m, + String wrapperClassName, + String wrapperNamespace, + String wrapperName, + GeneratedClassLoader cl) { + synchronized (m.getDeclaringClass()) { + MethodKey key = new MethodKey(m, false); + Class<?> wrapperClass = generatedClasses.get(key); + if (wrapperClass == null) { + String wrapperClassDescriptor = wrapperClassName.replace('.', '/'); + String wrapperClassSignature = "L" + wrapperClassDescriptor + ";"; + + List<BeanProperty> properties = new ArrayList<BeanProperty>(); + // Collect all OUT, INOUT parameters as fields + Annotation[][] paramAnns = m.getParameterAnnotations(); + Class<?>[] paramTypes = m.getParameterTypes(); + java.lang.reflect.Type[] genericParamTypes = m.getGenericParameterTypes(); + for (int i = 0; i < paramTypes.length; i++) { + WebParam webParam = findAnnotation(paramAnns[i], WebParam.class); + if (webParam != null) { + if (webParam.header() || webParam.mode() == WebParam.Mode.IN) { + continue; + } + } + if (!isHolder(genericParamTypes[i])) { + continue; + } + + List<Annotation> jaxb = findJAXBAnnotations(paramAnns[i]); + + java.lang.reflect.Type genericParamType = getHolderValueType(genericParamTypes[i]); + Class<?> paramType = CodeGenerationHelper.getErasure(genericParamType); + + String paramNamespace = ""; + String paramName = "arg" + i; + + if (webParam != null) { + if (webParam.name().length() > 0) + paramName = webParam.name(); + if (webParam.targetNamespace().length() > 0) + paramNamespace = webParam.targetNamespace(); + } + + BeanProperty prop = new BeanProperty(paramNamespace, paramName, paramType, genericParamType, true); + prop.getJaxbAnnotaions().addAll(jaxb); + properties.add(prop); + } + + WebResult webResult = m.getAnnotation(WebResult.class); + Class<?> returnType = m.getReturnType(); + if (!((webResult != null && webResult.header()) || returnType == Void.TYPE)) { + String propName = "return"; + String propNS = ""; + + if (webResult != null) { + if (webResult.name().length() > 0) { + propName = webResult.name(); + } + if (webResult.targetNamespace().length() > 1) { + propNS = webResult.targetNamespace(); + } + } + + List<Annotation> jaxb = findJAXBAnnotations(m.getAnnotations()); + + Type genericReturnType = m.getGenericReturnType(); + BeanProperty prop = new BeanProperty(propNS, propName, returnType, genericReturnType, true); + prop.getJaxbAnnotaions().addAll(jaxb); + properties.add(prop); + } + wrapperClass = + generate(wrapperClassDescriptor, wrapperClassSignature, wrapperNamespace, wrapperName, properties + .toArray(new BeanProperty[properties.size()]), cl); + generatedClasses.put(key, wrapperClass); + } + return wrapperClass; + + } + } + + private static class MethodKey { + private Method m; + private boolean request; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((m == null) ? 0 : m.hashCode()); + result = prime * result + (request ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final MethodKey other = (MethodKey)obj; + if (m == null) { + if (other.m != null) + return false; + } else if (!m.equals(other.m)) + return false; + if (request != other.request) + return false; + return true; + } + + public MethodKey(Method m, boolean request) { + super(); + this.m = m; + this.request = request; + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java new file mode 100644 index 0000000000..1b07e25bad --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +/** + * + * @version $Rev$ $Date$ + */ +public interface Bean<T> { + T getP1(); +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java new file mode 100644 index 0000000000..d38a21ba52 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean1.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +/** + * + * @version $Rev$ $Date$ + */ +public class Bean1 { + private String p1; + private int p2; + public String getP1() { + return p1; + } + public void setP1(String p1) { + this.p1 = p1; + } + public int getP2() { + return p2; + } + public void setP2(int p2) { + this.p2 = p2; + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java new file mode 100644 index 0000000000..7b9375063d --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/Bean2.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +/** + * + * @version $Rev$ $Date$ + */ +public class Bean2 implements Bean<String>{ + private String p1; + private int p2; + public String getP1() { + return p1; + } + public void setP1(String p1) { + this.p1 = p1; + } + public int getP2() { + return p2; + } + public void setP2(int p2) { + this.p2 = p2; + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGeneratorTestCase.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGeneratorTestCase.java new file mode 100644 index 0000000000..567591f166 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGeneratorTestCase.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.annotation.Annotation; + +import javax.xml.bind.JAXBContext; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.util.CheckClassAdapter; + +/** + * @version $Rev$ $Date$ + */ +public class FaultBeanGeneratorTestCase extends TestCase { + public void testGenerate() throws IOException { + byte[] content = new FaultBeanGenerator().generate(MyException.class); + ClassReader cr = new ClassReader(content); + PrintWriter pw = new PrintWriter(System.out); + CheckClassAdapter.verify(cr, false, pw); + } + + public void testGenerateClass() throws Exception { + Class<?> cls = FaultBeanGenerator.generateFaultBeanClass(MyException.class); + Assert.assertEquals("org.apache.tuscany.sca.interfacedef.java.jaxws.jaxws.MyExceptionBean", cls.getName()); + for (Annotation a : cls.getAnnotations()) { + System.out.println(a); + } + // XmlType xmlType = cls.getAnnotation(XmlType.class); + // System.out.println(xmlType); + Object bean = cls.newInstance(); + JAXBContext context = JAXBContextHelper.createJAXBContext(cls); + StringWriter sw = new StringWriter(); + context.createMarshaller().marshal(bean, sw); + System.out.println(sw.toString()); + + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java new file mode 100644 index 0000000000..108d283584 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessorTestCase.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import javax.jws.WebMethod; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.xml.namespace.QName; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.jaxb.DefaultXMLAdapterExtensionPoint; +import org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +import com.example.stock.StockExceptionTest; +/** + * + * @version $Rev$ $Date$ + */ +public class JAXWSJavaInterfaceProcessorTestCase extends TestCase { + private JAXWSJavaInterfaceProcessor interfaceProcessor; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + DataBindingExtensionPoint db = new DefaultDataBindingExtensionPoint(); + XMLAdapterExtensionPoint xa = new DefaultXMLAdapterExtensionPoint(); + interfaceProcessor = new JAXWSJavaInterfaceProcessor(db, new JAXWSFaultExceptionMapper(db, xa), xa); + } + + public void testWrapper() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(); + JavaInterface contract = iFactory.createJavaInterface(StockExceptionTest.class); + + interfaceProcessor.visitInterface(contract); + Operation op = contract.getOperations().get(0); + Assert.assertTrue(!op.isWrapperStyle()); + Assert.assertEquals(new QName("http://www.example.com/stock", "stockQuoteOffer"), op.getWrapper().getInputWrapperElement().getQName()); + Assert.assertEquals(new QName("http://www.example.com/stock", "stockQuoteOfferResponse"), op.getWrapper().getOutputWrapperElement().getQName()); + } + + /** + * Test method for + * {@link org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor#visitInterface(JavaInterface)}. + */ + public final void testProcessor() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(); + JavaInterface contract = iFactory.createJavaInterface(WebServiceInterfaceWithoutAnnotation.class); + + interfaceProcessor.visitInterface(contract); + assertFalse(contract.isRemotable()); + + contract = iFactory.createJavaInterface(WebServiceInterfaceWithAnnotation.class); + interfaceProcessor.visitInterface(contract); + assertTrue(contract.isRemotable()); + + Operation op1 = contract.getOperations().get(0); + Operation op2 = contract.getOperations().get(1); + + Operation op = null; + if ("m1".equals(op1.getName())) { + op = op1; + } else { + op = op2; + } + + assertTrue(!op.isWrapperStyle() && op.getWrapper() == null); + + if ("M2".equals(op2.getName())) { + op = op2; + } else { + op = op1; + } + assertTrue(!op.isWrapperStyle() && op.getWrapper() != null); + + } + + @WebService + private static interface WebServiceInterfaceWithAnnotation { + + @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) + @WebMethod(operationName = "m1") + String m1(String str); + + @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.WRAPPED) + @WebMethod(operationName = "M2") + String m2(String str, int i); + } + + private static interface WebServiceInterfaceWithoutAnnotation { + + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JavaReflectionHelperTestCase.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JavaReflectionHelperTestCase.java new file mode 100644 index 0000000000..b3c7102a78 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JavaReflectionHelperTestCase.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.lang.reflect.Field; + +import junit.framework.Assert; + +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class JavaReflectionHelperTestCase { + @Test + public void testErasure() throws Exception { + for (Field f : TestGenericClass.class.getDeclaredFields()) { + Class<?> cls = CodeGenerationHelper.getErasure(f.getGenericType()); + System.out.println(cls.getName()); + Assert.assertSame(f.getType(), cls); + } + } + + @Test + public void testSignature() throws Exception { + for (Field f : TestGenericClass.class.getDeclaredFields()) { + String sig = CodeGenerationHelper.getSignature(f.getGenericType()); + System.out.println(sig); + } + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java new file mode 100644 index 0000000000..4df0517de6 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyException.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +/** + * + * @version $Rev$ $Date$ + */ +public class MyException extends Exception { + private String error; + private int code; + + public MyException() { + super(); + } + + public MyException(String message, Throwable cause) { + super(message, cause); + } + + public MyException(String message) { + super(message); + } + + public MyException(Throwable cause) { + super(cause); + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java new file mode 100644 index 0000000000..78527193d5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/MyServiceImpl.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.util.List; + +import javax.jws.WebMethod; +import javax.jws.WebService; + +/** + * @version $Rev$ $Date$ + */ +@WebService +public class MyServiceImpl { + + public MyServiceImpl() { + super(); + } + + @WebMethod + public <T extends Bean1> T getBean(T b, Bean2 b2) { + return null; + } + + @WebMethod + public List<? extends Bean1> getBeans() { + return null; + } + + @WebMethod + public String convert(String str, int i) throws MyException { + return "ME"; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestGenericClass.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestGenericClass.java new file mode 100644 index 0000000000..2ecf822904 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestGenericClass.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * @version $Rev$ $Date$ + */ +public class TestGenericClass <T extends Serializable & List<String>, S> { + public TestGenericClass<?, S> i; + public T f1; + public T[] f2; + public S f3; + public List<? extends T> list1; + public List<?> list2; + public List<? extends Serializable> list3; + public int f4; + public int[] f5; + public Map<? super T, S> map; +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestInterface.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestInterface.java new file mode 100644 index 0000000000..a6a3375eff --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestInterface.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.interfacedef.java.jaxws; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.xml.ws.Holder; + +import org.osoa.sca.annotations.Remotable; + +/** + * @version $Rev$ $Date$ + */ +@Remotable +public interface TestInterface { + int convert(String currency1, String currency2); + + List<Double> getRates(String currency); + + void check(boolean flag); + + String[] list(int[] list); + + int[][] map(String[][] strs); + + String getGreetings(String name); + + String[] getGreetingsArray(String[] names); + + List<String> getGreetingsList(List<String> names); + + ArrayList<String> getGreetingsArrayList(ArrayList<String> names); + + Map<String, String> getGreetingsMap(Map<String, String> namesMap); + + HashMap<String, String> getGreetingsHashMap(HashMap<String, String> namesMap); + + @WebMethod + @WebResult(name = "output") + String webMethod(@WebParam(name = "input", mode = WebParam.Mode.IN) + String in, @WebParam(name = "holder", mode = WebParam.Mode.INOUT) + Holder<String> holder); +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGeneratorTestCase.java b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGeneratorTestCase.java new file mode 100644 index 0000000000..b14ef19939 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGeneratorTestCase.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxws; + +import java.io.StringReader; +import java.io.StringWriter; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBContext; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; +import org.apache.tuscany.sca.databinding.jaxb.JAXBTypeHelper; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class WrapperBeanGeneratorTestCase { + @Test + public void testGenerate() throws Exception { + List<Class<?>> classes = new WrapperBeanGenerator().generateWrapperBeans(TestInterface.class); + for (Class<?> cls : classes) { + for (Field f : cls.getDeclaredFields()) { + System.out.println(f.getName()); + System.out.println(f.getGenericType()); + for (Annotation a : f.getAnnotations()) { + System.out.println(a); + } + } + for (Method m : cls.getDeclaredMethods()) { + System.out.println(m); + for (Annotation a : m.getAnnotations()) { + System.out.println(a); + } + } + } + JAXBContext context = JAXBContextHelper.createJAXBContext(classes.toArray(new Class<?>[classes.size()])); + for (Class<?> cls : classes) { + Object obj = cls.newInstance(); + StringWriter sw = new StringWriter(); + context.createMarshaller().marshal(obj, sw); + // System.out.println(sw.toString()); + StringReader sr = new StringReader(sw.toString()); + context.createUnmarshaller().unmarshal(new StreamSource(sr), cls); + } + } + + @Test + public void testGenerateSchema() throws Exception { + List<Class<?>> classes = new WrapperBeanGenerator().generateWrapperBeans(TestInterface.class); + JAXBContext context = JAXBContextHelper.createJAXBContext(classes.toArray(new Class<?>[classes.size()])); + Map<String, String> results = JAXBTypeHelper.generateSchema(context); + for (String xsd : results.values()) { + System.out.println(xsd); + } + } +} diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/Stock.wsdl b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/Stock.wsdl new file mode 100644 index 0000000000..882408ade6 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/Stock.wsdl @@ -0,0 +1,142 @@ +<?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.
+-->
+<wsdl:definitions targetNamespace="http://www.example.com/stock" xmlns:impl="http://www.example.com/stock"
+ xmlns:tns="http://www.example.com/stock" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StockExceptionTest">
+ <wsdl:types>
+ <schema targetNamespace="http://www.example.com/stock" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <complexType name="StockOffer">
+ <sequence>
+ <element name="symbol" minOccurs="1" type="xsd:string" />
+ <element name="price" minOccurs="1" type="xsd:float" nillable="true" /><!-- max price reqested, actual response -->
+ <element name="name" minOccurs="0" type="xsd:string" />
+ <element name="list" minOccurs="0" maxOccurs="unbounded" type="xsd:string" />
+ </sequence>
+ </complexType>
+
+ <element name="stockQuoteOffer">
+ <complexType>
+ <sequence>
+ <element name="input" minOccurs="0" maxOccurs="unbounded" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="stockQuoteOfferResponse">
+ <complexType>
+ <sequence>
+ <element name="stockQuoteOfferReturn" minOccurs="0" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ </element>
+
+ <!-- Faults -->
+ <element name="InvalidSymbolFault">
+ <complexType>
+ <sequence>
+ <element name="message" minOccurs="1" type="xsd:string" />
+ <element name="offer" minOccurs="1" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ </element>
+
+ <element name="MarketClosedFault" type="xsd:int" />
+
+ <element name="TestNotDeclaredAtSourceFault" type="xsd:string" />
+
+ </schema>
+ </wsdl:types>
+
+
+ <wsdl:message name="stockQuoteOfferRequest">
+ <wsdl:part element="tns:stockQuoteOffer" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:message name="stockQuoteOfferResponse">
+ <wsdl:part element="tns:stockQuoteOfferResponse" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidSymbolFault">
+ <wsdl:part element="tns:InvalidSymbolFault" name="fault" />
+ </wsdl:message>
+
+ <wsdl:message name="MarketClosedFault">
+ <wsdl:part element="tns:MarketClosedFault" name="fault" />
+ </wsdl:message>
+
+ <wsdl:message name="TestNotDeclaredAtSourceFault">
+ <wsdl:part element="tns:TestNotDeclaredAtSourceFault" name="fault" />
+ </wsdl:message>
+
+
+ <wsdl:portType name="StockExceptionTest">
+ <wsdl:operation name="stockQuoteOffer">
+ <wsdl:input message="tns:stockQuoteOfferRequest" name="stockQuoteOfferRequest" />
+
+ <wsdl:output message="tns:stockQuoteOfferResponse" name="stockQuoteOfferResponse" />
+
+ <wsdl:fault message="tns:InvalidSymbolFault" name="InvalidSymbolException" />
+
+ <wsdl:fault message="tns:MarketClosedFault" name="MarketClosedException" />
+
+ <wsdl:fault message="tns:TestNotDeclaredAtSourceFault" name="TestNotDeclaredAtSourceException" />
+ </wsdl:operation>
+
+
+ </wsdl:portType>
+
+ <wsdl:binding name="StockExceptionTestServiceSoapBinding" type="tns:StockExceptionTest">
+ <!-- <wsaw:UsingAddressing wsdl:required="false" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"/> -->
+
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+
+ <wsdl:operation name="stockQuoteOffer">
+ <wsdlsoap:operation soapAction="" />
+
+ <wsdl:input name="stockQuoteOfferRequest">
+ <wsdlsoap:body use="literal" />
+ </wsdl:input>
+
+ <wsdl:output name="stockQuoteOfferResponse">
+ <wsdlsoap:body use="literal" />
+ </wsdl:output>
+
+ <wsdl:fault name="InvalidSymbolException">
+ <wsdlsoap:fault name="InvalidSymbolException" use="literal" />
+ </wsdl:fault>
+
+ <wsdl:fault name="MarketClosedException">
+ <wsdlsoap:fault name="MarketClosedException" use="literal" />
+ </wsdl:fault>
+
+ <wsdl:fault name="TestNotDeclaredAtSourceException">
+ <wsdlsoap:fault name="TestNotDeclaredAtSourceException" use="literal" />
+ </wsdl:fault>
+
+
+
+ </wsdl:operation>
+
+
+ </wsdl:binding>
+
+
+</wsdl:definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl new file mode 100644 index 0000000000..4fee9e9756 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-jaxws/src/test/resources/wsdl/StockExceptionTest.wsdl @@ -0,0 +1,149 @@ +<?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.
+ -->
+<wsdl:definitions targetNamespace="http://www.example.com/stock" xmlns:impl="http://www.example.com/stock"
+ xmlns:tns="http://www.example.com/stock" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsi="http://ws-i.org/profiles/basic/1.1/xsd"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StockExceptionTest">
+ <wsdl:types>
+ <schema targetNamespace="http://www.example.com/stock" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <complexType name="StockOffer">
+ <sequence>
+ <element name="symbol" minOccurs="1" type="xsd:string" />
+ <element name="price" minOccurs="1" type="xsd:float" nillable="true" /> <!-- max price reqested, actual response -->
+ <element name="name" minOccurs="0" type="xsd:string" />
+ <element name="list" minOccurs="0" maxOccurs="unbounded" type="xsd:string" />
+ </sequence>
+ </complexType>
+
+ <element name="stockQuoteOffer">
+ <complexType>
+ <sequence>
+ <element name="input" minOccurs="0" maxOccurs="unbounded" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ </element>
+ <!-- TUSCANY 2505, make the responseWrapper non-anonymous -->
+ <element name="stockQuoteOfferResponse" type="tns:StockQuoteOfferResponseType">
+ </element>
+ <complexType name="StockQuoteOfferResponseType">
+ <sequence>
+ <element name="stockQuoteOfferReturn" minOccurs="0" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ <!-- Faults -->
+ <element name="InvalidSymbolFault">
+ <complexType>
+ <sequence>
+ <element name="message" minOccurs="1" type="xsd:string" />
+ <element name="offer" minOccurs="1" type="tns:StockOffer" />
+ </sequence>
+ </complexType>
+ </element>
+
+ <element name="MarketClosedFault" type="xsd:int" />
+
+ <element name="TestNotDeclaredAtSourceFault" type="xsd:string" />
+
+ </schema>
+ </wsdl:types>
+
+
+ <wsdl:message name="stockQuoteOfferRequest">
+ <wsdl:part element="tns:stockQuoteOffer" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:message name="stockQuoteOfferResponse">
+ <wsdl:part element="tns:stockQuoteOfferResponse" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:message name="InvalidSymbolFault">
+ <wsdl:part element="tns:InvalidSymbolFault" name="fault" />
+ </wsdl:message>
+
+ <wsdl:message name="MarketClosedFault">
+ <wsdl:part element="tns:MarketClosedFault" name="fault" />
+ </wsdl:message>
+
+ <wsdl:message name="TestNotDeclaredAtSourceFault">
+ <wsdl:part element="tns:TestNotDeclaredAtSourceFault" name="fault" />
+ </wsdl:message>
+
+
+ <wsdl:portType name="StockExceptionTest">
+ <wsdl:operation name="stockQuoteOffer">
+ <wsdl:input message="tns:stockQuoteOfferRequest" name="stockQuoteOfferRequest" />
+
+ <wsdl:output message="tns:stockQuoteOfferResponse" name="stockQuoteOfferResponse" />
+
+ <wsdl:fault message="tns:InvalidSymbolFault" name="InvalidSymbolException" />
+
+ <wsdl:fault message="tns:MarketClosedFault" name="MarketClosedException" />
+
+ <wsdl:fault message="tns:TestNotDeclaredAtSourceFault" name="TestNotDeclaredAtSourceException" />
+ </wsdl:operation>
+
+
+ </wsdl:portType>
+
+ <wsdl:binding name="StockExceptionTestServiceSoapBinding" type="tns:StockExceptionTest">
+ <!-- <wsaw:UsingAddressing wsdl:required="false" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"/> -->
+
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+
+ <wsdl:operation name="stockQuoteOffer">
+ <wsdlsoap:operation soapAction="" />
+
+ <wsdl:input name="stockQuoteOfferRequest">
+ <wsdlsoap:body use="literal" />
+ </wsdl:input>
+
+ <wsdl:output name="stockQuoteOfferResponse">
+ <wsdlsoap:body use="literal" />
+ </wsdl:output>
+
+ <wsdl:fault name="InvalidSymbolException">
+ <wsdlsoap:fault name="InvalidSymbolException" use="literal" />
+ </wsdl:fault>
+
+ <wsdl:fault name="MarketClosedException">
+ <wsdlsoap:fault name="MarketClosedException" use="literal" />
+ </wsdl:fault>
+
+ <wsdl:fault name="TestNotDeclaredAtSourceException">
+ <wsdlsoap:fault name="TestNotDeclaredAtSourceException" use="literal" />
+ </wsdl:fault>
+
+
+
+ </wsdl:operation>
+
+
+ </wsdl:binding>
+
+ <wsdl:service name="StockExceptionTestService">
+ <wsdl:port binding="tns:StockExceptionTestServiceSoapBinding" name="StockExceptionTestServiceSoapPort">
+ <wsdlsoap:address location="http://localhost:8085/services/exchangeJaxbService" />
+
+ </wsdl:port>
+
+ </wsdl:service>
+
+</wsdl:definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-java-xml/LICENSE b/branches/trunk-20080910/modules/interface-java-xml/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/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/trunk-20080910/modules/interface-java-xml/NOTICE b/branches/trunk-20080910/modules/interface-java-xml/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/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/trunk-20080910/modules/interface-java-xml/pom.xml b/branches/trunk-20080910/modules/interface-java-xml/pom.xml new file mode 100644 index 0000000000..989e7bd6ae --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/pom.xml @@ -0,0 +1,83 @@ +<?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-interface-java-xml</artifactId> + <name>Apache Tuscany SCA Java Interface XML Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly-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-contribution-impl</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-sca</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.interface.java.xml</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef.java.xml*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaConstants.java b/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaConstants.java new file mode 100644 index 0000000000..5d2d8ed51c --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaConstants.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.xml; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.xml.Constants; + +/** + * Interface Java XML Constants. + * + * @version $Rev$ $Date$ + */ +public interface JavaConstants { + + String INTERFACE_JAVA = "interface.java"; + QName INTERFACE_JAVA_QNAME = new QName(Constants.SCA10_NS, "interface.java"); + String INTERFACE = "interface"; + String CALLBACK_INTERFACE = "callbackInterface"; + +} diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaInterfaceProcessor.java b/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaInterfaceProcessor.java new file mode 100644 index 0000000000..ae5bf4c56d --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/main/java/org/apache/tuscany/sca/interfacedef/java/xml/JavaInterfaceProcessor.java @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceProcessor implements StAXArtifactProcessor<JavaInterfaceContract>, JavaConstants { + + private JavaInterfaceFactory javaFactory; + private Monitor monitor; + + public JavaInterfaceProcessor(ModelFactoryExtensionPoint modelFactories, Monitor monitor) { + this.javaFactory = modelFactories.getFactory(JavaInterfaceFactory.class); + this.monitor = monitor; + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-javaxml-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-javaxml-validation-messages", Severity.ERROR, model, message,(Object[])messageParameters); + monitor.problem(problem); + } + } + + private JavaInterface createJavaInterface(String interfaceName) { + JavaInterface javaInterface = javaFactory.createJavaInterface(); + javaInterface.setUnresolved(true); + javaInterface.setName(interfaceName); + return javaInterface; + } + + public JavaInterfaceContract read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an <interface.java> + JavaInterfaceContract javaInterfaceContract = javaFactory.createJavaInterfaceContract(); + String interfaceName = reader.getAttributeValue(null, INTERFACE); + if (interfaceName != null) { + JavaInterface javaInterface = createJavaInterface(interfaceName); + javaInterfaceContract.setInterface(javaInterface); + } + + String callbackInterfaceName = reader.getAttributeValue(null, CALLBACK_INTERFACE); + if (callbackInterfaceName != null) { + JavaInterface javaCallbackInterface = createJavaInterface(callbackInterfaceName); + javaInterfaceContract.setCallbackInterface(javaCallbackInterface); + } + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && INTERFACE_JAVA_QNAME.equals(reader.getName())) { + break; + } + } + return javaInterfaceContract; + } + + public void write(JavaInterfaceContract javaInterfaceContract, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + // Write an <interface.java> + writer.writeStartElement(Constants.SCA10_NS, INTERFACE_JAVA); + JavaInterface javaInterface = (JavaInterface)javaInterfaceContract.getInterface(); + + if (javaInterface != null && javaInterface.getName() != null) { + writer.writeAttribute(INTERFACE, javaInterface.getName()); + } + + JavaInterface javaCallbackInterface = (JavaInterface)javaInterfaceContract.getCallbackInterface(); + if (javaCallbackInterface != null && javaCallbackInterface.getName() != null) { + writer.writeAttribute(CALLBACK_INTERFACE, javaCallbackInterface.getName()); + } + + writer.writeEndElement(); + } + + private JavaInterface resolveJavaInterface(JavaInterface javaInterface, ModelResolver resolver) throws ContributionResolveException { + + if (javaInterface != null && javaInterface.isUnresolved()) { + + // Resolve the Java interface + javaInterface = resolver.resolveModel(JavaInterface.class, javaInterface); + if (javaInterface.isUnresolved()) { + + // If the Java interface has never been resolved yet, do it now + ClassReference classReference = new ClassReference(javaInterface.getName()); + classReference = resolver.resolveModel(ClassReference.class, classReference); + Class javaClass = classReference.getJavaClass(); + if (javaClass == null) { + error("ClassNotFoundException", resolver, javaInterface.getName()); + return javaInterface; + //throw new ContributionResolveException(new ClassNotFoundException(javaInterface.getName())); + } + + try { + // Introspect the Java interface and populate the interface and + // operations + javaFactory.createJavaInterface(javaInterface, javaClass); + + } catch (InvalidInterfaceException e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", javaFactory, ce); + return javaInterface; + //throw ce; + } + + // Cache the resolved interface + javaInterface.setUnresolved(false); + resolver.addModel(javaInterface); + } + } + return javaInterface; + } + + public void resolve(JavaInterfaceContract javaInterfaceContract, ModelResolver resolver) throws ContributionResolveException { + + // Resolve the interface and callback interface + JavaInterface javaInterface = resolveJavaInterface((JavaInterface)javaInterfaceContract.getInterface(), resolver); + javaInterfaceContract.setInterface(javaInterface); + + JavaInterface javaCallbackInterface = resolveJavaInterface((JavaInterface)javaInterfaceContract.getCallbackInterface(), resolver); + javaInterfaceContract.setCallbackInterface(javaCallbackInterface); + } + + public QName getArtifactType() { + return INTERFACE_JAVA_QNAME; + } + + public Class<JavaInterfaceContract> getModelType() { + return JavaInterfaceContract.class; + } +} diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..b3e52e5709 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,19 @@ +# 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. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.interfacedef.java.xml.JavaInterfaceProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#interface.java,model=org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/interface-javaxml-validation-messages.properties b/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/interface-javaxml-validation-messages.properties new file mode 100644 index 0000000000..bc0a7192b5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/main/resources/interface-javaxml-validation-messages.properties @@ -0,0 +1,22 @@ +# +# +# 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. +# +# +ClassNotFoundException = Class Not Found Exception: {0} +ContributionResolveException = ContributionResolveException occured due to : diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/ReadTestCase.java b/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/ReadTestCase.java new file mode 100644 index 0000000000..313f950873 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/ReadTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.xml; + +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; + +/** + * Test reading Java interfaces. + * + * @version $Rev$ $Date$ + */ +public class ReadTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor<Object> staxProcessor; + private CompositeBuilder compositeBuilder; + + @Override + public void setUp() throws Exception { + DefaultExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + inputFactory = XMLInputFactory.newInstance(); + outputFactory = XMLOutputFactory.newInstance(); + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(extensionPoints); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, null); + + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + SCABindingFactory scaBindingFactory = modelFactories.getFactory(SCABindingFactory.class); + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + InterfaceContractMapper mapper = utilities.getUtility(InterfaceContractMapper.class); + IntentAttachPointTypeFactory attachPointTypeFactory = modelFactories.getFactory(IntentAttachPointTypeFactory.class); + compositeBuilder = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, attachPointTypeFactory, mapper, null); + } + + public void testReadComponentType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ComponentType componentType = (ComponentType)staxProcessor.read(reader); + assertNotNull(componentType); + } + + public void testReadConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ConstrainingType constrainingType = (ConstrainingType)staxProcessor.read(reader); + assertNotNull(constrainingType); + } + + public void testReadComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite composite = (Composite)staxProcessor.read(reader); + assertNotNull(composite); + + compositeBuilder.build(composite); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/WriteTestCase.java b/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/WriteTestCase.java new file mode 100644 index 0000000000..55fc12d176 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/test/java/org/apache/tuscany/sca/interfacedef/java/xml/WriteTestCase.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.xml; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; + +/** + * Test writing Java interfaces. + * + * @version $Rev$ $Date$ + */ +public class WriteTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor<Object> staxProcessor; + + @Override + public void setUp() throws Exception { + DefaultExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + inputFactory = XMLInputFactory.newInstance(); + outputFactory = XMLOutputFactory.newInstance(); + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(extensionPoints); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, null); + } + + public void testReadWriteComponentType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + ComponentType componentType = (ComponentType)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(componentType); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(componentType, outputFactory.createXMLStreamWriter(bos)); + } + + public void testReadWriteConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = (ConstrainingType)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(constrainingType); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(constrainingType, outputFactory.createXMLStreamWriter(bos)); + } + + public void testReadWriteComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + Composite composite = (Composite)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(composite); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(composite, outputFactory.createXMLStreamWriter(bos)); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/Calculator.composite b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/Calculator.composite new file mode 100644 index 0000000000..3de6410596 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/Calculator.composite @@ -0,0 +1,53 @@ +<?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. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:calc="http://sample.calculator" + targetNamespace="http://calc" + name="Calculator"> + + <service name="CalculatorService" promote="CalculatorServiceComponent"> + <interface.java interface="calculator.CalculatorService"/> + </service> + + <component name="CalculatorServiceComponent"> + <implementation.java class="calculator.CalculatorServiceImpl"/> + <reference name="addService" target="AddServiceComponent"/> + <reference name="subtractService" target="SubtractServiceComponent"/> + <reference name="multiplyService" target="MultiplyServiceComponent"/> + <reference name="divideService" target="DivideServiceComponent"/> + </component> + + <component name="AddServiceComponent"> + <implementation.java class="calculator.AddServiceImpl"/> + </component> + + <component name="SubtractServiceComponent"> + <implementation.java class="calculator.SubtractServiceImpl"/> + </component> + + <component name="MultiplyServiceComponent"> + <implementation.java class="calculator.MultiplyServiceImpl"/> + </component> + + <component name="DivideServiceComponent"> + <implementation.java class="calculator.DivideServiceImpl"/> + </component> + +</composite> diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorComponent.constrainingType b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorComponent.constrainingType new file mode 100644 index 0000000000..dca38c9224 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorComponent.constrainingType @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="ASCII"?> +<!-- + * 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. +--> +<constrainingType xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:calc="http://calc" + targetNamespace="http://calc" + name="CalculatorComponent"> + + <service name="CalculatorService"> + <interface.java interface="calculator.CalculatorService" /> + </service> + + <reference name="divideService"> + <interface.java interface="calculator.DivideService" /> + </reference> + +</constrainingType> +
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorImpl.componentType b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorImpl.componentType new file mode 100644 index 0000000000..23ebf576e5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/java/xml/CalculatorImpl.componentType @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="ASCII"?> +<!-- + * 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. +--> +<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0"> + + <service name="CalculatorService"> + <interface.java interface="calculator.CalculatorService" /> + </service> + + <reference name="divideService"> + <interface.java interface="calculator.DivideService" /> + </reference> + +</componentType> +
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-java/LICENSE b/branches/trunk-20080910/modules/interface-java/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/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/trunk-20080910/modules/interface-java/NOTICE b/branches/trunk-20080910/modules/interface-java/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/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/trunk-20080910/modules/interface-java/pom.xml b/branches/trunk-20080910/modules/interface-java/pom.xml new file mode 100644 index 0000000000..bab2576ea8 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/pom.xml @@ -0,0 +1,82 @@ +<?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-interface-java</artifactId> + <name>Apache Tuscany SCA Java Interface Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-extensibility</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-api</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>1.4-SNAPSHOT</version> + </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.interface.java</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef.java*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java new file mode 100644 index 0000000000..7853b597d3 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/DefaultJavaInterfaceFactory.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceFactoryImpl; +import org.apache.tuscany.sca.interfacedef.java.impl.PolicyJavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.PolicyFactory; + +/** + * A factory for the Java interface model. + * + * @version $Rev$ $Date$ + */ +public class DefaultJavaInterfaceFactory extends JavaInterfaceFactoryImpl implements JavaInterfaceFactory { + private ModelFactoryExtensionPoint modelFactoryExtensionPoint; + private boolean loadedVisitors; + + public DefaultJavaInterfaceFactory() { + } + + public DefaultJavaInterfaceFactory(ModelFactoryExtensionPoint modelFactoryExtensionPoint) { + this.modelFactoryExtensionPoint = modelFactoryExtensionPoint; + } + + @Override + public List<JavaInterfaceVisitor> getInterfaceVisitors() { + loadVisitors(); + return super.getInterfaceVisitors(); + } + + /** + * Load visitors declared under META-INF/services + */ + @SuppressWarnings("unchecked") + private void loadVisitors() { + if (loadedVisitors) + return; + + if (modelFactoryExtensionPoint != null) { + PolicyFactory policyFactory = modelFactoryExtensionPoint.getFactory(PolicyFactory.class); + if (policyFactory != null) { + addInterfaceVisitor(new PolicyJavaInterfaceVisitor(policyFactory)); + } + } + + // Get the databinding service declarations + Set<ServiceDeclaration> visitorDeclarations; + try { + visitorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(JavaInterfaceVisitor.class); + } catch (IOException e) { + throw new IllegalStateException(e); + } + + // Load data bindings + for (ServiceDeclaration visitorDeclaration: visitorDeclarations) { + JavaInterfaceVisitor visitor; + try { + Class<JavaInterfaceVisitor> visitorClass = (Class<JavaInterfaceVisitor>)visitorDeclaration.loadClass(); + visitor = visitorClass.newInstance(); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } catch (InstantiationException e) { + throw new IllegalArgumentException(e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } + addInterfaceVisitor(visitor); + } + + loadedVisitors = true; + } + + + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java new file mode 100644 index 0000000000..9c09ef50c2 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterface.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java; + +import javax.xml.namespace.QName; +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.interfacedef.Interface; + +/** + * Represents a Java interface. + * + * @version $Rev$ $Date$ + */ +public interface JavaInterface extends Interface, Base { + + /** + * Returns the name of the Java interface class. + * + * @return the name of the Java interface class + */ + String getName(); + + /** + * Sets the name of the Java interface class. + * + * @param className the name of the Java interface class + */ + void setName(String className); + + /** + * Returns the QName of the JAX-WS interface. + * + * @return the QName of the JAX-WS interface + */ + QName getQName(); + + /** + * Sets the QName of the JAX-WS interface. + * + * @param interfaceName the QName of the JAX-WS interface + */ + void setQName(QName interfaceName); + + /** + * Returns the Java interface class. + * + * @return the Java interface class + */ + Class<?> getJavaClass(); + + /** + * Sets the Java interface class. + * + * @param javaClass the Java interface class + */ + void setJavaClass(Class<?> javaClass); + + /** + * Returns the callback class specified in an @Callback annotation. + * + * @return the callback class specified in an @Callback annotation + */ + Class<?> getCallbackClass(); + + /** + * Sets the callback class specified in an @Callback annotation. + * + * @param callbackClass the callback class specified in an @Callback annotation + */ + void setCallbackClass(Class<?> callbackClass); +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.java new file mode 100644 index 0000000000..e3a84c63f0 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceContract.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.interfacedef.java; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * Represents a Java interface contract. + * JavaInterfaceContract + * + * @version $Rev$ $Date$ + */ +public interface JavaInterfaceContract extends InterfaceContract { + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java new file mode 100644 index 0000000000..9225926269 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaInterfaceFactory.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java; + +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * Factory for the Java interface model + * + * @version $Rev$ $Date$ + */ +public interface JavaInterfaceFactory { + + /** + * Creates a new Java interface model. + * + * @return + */ + JavaInterface createJavaInterface(); + + /** + * Creates a new Java interface model from an interface class. + * @param interfaceClass the interface class to introspect. + * @return + */ + JavaInterface createJavaInterface(Class<?> interfaceClass) throws InvalidInterfaceException; + + /** + * Creates the contents of a Java interface model from an interface class. + * @param javaInterface the Java interface model + * @param interfaceClass the interface class to introspect. + * @return + */ + void createJavaInterface(JavaInterface javaInterface, Class<?> interfaceClass) throws InvalidInterfaceException; + + /** + * Creates a new Java interface contract. + * + * @return + */ + JavaInterfaceContract createJavaInterfaceContract(); + + /** + * Registers the given visitor. + * + * @param visitor + */ + void addInterfaceVisitor(JavaInterfaceVisitor visitor); + + /** + * Deregisters the given visitor. + * + * @param visitor + */ + void removeInterfaceVisitor(JavaInterfaceVisitor visitor); + + /** + * Returns a list of interface visitors. + * + * @return + */ + List<JavaInterfaceVisitor> getInterfaceVisitors(); +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java new file mode 100644 index 0000000000..e6cb35cc4b --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.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.interfacedef.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Represents a Java operation. + * + * @version $Rev$ $Date$ + */ +public interface JavaOperation extends Operation { + + /** + * Returns the Java method defining the operation. + * @return the Java method + */ + Method getJavaMethod(); + + /** + * Sets the Java method defining the operation. + * @param method the Java method + */ + void setJavaMethod(Method method); + + /** + * Returns the JAX-WS @WebMethod action parameter. + * @return the action value + */ + String getAction(); + + /** + * Sets the JAX-WS @WebMethod action parameter. + * @param action the action value + */ + void setAction(String action); + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java new file mode 100644 index 0000000000..d43ebe558b --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceContractImpl.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; + +/** + * Represents a Java interface contract. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceContractImpl extends InterfaceContractImpl implements JavaInterfaceContract { + + protected JavaInterfaceContractImpl() { + } + + @Override + public JavaInterfaceContractImpl clone() throws CloneNotSupportedException { + return (JavaInterfaceContractImpl) super.clone(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java new file mode 100644 index 0000000000..b1efd6e197 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * A factory for the Java model. + * + * @version $Rev$ $Date$ + */ +public abstract class JavaInterfaceFactoryImpl implements JavaInterfaceFactory { + + private List<JavaInterfaceVisitor> visitors = new ArrayList<JavaInterfaceVisitor>(); + private JavaInterfaceIntrospectorImpl introspector; + + public JavaInterfaceFactoryImpl() { + introspector = new JavaInterfaceIntrospectorImpl(this); + } + + public JavaInterface createJavaInterface() { + return new JavaInterfaceImpl(); + } + + public JavaInterface createJavaInterface(Class<?> interfaceClass) throws InvalidInterfaceException { + JavaInterface javaInterface = createJavaInterface(); + introspector.introspectInterface(javaInterface, interfaceClass); + return javaInterface; + } + + public void createJavaInterface(JavaInterface javaInterface, Class<?> interfaceClass) throws InvalidInterfaceException { + introspector.introspectInterface(javaInterface, interfaceClass); + } + + public JavaInterfaceContract createJavaInterfaceContract() { + return new JavaInterfaceContractImpl(); + } + + public void addInterfaceVisitor(JavaInterfaceVisitor extension) { + visitors.add(extension); + } + + public void removeInterfaceVisitor(JavaInterfaceVisitor extension) { + visitors.remove(extension); + } + + public List<JavaInterfaceVisitor> getInterfaceVisitors() { + return visitors; + } +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java new file mode 100644 index 0000000000..42e45317b7 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import javax.xml.namespace.QName; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +/** + * Represents a Java interface. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceImpl extends InterfaceImpl implements JavaInterface { + + private String className; + private Class<?> javaClass; + private Class<?> callbackClass; + private QName qname; + + protected JavaInterfaceImpl() { + } + + public String getName() { + if (isUnresolved()) { + return className; + } else if (javaClass != null) { + return javaClass.getName(); + } else { + return null; + } + } + + public void setName(String className) { + if (!isUnresolved()) { + throw new IllegalStateException(); + } + this.className = className; + } + + public QName getQName() { + return qname; + } + + public void setQName(QName interfacename) { + qname = interfacename; + } + + public Class<?> getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class<?> javaClass) { + this.javaClass = javaClass; + } + + public Class<?> getCallbackClass() { + return callbackClass; + } + + public void setCallbackClass(Class<?> callbackClass) { + this.callbackClass = callbackClass; + } + + @Override + public String toString() { + return getName(); + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof JavaInterface) { + if (getName() != null) { + return getName().equals(((JavaInterface)obj).getName()); + } else { + return ((JavaInterface)obj).getName() == null; + } + } else { + return false; + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java new file mode 100644 index 0000000000..b1198824fa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java @@ -0,0 +1,258 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidCallbackException; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.InvalidOperationException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.OverloadedOperationException; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.osoa.sca.annotations.Conversational; +import org.osoa.sca.annotations.EndsConversation; +import org.osoa.sca.annotations.OneWay; +import org.osoa.sca.annotations.Remotable; + +/** + * Default implementation of a Java interface introspector. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceIntrospectorImpl { + public static final String IDL_INPUT = "idl:input"; + + private static final String UNKNOWN_DATABINDING = null; + + private List<JavaInterfaceVisitor> visitors = new ArrayList<JavaInterfaceVisitor>(); + + public JavaInterfaceIntrospectorImpl(JavaInterfaceFactory javaFactory) { + this.visitors = javaFactory.getInterfaceVisitors(); + } + + public void introspectInterface(JavaInterface javaInterface, Class<?> clazz) + throws InvalidInterfaceException { + javaInterface.setJavaClass(clazz); + + boolean remotable = clazz.isAnnotationPresent(Remotable.class); + + // Consider @javax.ejb.Remote, java.rmi.Remote and javax.ejb.EJBObject + // equivalent to @Remotable + if (!remotable) { + for (Annotation annotation : clazz.getAnnotations()) { + if ("javax.ejb.Remote".equals(annotation.annotationType().getName())) { + remotable = true; + break; + } + } + } + if (!remotable) { + for (Class<?> superInterface : clazz.getInterfaces()) { + if (Remote.class == superInterface || "javax.ejb.EJBObject".equals(superInterface.getName())) { + remotable = true; + break; + } + } + } + + javaInterface.setRemotable(remotable); + + boolean conversational = clazz.isAnnotationPresent(Conversational.class); + javaInterface.setConversational(conversational); + + Class<?> callbackClass = null; + org.osoa.sca.annotations.Callback callback = clazz.getAnnotation(org.osoa.sca.annotations.Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + callbackClass = callback.value(); + if (remotable && !callbackClass.isAnnotationPresent(Remotable.class)) { + throw new InvalidCallbackException("Callback must be remotable on a remotable interface"); + } + if (!remotable && callbackClass.isAnnotationPresent(Remotable.class)) { + throw new InvalidCallbackException("Callback must not be remotable on a local interface"); + } + } else if (callback != null && Void.class.equals(callback.value())) { + throw new InvalidCallbackException("No callback interface specified on annotation"); + } + + javaInterface.setCallbackClass(callbackClass); + + String ns = JavaXMLMapper.getNamespace(clazz); + javaInterface.getOperations().addAll(getOperations(clazz, remotable, conversational, ns)); + + for (JavaInterfaceVisitor extension : visitors) { + extension.visitInterface(javaInterface); + } + } + + private Class<?>[] getActualTypes(Type[] types, Class<?>[] rawTypes, Map<String, Type> typeBindings) { + Class<?>[] actualTypes = new Class<?>[types.length]; + for (int i = 0; i < actualTypes.length; i++) { + actualTypes[i] = getActualType(types[i], rawTypes[i], typeBindings); + } + return actualTypes; + } + + private Class<?> getActualType(Type type, Class<?> rawType, Map<String, Type> typeBindings) { + if (type instanceof TypeVariable<?>) { + TypeVariable<?> typeVariable = (TypeVariable<?>)type; + type = typeBindings.get(typeVariable.getName()); + if (type instanceof Class<?>) { + return (Class<?>)type; + } + } + return rawType; + } + + private <T> List<Operation> getOperations(Class<T> clazz, + boolean remotable, + boolean conversational, + String ns) throws InvalidInterfaceException { + + Set<Type> genericInterfaces = new HashSet<Type>(); + for (Type t : clazz.getGenericInterfaces()) { + genericInterfaces.add(t); + } + Map<String, Type> typeBindings = new HashMap<String, Type>(); + for (Type genericInterface : genericInterfaces) { + if (genericInterface instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType)genericInterface; + TypeVariable<?>[] typeVariables = ((Class<?>)parameterizedType.getRawType()).getTypeParameters(); + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + for (int i = 0; i < typeArguments.length; i++) { + typeBindings.put(typeVariables[i].getName(), typeArguments[i]); + } + } + } + + Method[] methods = clazz.getMethods(); + List<Operation> operations = new ArrayList<Operation>(methods.length); + Set<String> names = remotable ? new HashSet<String>() : null; + for (Method method : methods) { + if (method.getDeclaringClass() == Object.class) { + // Skip the methods on the Object.class + continue; + } + String name = method.getName(); + if (remotable && names.contains(name)) { + throw new OverloadedOperationException(method); + } + if (remotable) { + names.add(name); + } + + Class<?> returnType = getActualType(method.getGenericReturnType(), method.getReturnType(), typeBindings); + Class<?>[] parameterTypes = + getActualTypes(method.getGenericParameterTypes(), method.getParameterTypes(), typeBindings); + Class<?>[] faultTypes = + getActualTypes(method.getGenericExceptionTypes(), method.getExceptionTypes(), typeBindings); + + boolean nonBlocking = method.isAnnotationPresent(OneWay.class); + if (nonBlocking) { + if (!(returnType == void.class)) { + throw new InvalidOperationException( + "Method should return 'void' when declared with an @OneWay annotation. " + method, + method); + } + if (!(faultTypes.length == 0)) { + throw new InvalidOperationException( + "Method should not declare exceptions with an @OneWay annotation. " + method, + method); + } + } + + ConversationSequence conversationSequence = ConversationSequence.CONVERSATION_NONE; + if (method.isAnnotationPresent(EndsConversation.class)) { + if (!conversational) { + throw new InvalidOperationException( + "Method is marked as end conversation but contract is not conversational", + method); + } + conversationSequence = ConversationSequence.CONVERSATION_END; + } else if (conversational) { + conversationSequence = ConversationSequence.CONVERSATION_CONTINUE; + } + + // Set outputType to null for void + XMLType xmlReturnType = new XMLType(new QName(ns, "return"), null); + DataType<XMLType> returnDataType = + returnType == void.class ? null : new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, returnType, method + .getGenericReturnType(), xmlReturnType); + List<DataType> paramDataTypes = new ArrayList<DataType>(parameterTypes.length); + Type[] genericParamTypes = method.getGenericParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++) { + Class paramType = parameterTypes[i]; + XMLType xmlParamType = new XMLType(new QName(ns, "arg" + i), null); + paramDataTypes.add(new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, paramType, genericParamTypes[i], + xmlParamType)); + } + List<DataType> faultDataTypes = new ArrayList<DataType>(faultTypes.length); + Type[] genericFaultTypes = method.getGenericExceptionTypes(); + for (int i = 0; i < faultTypes.length; i++) { + Class<?> faultType = faultTypes[i]; + // Only add checked exceptions + // JAXWS Specification v2.1 section 3.7 says RemoteException should not be mapped + if (Exception.class.isAssignableFrom(faultType) && (!RuntimeException.class.isAssignableFrom(faultType)) + && (!RemoteException.class.isAssignableFrom(faultType))) { + XMLType xmlFaultType = new XMLType(new QName(ns, faultType.getSimpleName()), null); + DataType<XMLType> faultDataType = + new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, faultType, genericFaultTypes[i], xmlFaultType); + faultDataTypes.add(new DataTypeImpl<DataType>(UNKNOWN_DATABINDING, faultType, genericFaultTypes[i], + faultDataType)); + } + } + + DataType<List<DataType>> inputType = + new DataTypeImpl<List<DataType>>(IDL_INPUT, Object[].class, paramDataTypes); + JavaOperation operation = new JavaOperationImpl(); + operation.setName(name); + operation.setInputType(inputType); + operation.setOutputType(returnDataType); + operation.setFaultTypes(faultDataTypes); + operation.setConversationSequence(conversationSequence); + operation.setNonBlocking(nonBlocking); + operation.setJavaMethod(method); + operations.add(operation); + } + return operations; + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java new file mode 100644 index 0000000000..2a9e3c5329 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +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.JavaOperation; + +/** + * Contains methods for mapping between an operation in a + * {@link org.apache.tuscany.spi.model.ServiceContract} and a method defined by + * a Java interface + * + * @version $Rev$ $Date$ + */ +public final class JavaInterfaceUtil { + + private JavaInterfaceUtil() { + } + + /** + * Return the method on the implementation class that matches the operation. + * + * @param implClass the implementation class or interface + * @param operation the operation to match + * @return the method described by the operation + * @throws NoSuchMethodException if no such method exists + * @Deprecated + */ + public static Method findMethod(Class<?> implClass, Operation operation) throws NoSuchMethodException { + String name = operation.getName(); + if (operation instanceof JavaOperation) { + name = ((JavaOperation)operation).getJavaMethod().getName(); + } + Interface interface1 = operation.getInterface(); + int numParams = operation.getInputType().getLogical().size(); + if (interface1 != null && interface1.isRemotable()) { + List<Method> matchingMethods = new ArrayList<Method>(); + for (Method m : implClass.getMethods()) { + if (m.getName().equals(name) && m.getParameterTypes().length == numParams) { + matchingMethods.add(m); + } + } + + // TUSCANY-2180 If there is only one method then we just match on the name + // (this is the same as the existing behaviour) + if (matchingMethods.size() == 1) { + return matchingMethods.get(0); + } + if (matchingMethods.size() > 1) { + // TUSCANY-2180 We need to check the parameter types too + Class<?>[] paramTypes = getPhysicalTypes(operation); + return implClass.getMethod(name, paramTypes); + } + + // No matching method found + throw new NoSuchMethodException("No matching method for operation " + operation.getName() + + " is found on " + + implClass); + } + Class<?>[] paramTypes = getPhysicalTypes(operation); + return implClass.getMethod(name, paramTypes); + } + + /** + * @Deprecated + */ + private static Class<?>[] getPhysicalTypes(Operation operation) { + DataType<List<DataType>> inputType = operation.getInputType(); + if (inputType == null) { + return new Class<?>[] {}; + } + List<DataType> types = inputType.getLogical(); + Class<?>[] javaTypes = new Class<?>[types.size()]; + for (int i = 0; i < javaTypes.length; i++) { + Type physical = types.get(i).getPhysical(); + if (physical instanceof Class<?>) { + javaTypes[i] = (Class<?>)physical; + } else { + throw new UnsupportedOperationException(); + } + } + return javaTypes; + } + + /** + * Searches a collection of operations for a match against the given method + * + * @param method the method to match + * @param operations the operations to match against + * @return a matching operation or null + * @Deprecated + */ + public static Operation findOperation(Method method, Collection<Operation> operations) { + for (Operation operation : operations) { + if (match(operation, method)) { + return operation; + } + } + return null; + } + + /** + * Determines if the given operation matches the given method + * + * @return true if the operation matches, false if does not + */ + private static boolean match(Operation operation, Method method) { + Class<?>[] params = method.getParameterTypes(); + DataType<List<DataType>> inputType = operation.getInputType(); + List<DataType> types = inputType.getLogical(); + boolean found = true; + if (types.size() == params.length && method.getName().equals(operation.getName())) { + for (int i = 0; i < params.length; i++) { + Class<?> clazz = params[i]; + if (!clazz.equals(operation.getInputType().getLogical().get(i).getPhysical())) { + found = false; + } + } + } else { + found = false; + } + return found; + + } + + private static String getPackageName(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + public static String getNamespace(Class<?> cls) { + String packageName = getPackageName(cls); + if ("".equals(packageName)) { + return ""; + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = packageName.split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return ns.toString(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java new file mode 100644 index 0000000000..4384213bf5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; + +/** + * Represents a Java operation. + * + * @version $Rev$ $Date$ + */ +public class JavaOperationImpl extends OperationImpl implements JavaOperation { + + private Method method; + private String action; + + public Method getJavaMethod() { + return method; + } + + public void setJavaMethod(Method method) { + this.method = method; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + final JavaOperationImpl other = (JavaOperationImpl)obj; + if (method == null) { + if (other.method != null) + return false; + } else if (!method.equals(other.method)) + return false; + return true; + } + + @Override + public String toString() { + return method == null ? "null" : method.toGenericString(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java new file mode 100644 index 0000000000..ed00510a67 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/PolicyJavaInterfaceVisitor.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +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.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.osoa.sca.annotations.PolicySets; +import org.osoa.sca.annotations.Requires; + +/** + * Processes an {@link org.osoa.sca.annotations.Requires} annotation + * + * @version $Rev$ $Date$ + */ +public class PolicyJavaInterfaceVisitor implements JavaInterfaceVisitor { + private PolicyFactory policyFactory; + + public PolicyJavaInterfaceVisitor(PolicyFactory policyFactory) { + super(); + this.policyFactory = policyFactory; + } + + private QName getQName(String intentName) { + QName qname; + if (intentName.startsWith("{")) { + int i = intentName.indexOf('}'); + if (i != -1) { + qname = new QName(intentName.substring(1, i), intentName.substring(i + 1)); + } else { + qname = new QName("", intentName); + } + } else { + qname = new QName("", intentName); + } + return qname; + } + + /** + * Read policy intents on the given interface or class + * @param clazz + * @param requiredIntents + */ + private void readIntentsAndPolicySets(Class<?> clazz, List<Intent> requiredIntents, List<PolicySet> policySets) { + Requires intentAnnotation = clazz.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + for (String intentName : intentNames) { + + // Add each intent to the list + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + requiredIntents.add(intent); + } + } + } + + PolicySets policySetAnnotation = clazz.getAnnotation(PolicySets.class); + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + for (String policySetName : policySetNames) { + + // Add each intent to the list + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + policySets.add(policySet); + } + } + } + } + + private void readIntents(Requires intentAnnotation, List<Intent> requiredIntents) { + //Requires intentAnnotation = method.getAnnotation(Requires.class); + if (intentAnnotation != null) { + String[] intentNames = intentAnnotation.value(); + if (intentNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String intentName : intentNames) { + + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + Intent intent = policyFactory.createIntent(); + intent.setName(getQName(intentName)); + //intent.getOperations().add(operation); + requiredIntents.add(intent); + } + } + } + } + + private void readPolicySets(PolicySets policySetAnnotation, List<PolicySet> policySets) { + if (policySetAnnotation != null) { + String[] policySetNames = policySetAnnotation.value(); + if (policySetNames.length != 0) { + //Operation operation = assemblyFactory.createOperation(); + //operation.setName(method.getName()); + //operation.setUnresolved(true); + for (String policySetName : policySetNames) { + // Add each intent to the list, associated with the + // operation corresponding to the annotated method + PolicySet policySet = policyFactory.createPolicySet(); + policySet.setName(getQName(policySetName)); + //intent.getOperations().add(operation); + policySets.add(policySet); + } + } + } + } + + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { + + if (javaInterface.getJavaClass() != null) { + readIntentsAndPolicySets(javaInterface.getJavaClass(), javaInterface.getRequiredIntents(), javaInterface + .getPolicySets()); + + // Read intents on the service interface methods + List<Operation> operations = javaInterface.getOperations(); + for (Operation op : operations) { + JavaOperation operation = (JavaOperation)op; + Method method = operation.getJavaMethod(); + if (method.getAnnotation(Requires.class) != null || method.getAnnotation(PolicySets.class) != null) { + readIntents(method.getAnnotation(Requires.class), op.getRequiredIntents()); + readPolicySets(method.getAnnotation(PolicySets.class), op.getPolicySets()); + } + } + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java new file mode 100644 index 0000000000..3bc03a528e --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/introspect/JavaInterfaceVisitor.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspect; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; + +/** + * Implementations introspect metadata on a Java interface, populating the + * corresponding {@link JavaInterface} + * + * @version $Rev$ $Date$ + */ +public interface JavaInterfaceVisitor { + + /** + * Visit a java interface + * @param javaInterface + * @throws InvalidInterfaceException + */ + void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException; + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory b/branches/trunk-20080910/modules/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory new file mode 100644 index 0000000000..5ba12ec137 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilDuplicateRemotableTestCase.java b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilDuplicateRemotableTestCase.java new file mode 100644 index 0000000000..14b0577f65 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilDuplicateRemotableTestCase.java @@ -0,0 +1,308 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.OverloadedOperationException; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Remotable; + +/** + * This test case will test that a Component that has multiple Remotable interfaces + * that contain methods with the same name will correctly select the right method. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceUtilDuplicateRemotableTestCase extends TestCase { + + /** + * Test to get the getTime() method from the LocalTimeService + * + * @throws Exception Test failed + */ + public void testLocalTimeServiceGetTime() throws Exception { + doTestLocalTimeServiceGetTime(LocalTimeService.class); + } + + /** + * Test to get the getTime() method from the LocalTimeService interface from + * the specified class + * + * @param timeServiceClass The class that implements the LocalTimeService + * @throws Exception Test failed + */ + private void doTestLocalTimeServiceGetTime(Class timeServiceClass) throws Exception { + // Add a getTime() method + Operation operation = newOperation("getTime", LocalTimeService.class); + + Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation); + assertEquals("getTime", method.getName()); + assertEquals(0, method.getParameterTypes().length); + } + + /** + * Test to get the getTime(String) method from the WorldTimeService + * + * @throws Exception Test failed + */ + public void testWorldTimeServiceGetTime() throws Exception { + doTestWorldTimeServiceGetTime(WorldTimeService.class); + } + + /** + * Test to get the getTime(String) method from the WorldTimeService interface from + * the specified class + * + * @param timeServiceClass The class that implements the WorldTimeService + * @throws Exception Test failed + */ + private void doTestWorldTimeServiceGetTime(Class timeServiceClass) throws Exception { + // Add a getTime(String) method + Operation operation = newOperation("getTime", WorldTimeService.class, String.class); + + Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation); + assertEquals("getTime", method.getName()); + assertEquals(1, method.getParameterTypes().length); + assertEquals(String.class, method.getParameterTypes()[0]); + } + + /** + * Test to get the getTime(int) method from the GMTTimeService + * + * @throws Exception Test failed + */ + public void testGMTTimeServiceGetTime() throws Exception { + doTestGMTTimeServiceGetTime(GMTTimeService.class); + } + + /** + * Test to get the getTime(int) method from the GMTTimeService interface from + * the specified class + * + * @param timeServiceClass The class that implements the WorldTimeService + * @throws Exception Test failed + */ + private void doTestGMTTimeServiceGetTime(Class timeServiceClass) throws Exception { + // Add a getTime(String) method + Operation operation = newOperation("getTime", GMTTimeService.class, Integer.TYPE); + + Method method = JavaInterfaceUtil.findMethod(timeServiceClass, operation); + assertEquals("getTime", method.getName()); + assertEquals(1, method.getParameterTypes().length); + assertEquals(Integer.TYPE, method.getParameterTypes()[0]); + } + + + /** + * Test to get the getTime() method from the LocalTimeService on the + * TimeServiceImpl class + * + * @throws Exception Test failed + */ + public void testLocalTimeServiceGetTimeFromTimeServiceImpl() throws Exception { + doTestLocalTimeServiceGetTime(TimeServiceImpl.class); + } + + /** + * Test to get the getTime(String) method from the WorldTimeService on the + * TimeServiceImpl class + * + * @throws Exception Test failed + */ + public void testWorldTimeServiceGetTimeFromTimeServiceImpl() throws Exception { + doTestWorldTimeServiceGetTime(TimeServiceImpl.class); + } + + /** + * Test to get the getTime(int) method from the GMTTimeService + * + * @throws Exception Test failed + */ + public void testGMTTimeServiceGetTimeFromTimeServiceImpl() throws Exception { + doTestGMTTimeServiceGetTime(TimeServiceImpl.class); + } + + /** + * Creates a new operation with the specified name and parameter types + * + * @param name The name of the operation + * @param operationInterface The interface to which the operation belongs + * @param parameterTypes The types of the parameters for this operation + * @return An operation with the specified name and parameter types + */ + private static Operation newOperation(String name, Class operationInterface, Class... parameterTypes) { + // Create and set the operation name + Operation operation = new OperationImpl(); + operation.setName(name); + + // Make the operation remotable + Interface iface = new InterfaceImpl(); + iface.setRemotable(true); + operation.setInterface(iface); + + // Construct the parameters + List<DataType> types = new ArrayList<DataType>(); + DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + for (Class parameterType : parameterTypes) { + DataType type = new DataTypeImpl<Class>(parameterType, Object.class); + types.add(type); + } + operation.setInputType(inputType); + + // Return the created operation + return operation; + } + + /** + * Test case that validates that a @Remotable interface with Overloaded operations + * is detected. + * + * This test case is for TUSCANY-2194 + */ + public void testDuplicateOpeartionOnRemotableInterface() + { + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + JavaInterfaceIntrospectorImpl introspector = new JavaInterfaceIntrospectorImpl(javaFactory); + JavaInterfaceImpl javaInterface = new JavaInterfaceImpl(); + + try { + introspector.introspectInterface(javaInterface, DuplicateMethodOnRemotableInterface.class); + Assert.fail("Should have thrown an exception as @Remotable interface has overloaded methods"); + } catch (OverloadedOperationException ex) { + // As expected + // Make sure that the class and method names are in the exception + String exMsg = ex.toString(); + Assert.assertTrue("Method name missing from exception", exMsg.indexOf("aDuplicateMethod") != -1); + Assert.assertTrue("Class name missing from exception", + exMsg.indexOf(DuplicateMethodOnRemotableInterface.class.getName()) != -1); + } catch (InvalidInterfaceException ex) { + // Should have thrown OverloadedOperationException + Assert.fail("Should have thrown an OverloadedOperationException but threw " + ex); + } + } + + + /** + * Sample @Remotable interface that has an overloaded operation which is not + * allowed according to the SCA Assembly Specification. + */ + @Remotable + private interface DuplicateMethodOnRemotableInterface { + void aNonDuplicateMethod(); + void aDuplicateMethod(); + void aDuplicateMethod(String aParam); + } + + + /** + * Sample interface needed for the unit tests + */ + @Remotable + private interface LocalTimeService { + + /** + * Gets the local time + * + * @return The Local Time + */ + String getTime(); + } + + /** + * Sample interface needed for the unit tests + */ + @Remotable + private interface WorldTimeService { + + /** + * Gets the time in the specified TimeZone + * + * @param timeZone A Time Zone + * + * @return The time in the specified TimeZone + */ + String getTime(String timeZone); + } + + /** + * Sample interface needed for the unit tests + */ + @Remotable + private interface GMTTimeService { + + /** + * Gets the time with the specified GMT offset + * + * @param gmtOffset A GMT offset in hours + * + * @return The time with the specified GMT offset + */ + String getTime(int gmtOffset); + } + + /** + * Sample implementation class that implements the three @Remotable interfaces + */ + private class TimeServiceImpl implements LocalTimeService, WorldTimeService, GMTTimeService { + /** + * Gets the local time + * + * @return The Local Time + */ + public String getTime() { + return "The current local time"; + } + + /** + * Gets the time in the specified TimeZone + * + * @param timeZone A Time Zone + * + * @return The time in the specified TimeZone + */ + public String getTime(String timeZone) { + return "The current time in TimeZone " + timeZone; + } + + /** + * Gets the time with the specified GMT offset + * + * @param gmtOffset A GMT offset in hours + * + * @return The time with the specified GMT offset + */ + public String getTime(int gmtOffset) { + return "The current time with GMT offset of " + gmtOffset; + } + } +} diff --git a/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java new file mode 100644 index 0000000000..66f98adce3 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtilTestCase.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.impl; + +import static org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil.findOperation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; + +/** + * @version $Rev$ $Date$ + */ +public class JavaInterfaceUtilTestCase extends TestCase { + private List<Operation> operations; + + public void testNoParamsFindOperation() throws Exception { + Method method = Foo.class.getMethod("foo"); + Operation ret = findOperation(method, operations); + assertEquals("foo", ret.getName()); + assertEquals(0, method.getParameterTypes().length); + } + + public void testParamsFindOperation() throws Exception { + Method method = Foo.class.getMethod("foo", String.class); + Operation ret = findOperation(method, operations); + assertEquals("foo", ret.getName()); + assertEquals(String.class, method.getParameterTypes()[0]); + } + + public void testPrimitiveParamFindOperation() throws NoSuchMethodException { + Method method = Foo.class.getMethod("foo", Integer.TYPE); + Operation operation = findOperation(method, operations); + assertEquals(Integer.TYPE, operation.getInputType().getLogical().get(0).getPhysical()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + Operation operation = newOperation("foo"); + List<DataType> types = new ArrayList<DataType>(); + DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + operation.setInputType(inputType); + + operations = new ArrayList<Operation>(); + operations.add(operation); + + types = new ArrayList<DataType>(); + inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + DataType type = new DataTypeImpl<Class>(String.class, Object.class); + types.add(type); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList<DataType>(); + type = new DataTypeImpl<Class>(String.class, Object.class); + DataType type2 = new DataTypeImpl<Class>(String.class, Object.class); + types.add(type); + types.add(type2); + inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList<DataType>(); + type = new DataTypeImpl<Class>(Integer.class, Object.class); + types.add(type); + inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + types = new ArrayList<DataType>(); + type = new DataTypeImpl<Class>(Integer.TYPE, Object.class); + types.add(type); + inputType = new DataTypeImpl<List<DataType>>(Object[].class, types); + operation = newOperation("foo"); + operation.setInputType(inputType); + operations.add(operation); + + } + + private interface Foo { + void foo(); + + void foo(String foo); + + void foo(int b); + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java new file mode 100644 index 0000000000..f90a5cb8a1 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/ConversationalIntrospectionTestCase.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspection.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InvalidOperationException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.osoa.sca.annotations.Conversational; +import org.osoa.sca.annotations.EndsConversation; + +/** + * @version $Rev$ $Date$ + */ +public class ConversationalIntrospectionTestCase extends TestCase { + private JavaInterfaceFactory javaFactory; + + @Override + protected void setUp() throws Exception { + javaFactory = new DefaultJavaInterfaceFactory(); + } + + private Operation getOperation(Interface i, String name) { + for (Operation op : i.getOperations()) { + if (op.getName().equals(name)) { + return op; + } + } + return null; + } + + public void testServiceContractConversationalInformationIntrospection() throws Exception { + Interface i = javaFactory.createJavaInterface(Foo.class); + assertNotNull(i); + assertTrue(i.isConversational()); + ConversationSequence seq = getOperation(i, "operation").getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_CONTINUE, seq); + seq = getOperation(i, "endOperation").getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_END, seq); + } + + public void testBadServiceContract() throws Exception { + try { + javaFactory.createJavaInterface(BadFoo.class); + fail(); + } catch (InvalidOperationException e) { + // expected + } + } + + public void testNonConversationalInformationIntrospection() throws Exception { + Interface i = javaFactory.createJavaInterface(NonConversationalFoo.class); + assertFalse(i.isConversational()); + ConversationSequence seq = getOperation(i, "operation") + .getConversationSequence(); + assertEquals(ConversationSequence.CONVERSATION_NONE, seq); + } + + @Conversational + private interface Foo { + void operation(); + + @EndsConversation + void endOperation(); + } + + private interface BadFoo { + void operation(); + + @EndsConversation + void endOperation(); + } + + private interface NonConversationalFoo { + void operation(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java new file mode 100644 index 0000000000..14ac8b0134 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/JavaInterfaceProcessorRegistryImplTestCase.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspection.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.io.IOException; +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class JavaInterfaceProcessorRegistryImplTestCase extends TestCase { + private JavaInterfaceFactory factory; + + @SuppressWarnings("unchecked") + public void testSimpleInterface() throws InvalidInterfaceException { + JavaInterface intf = factory.createJavaInterface(Simple.class); + + assertEquals(Simple.class, intf.getJavaClass()); + List<Operation> operations = intf.getOperations(); + assertEquals(1, operations.size()); + Operation baseInt = operations.get(0); + assertEquals("baseInt", baseInt.getName()); + + QName element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "return"); + + DataType<XMLType> returnType = baseInt.getOutputType(); + assertEquals(Integer.TYPE, returnType.getPhysical()); + assertEquals(element, returnType.getLogical().getElementName()); + + List<DataType> parameterTypes = baseInt.getInputType().getLogical(); + assertEquals(1, parameterTypes.size()); + DataType<XMLType> arg0 = parameterTypes.get(0); + assertEquals(Integer.TYPE, arg0.getPhysical()); + + element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "arg0"); + assertEquals(element, arg0.getLogical().getElementName()); + + List<DataType> faultTypes = baseInt.getFaultTypes(); + assertEquals(1, faultTypes.size()); + DataType<DataType<XMLType>> fault0 = faultTypes.get(0); + assertEquals(IOException.class, fault0.getPhysical()); + element = new QName("http://impl.introspection.java.interfacedef.sca.tuscany.apache.org/", "IOException"); + assertEquals(element, fault0.getLogical().getLogical().getElementName()); + } + + public void testUnregister() throws Exception { + JavaInterfaceVisitor extension = createMock(JavaInterfaceVisitor.class); + extension.visitInterface(EasyMock.isA(JavaInterface.class)); + expectLastCall().once(); + replay(extension); + factory.addInterfaceVisitor(extension); + factory.createJavaInterface(Base.class); + factory.removeInterfaceVisitor(extension); + factory.createJavaInterface(Base.class); + verify(extension); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + factory = new DefaultJavaInterfaceFactory(); + + } + + private static interface Base { + int baseInt(int param) throws IllegalArgumentException, IOException; + } + + private static interface Simple extends Base { + + } +} diff --git a/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java new file mode 100644 index 0000000000..5a454f176c --- /dev/null +++ b/branches/trunk-20080910/modules/interface-java/src/test/java/org/apache/tuscany/sca/interfacedef/java/introspection/impl/PolicyProcessorTestCase.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.java.introspection.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.impl.PolicyJavaInterfaceVisitor; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.osoa.sca.annotations.PolicySets; +import org.osoa.sca.annotations.Requires; + +/** + * @version $Rev$ $Date$ + */ +public class PolicyProcessorTestCase extends TestCase { + private JavaInterfaceFactory factory = new DefaultJavaInterfaceFactory(); + private PolicyJavaInterfaceVisitor policyProcessor; + + public void testInterfaceLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface1.class); + policyProcessor.visitInterface(type); + assertEquals(1, type.getRequiredIntents().size()); + assertEquals(1, type.getPolicySets().size()); + } + + public void testMethodLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface2.class); + policyProcessor.visitInterface(type); + assertEquals(0, type.getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(0).getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(1).getRequiredIntents().size()); + assertEquals(0, type.getPolicySets().size()); + assertEquals(1, type.getOperations().get(0).getPolicySets().size()); + assertEquals(1, type.getOperations().get(1).getPolicySets().size()); + } + + public void testInterfaceAndMethodLevel() throws Exception { + JavaInterface type = factory.createJavaInterface(Interface3.class); + policyProcessor.visitInterface(type); + assertEquals(1, type.getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(0).getRequiredIntents().size()); + assertEquals(1, type.getOperations().get(1).getRequiredIntents().size()); + assertEquals(1, type.getPolicySets().size()); + assertEquals(1, type.getOperations().get(0).getPolicySets().size()); + assertEquals(1, type.getOperations().get(1).getPolicySets().size()); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + policyProcessor = new PolicyJavaInterfaceVisitor(new DefaultPolicyFactory()); + } + + // @Remotable + @Requires( {"transaction.global"}) + @PolicySets( {"{http://ns1}PS1"}) + private interface Interface1 { + int method1(); + + int method2(); + + int method3(); + + int method4(); + } + + private interface Interface2 { + @Requires( {"transaction.global"}) + @PolicySets( {"{http://ns1}PS1"}) + int method1(); + + @Requires( {"transaction.local"}) + @PolicySets( {"{http://ns1}PS2"}) + int method2(); + } + + @Requires( {"transaction.global.Interface6"}) + @PolicySets( {"{http://ns1}PS1"}) + private interface Interface3 { + @Requires( {"transaction.global.Interface6.method1"}) + @PolicySets( {"{http://ns1}PS2"}) + int method1(); + + @Requires( {"transaction.local.Interface6.method2"}) + @PolicySets( {"{http://ns1}PS3"}) + int method2(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/LICENSE b/branches/trunk-20080910/modules/interface-wsdl-xml/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/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/trunk-20080910/modules/interface-wsdl-xml/NOTICE b/branches/trunk-20080910/modules/interface-wsdl-xml/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/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/trunk-20080910/modules/interface-wsdl-xml/pom.xml b/branches/trunk-20080910/modules/interface-wsdl-xml/pom.xml new file mode 100644 index 0000000000..62b224c586 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/pom.xml @@ -0,0 +1,95 @@ +<?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-interface-wsdl-xml</artifactId> + <name>Apache Tuscany SCA WSDL Interface XML Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution-namespace</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution-impl</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly-xml</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-xsd-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-sca</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.interface.wsdl.xml</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef.wsdl.xml*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELExtensionHandler.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELExtensionHandler.java new file mode 100644 index 0000000000..13203d4adc --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELExtensionHandler.java @@ -0,0 +1,140 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.interfacedef.wsdl.xml;
+
+import java.io.PrintWriter;
+
+import javax.wsdl.Definition;
+import javax.wsdl.WSDLException;
+import javax.wsdl.extensions.ExtensibilityElement;
+import javax.wsdl.extensions.ExtensionDeserializer;
+import javax.wsdl.extensions.ExtensionRegistry;
+import javax.wsdl.extensions.ExtensionSerializer;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * A WSDL extension processor for extension elements introduced by BPEL - in particular
+ * the <partnerLinkType.../> elements
+ *
+ * @version $Rev$ $Date$
+ */
+public class BPELExtensionHandler implements ExtensionSerializer, ExtensionDeserializer {
+
+ private final String localName = "partnerLinkType";
+ private final String roleName = "role";
+
+ /**
+ * Marshals the BPEL partner link type extension element to XML
+ * See (@link javax.wsdl.extensions.ExtensionSerializer)
+ */
+ @SuppressWarnings("unchecked")
+ public void marshall(Class parentType, QName elementType, ExtensibilityElement theElement,
+ PrintWriter writer, Definition def, ExtensionRegistry extReg)
+ throws WSDLException {
+ // The format of the Partner Link Type in XML is as follows:
+ // <foo:partnerLinkType name="bar">
+ // <foo:role name="somename" portType="xyz:portTypeName"/>
+ // <foo:role name="othername" portType="xyz:portTypeName2"/>
+ // <foo:partnerLinkType>
+ BPELPartnerLinkTypeExt thePLinkType = (BPELPartnerLinkTypeExt) theElement;
+ QName theType = thePLinkType.getElementType();
+
+ writer.println("<" + theType.toString() +
+ " name=\"" + thePLinkType.getName() + "\">");
+ for( int i = 0; i < 2; i++ ) {
+ if( thePLinkType.getRoleName( i ) != null ) {
+ writer.println( "<" + theType.getPrefix() + ":role"
+ + " name=\"" + thePLinkType.getRoleName(i) + "\" portType=\""
+ + thePLinkType.getRolePortType(i) + "\">");
+ } // end if
+ } // end for
+ writer.println("</" + theType.toString() + ">");
+ } // end marshall
+
+ /**
+ * Unmarshals the BPEL partner link type element from XML
+ * See (@link javax.wsdl.extensions.ExtensionDeserializer)
+ * The format of the Partner Link Type in XML is as follows:
+ * <foo:partnerLinkType name="bar">
+ * <foo:role name="somename" portType="xyz:portTypeName"/>
+ * <foo:role name="othername" portType="xyz:portTypeName2"/>
+ * <foo:partnerLinkType>
+ *
+ * One role is mandatory, the second is optional.
+ */
+ @SuppressWarnings("unchecked")
+ public ExtensibilityElement unmarshall(Class theClass, QName elementType,
+ Element theElement, Definition def, ExtensionRegistry extReg)
+ throws WSDLException {
+
+ // Check that this elementType really is a partnerLinkType element
+ if( !elementType.getLocalPart().equals(localName) ) return null;
+ BPELPartnerLinkTypeExt theExtension = new BPELPartnerLinkTypeExt();
+ theExtension.setElementType(elementType);
+ theExtension.setName( theElement.getAttribute("name") );
+
+ // Fetch the child "role" elements
+ NodeList theRoles = theElement.getElementsByTagNameNS("*", roleName);
+ for ( int i=0; i < theRoles.getLength(); i++ ) {
+ if( i > 1 ) break;
+ Element roleNode = (Element)theRoles.item(i);
+ String roleName = roleNode.getAttribute("name");
+ String portType = roleNode.getAttribute("portType");
+ if (portType == null || portType.length() == 0) {
+ // Fetch the child "portType" element
+ NodeList portTypesNodes = roleNode.getElementsByTagNameNS("*", "portType");
+ for (int p = 0; p < portTypesNodes.getLength(); p++) {
+ Element portTypeNode = (Element)portTypesNodes.item(p);
+ portType = portTypeNode.getAttribute("name");
+ break;
+ }
+ }
+ // The PortType attribute is a QName in prefix:localName format - convert to a QName
+ QName rolePortType = getQNameValue( def, portType );
+ theExtension.setRole( i, roleName, rolePortType );
+ } // end for
+ return theExtension;
+ } // end unmarshall
+
+
+ /**
+ * Returns a QName from a string.
+ * @param definition - a WSDL Definition
+ * @param value - the String from which to form the QName in the form "pref:localName"
+ * @return
+ */
+ protected QName getQNameValue(Definition definition, String value) {
+ if (value != null && definition != null) {
+ int index = value.indexOf(':');
+ String prefix = index == -1 ? "" : value.substring(0, index);
+ String localName = index == -1 ? value : value.substring(index + 1);
+ String ns = definition.getNamespace(prefix);
+ if (ns == null) {
+ ns = "";
+ }
+ return new QName(ns, localName, prefix);
+ } else {
+ return null;
+ }
+ } // end getQNameValue
+
+} // end BPELExtensionHandler
diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELPartnerLinkTypeExt.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELPartnerLinkTypeExt.java new file mode 100644 index 0000000000..67124832f3 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/BPELPartnerLinkTypeExt.java @@ -0,0 +1,79 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.interfacedef.wsdl.xml;
+
+import javax.wsdl.extensions.ExtensibilityElement;
+import javax.xml.namespace.QName;
+
+/**
+ * A class to serve as the extensibility element for BPEL partnerLinkType elements
+ *
+ * @version $Rev$ $Date$
+ */
+public class BPELPartnerLinkTypeExt implements ExtensibilityElement {
+
+ private QName elementType = null;
+ private String linkTypeName = null;
+ private String[] roleNames = new String[2];
+ private QName[] rolePortTypes = new QName[2];
+
+ // -- methods required by the Extensibility Element interface
+ public QName getElementType() {
+ return elementType;
+ }
+
+ public Boolean getRequired() {
+ return true;
+ }
+
+ public void setElementType(QName theName ) {
+ elementType = theName;
+ }
+
+ public void setRequired(Boolean required) {
+ // intentionally left blank
+ }
+
+ // -- other methods
+
+ public void setName( String theName ) {
+ linkTypeName = theName;
+ }
+
+ public String getName() {
+ return linkTypeName;
+ }
+
+ public void setRole( int i, String name, QName portType ) {
+ if( i > 1 ) return;
+ roleNames[i] = name;
+ rolePortTypes[i] = portType;
+ }
+
+ public String getRoleName( int i ) {
+ if( i > 1 ) return null;
+ return roleNames[i];
+ }
+
+ public QName getRolePortType( int i ) {
+ if( i > 1 ) return null;
+ return rolePortTypes[i];
+ }
+
+} // end BPELPartnerLinkTypeExt
diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLConstants.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLConstants.java new file mode 100644 index 0000000000..f9ddda6d98 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLConstants.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.xml.Constants; + +/** + * Constants for WSDL. + * + * @version $Rev$ $Date$ + */ +public interface WSDLConstants { + + String INTERFACE_WSDL = "interface.wsdl"; + QName INTERFACE_WSDL_QNAME = new QName(Constants.SCA10_NS, "interface.wsdl"); + String INTERFACE = "interface"; + String CALLBACK_INTERFACE = "callbackInterface"; + String WSDL_LOCATION = "wsdlLocation"; + String WSDLI_NS = "http://www.w3.org/2004/08/wsdl-instance"; + QName WSDL_LOCATION_QNAME = new QName(WSDLI_NS, WSDL_LOCATION); + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessor.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessor.java new file mode 100644 index 0000000000..6302913c25 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessor.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import javax.wsdl.Definition; +import javax.wsdl.Import; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; +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.XSDefinition; +import org.apache.tuscany.sca.xsd.XSDFactory; + +/** + * An ArtifactProcessor for WSDL documents. + * + * @version $Rev$ $Date$ + */ +public class WSDLDocumentProcessor implements URLArtifactProcessor<WSDLDefinition> { + + public static final QName WSDL11 = new QName("http://schemas.xmlsoap.org/wsdl/", "definitions"); + public static final QName WSDL11_IMPORT = new QName("http://schemas.xmlsoap.org/wsdl/", "import"); + public static final QName XSD = new QName("http://www.w3.org/2001/XMLSchema", "schema"); + + private static final XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + + private WSDLFactory factory; + private XSDFactory xsdFactory; + private Monitor monitor; + + public WSDLDocumentProcessor(ModelFactoryExtensionPoint modelFactories, Monitor monitor) { + this.factory = modelFactories.getFactory(WSDLFactory.class); + this.xsdFactory = modelFactories.getFactory(XSDFactory.class); + this.monitor = monitor; + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-wsdlxml-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + public WSDLDefinition read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException { + try { + WSDLDefinition definition = indexRead(artifactURL); + definition.setURI(artifactURI); + return definition; + } catch (Exception e) { + ContributionReadException ce = new ContributionReadException(e); + error("ContributionReadException", artifactURL, ce); + //throw ce; + return null; + } + } + + public void resolve(WSDLDefinition model, ModelResolver resolver) throws ContributionResolveException { + if (model == null) return; + + Definition definition = model.getDefinition(); + if (definition != null) { + for (Object imports : definition.getImports().values()) { + List importList = (List)imports; + for (Object i : importList) { + Import imp = (Import)i; + if (imp.getDefinition() != null) { + continue; + } + if (imp.getLocationURI() == null) { + // FIXME: [rfeng] By the WSDL 1.1 Specification, the location attribute is required + // We need to resolve it by QName + WSDLDefinition proxy = factory.createWSDLDefinition(); + proxy.setUnresolved(true); + proxy.setNamespace(imp.getNamespaceURI()); + WSDLDefinition resolved = resolver.resolveModel(WSDLDefinition.class, proxy); + if (resolved != null && !resolved.isUnresolved()) { + imp.setDefinition(resolved.getDefinition()); + if (!model.getImportedDefinitions().contains(resolved)) { + model.getImportedDefinitions().add(resolved); + } + } + } else { + String location = imp.getLocationURI(); + URI uri = URI.create(location); + if (uri.isAbsolute()) { + WSDLDefinition resolved; + try { + resolved = read(null, uri, uri.toURL()); + imp.setDefinition(resolved.getDefinition()); + if (!model.getImportedDefinitions().contains(resolved)) { + model.getImportedDefinitions().add(resolved); + } + } catch (Exception e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", resolver, ce); + //throw ce; + } + } else { + if (location.startsWith("/")) { + // This is a relative URI against a contribution + location = location.substring(1); + // TODO: Need to resolve it against the contribution + } else { + // This is a relative URI against the WSDL document + URI baseURI = URI.create(model.getDefinition().getDocumentBaseURI()); + URI locationURI = baseURI.resolve(location); + WSDLDefinition resolved; + try { + resolved = read(null, locationURI, locationURI.toURL()); + imp.setDefinition(resolved.getDefinition()); + if (!model.getImportedDefinitions().contains(resolved)) { + model.getImportedDefinitions().add(resolved); + } + } catch (Exception e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", resolver, ce); + //throw ce; + } + } + } + } + } + } + } + } + + public String getArtifactType() { + return ".wsdl"; + } + + public Class<WSDLDefinition> getModelType() { + return WSDLDefinition.class; + } + + /** + * Read the namespace for the WSDL definition and inline schemas + * + * @param doc + * @return + * @throws IOException + * @throws XMLStreamException + */ + protected WSDLDefinition indexRead(URL doc) throws Exception { + WSDLDefinition wsdlDefinition = factory.createWSDLDefinition(); + wsdlDefinition.setUnresolved(true); + wsdlDefinition.setLocation(doc.toURI()); + + InputStream is = doc.openStream(); + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + int eventType = reader.getEventType(); + int index = 0; + while (true) { + if (eventType == XMLStreamConstants.START_ELEMENT) { + if (WSDL11.equals(reader.getName())) { + String tns = reader.getAttributeValue(null, "targetNamespace"); + wsdlDefinition.setNamespace(tns); + // The definition is marked as resolved but not loaded + wsdlDefinition.setUnresolved(false); + wsdlDefinition.setDefinition(null); + } + if (XSD.equals(reader.getName())) { + String tns = reader.getAttributeValue(null, "targetNamespace"); + XSDefinition xsd = xsdFactory.createXSDefinition(); + xsd.setUnresolved(true); + xsd.setNamespace(tns); + xsd.setLocation(URI.create(doc.toURI() + "#" + index)); + index++; + // The definition is marked as resolved but not loaded + xsd.setUnresolved(false); + xsd.setSchema(null); + wsdlDefinition.getXmlSchemas().add(xsd); + } + } + if (reader.hasNext()) { + eventType = reader.next(); + } else { + break; + } + } + return wsdlDefinition; + } finally { + is.close(); + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLInterfaceProcessor.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLInterfaceProcessor.java new file mode 100644 index 0000000000..e04a4d6743 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLInterfaceProcessor.java @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.builder.impl.ProblemImpl; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +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.WSDLObject; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.Problem; +import org.apache.tuscany.sca.monitor.Problem.Severity; + +/** + * + * @version $Rev$ $Date$ + */ +public class WSDLInterfaceProcessor implements StAXArtifactProcessor<WSDLInterfaceContract>, WSDLConstants { + + private WSDLFactory wsdlFactory; + private Monitor monitor; + + public WSDLInterfaceProcessor(ModelFactoryExtensionPoint modelFactories, Monitor monitor) { + this.wsdlFactory = modelFactories.getFactory(WSDLFactory.class); + this.monitor = monitor; + } + + /** + * Report a warning. + * + * @param problems + * @param message + * @param model + */ + private void warning(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-wsdlxml-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a error. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Object... messageParameters) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-wsdlxml-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters); + monitor.problem(problem); + } + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(String message, Object model, Exception ex) { + if (monitor != null) { + Problem problem = new ProblemImpl(this.getClass().getName(), "interface-wsdlxml-validation-messages", Severity.ERROR, model, message, ex); + monitor.problem(problem); + } + } + + /** + * Create a WSDL interface from a URI. + * @param uri + * @return + * @throws ContributionReadException + */ + private WSDLInterface createWSDLInterface(String uri) throws ContributionReadException { + + WSDLInterface wsdlInterface = null; + + // Read a QName in the form: + // namespace#wsdl.interface(name) + int index = uri.indexOf('#'); + if (index == -1) { + error("InvalidWSDLInterfaceAttr", wsdlFactory, uri); + //throw new ContributionReadException("Invalid WSDL interface attribute: " + uri); + } else { + wsdlInterface = wsdlFactory.createWSDLInterface(); + wsdlInterface.setUnresolved(true); + String namespace = uri.substring(0, index); + String name = uri.substring(index + 1); + name = name.substring("wsdl.interface(".length(), name.length() - 1); + wsdlInterface.setName(new QName(namespace, name)); + } + + return wsdlInterface; + } + + public WSDLInterfaceContract read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + // Read an <interface.wsdl> + WSDLInterfaceContract wsdlInterfaceContract = wsdlFactory.createWSDLInterfaceContract(); + + // Read wsdlLocation + String location = reader.getAttributeValue(WSDLI_NS, WSDL_LOCATION); + wsdlInterfaceContract.setLocation(location); + + String uri = reader.getAttributeValue(null, INTERFACE); + if (uri != null) { + WSDLInterface wsdlInterface = createWSDLInterface(uri); + if (wsdlInterface != null) + wsdlInterfaceContract.setInterface(wsdlInterface); + } + + uri = reader.getAttributeValue(null, CALLBACK_INTERFACE); + if (uri != null) { + WSDLInterface wsdlCallbackInterface = createWSDLInterface(uri); + if (wsdlCallbackInterface != null) + wsdlInterfaceContract.setCallbackInterface(wsdlCallbackInterface); + } + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && INTERFACE_WSDL_QNAME.equals(reader.getName())) { + break; + } + } + return wsdlInterfaceContract; + } + + public void write(WSDLInterfaceContract wsdlInterfaceContract, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + // Write an <interface.wsdl> + writer.writeStartElement(Constants.SCA10_NS, INTERFACE_WSDL); + + // Write interface name + WSDLInterface wsdlInterface = (WSDLInterface)wsdlInterfaceContract.getInterface(); + if (wsdlInterface != null) { + QName qname = wsdlInterface.getName(); + String uri = qname.getNamespaceURI() + "#wsdl.interface(" + qname.getLocalPart() + ")"; + writer.writeAttribute(INTERFACE, uri); + } + + WSDLInterface wsdlCallbackInterface = (WSDLInterface)wsdlInterfaceContract.getCallbackInterface(); + if (wsdlCallbackInterface != null) { + QName qname = wsdlCallbackInterface.getName(); + String uri = qname.getNamespaceURI() + "#wsdl.interface(" + qname.getLocalPart() + ")"; + writer.writeAttribute(CALLBACK_INTERFACE, uri); + } + + // Write location + if (wsdlInterfaceContract.getLocation() != null) { + writer.writeAttribute(WSDLI_NS, WSDL_LOCATION, wsdlInterfaceContract.getLocation()); + } + + writer.writeEndElement(); + } + + private WSDLInterface resolveWSDLInterface(WSDLInterface wsdlInterface, ModelResolver resolver) throws ContributionResolveException { + + if (wsdlInterface != null && wsdlInterface.isUnresolved()) { + + // Resolve the WSDL interface + wsdlInterface = resolver.resolveModel(WSDLInterface.class, wsdlInterface); + if (wsdlInterface.isUnresolved()) { + + // If the WSDL interface has never been resolved yet, do it now + // First, resolve the WSDL definition for the given namespace + WSDLDefinition wsdlDefinition = wsdlFactory.createWSDLDefinition(); + wsdlDefinition.setUnresolved(true); + wsdlDefinition.setNamespace(wsdlInterface.getName().getNamespaceURI()); + WSDLDefinition resolved = resolver.resolveModel(WSDLDefinition.class, wsdlDefinition); + if (!resolved.isUnresolved()) { + wsdlDefinition.setDefinition(resolved.getDefinition()); + wsdlDefinition.setLocation(resolved.getLocation()); + wsdlDefinition.setURI(resolved.getURI()); + wsdlDefinition.getImportedDefinitions().addAll(resolved.getImportedDefinitions()); + wsdlDefinition.getXmlSchemas().addAll(resolved.getXmlSchemas()); + wsdlDefinition.setUnresolved(false); + WSDLObject<PortType> portType = wsdlDefinition.getWSDLObject(PortType.class, wsdlInterface.getName()); + if (portType != null) { + // Introspect the WSDL portType and add the resulting + // WSDLInterface to the resolver + try { + wsdlDefinition.setDefinition(portType.getDefinition()); + wsdlInterface = wsdlFactory.createWSDLInterface(portType.getElement(), wsdlDefinition, resolver); + wsdlInterface.setWsdlDefinition(wsdlDefinition); + resolver.addModel(wsdlInterface); + } catch (InvalidInterfaceException e) { + ContributionResolveException ce = new ContributionResolveException(e); + error("ContributionResolveException", wsdlFactory, ce); + //throw ce; + } + } + else { + warning("WsdlInterfaceDoesNotMatch", wsdlDefinition, wsdlInterface.getName()); + } + } + } + } + return wsdlInterface; + } + + public void resolve(WSDLInterfaceContract wsdlInterfaceContract, ModelResolver resolver) throws ContributionResolveException { + + // Resolve the interface and callback interface + WSDLInterface wsdlInterface = resolveWSDLInterface((WSDLInterface)wsdlInterfaceContract.getInterface(), resolver); + wsdlInterfaceContract.setInterface(wsdlInterface); + + WSDLInterface wsdlCallbackInterface = resolveWSDLInterface((WSDLInterface)wsdlInterfaceContract.getCallbackInterface(), resolver); + wsdlInterfaceContract.setCallbackInterface(wsdlCallbackInterface); + } + + public QName getArtifactType() { + return WSDLConstants.INTERFACE_WSDL_QNAME; + } + + public Class<WSDLInterfaceContract> getModelType() { + return WSDLInterfaceContract.class; + } +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLModelResolver.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLModelResolver.java new file mode 100644 index 0000000000..9c23458743 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLModelResolver.java @@ -0,0 +1,487 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.wsdl.Definition; +import javax.wsdl.Operation; +import javax.wsdl.PortType; +import javax.wsdl.Types; +import javax.wsdl.WSDLException; +import javax.wsdl.extensions.AttributeExtensible; +import javax.wsdl.extensions.ExtensibilityElement; +import javax.wsdl.extensions.ExtensionDeserializer; +import javax.wsdl.extensions.ExtensionRegistry; +import javax.wsdl.extensions.ExtensionSerializer; +import javax.wsdl.extensions.UnknownExtensibilityElement; +import javax.wsdl.extensions.UnknownExtensionDeserializer; +import javax.wsdl.extensions.UnknownExtensionSerializer; +import javax.wsdl.extensions.schema.Schema; +import javax.wsdl.xml.WSDLLocator; +import javax.wsdl.xml.WSDLReader; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.DefaultImport; +import org.apache.tuscany.sca.contribution.Import; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.namespace.NamespaceImport; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionRuntimeException; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory; +import org.apache.tuscany.sca.xsd.XSDFactory; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.apache.tuscany.sca.xsd.xml.XMLDocumentHelper; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * A Model Resolver for WSDL models. + * + * @version $Rev: 557916 $ $Date: 2007-07-20 01:04:40 -0700 (Fri, 20 Jul 2007) $ + */ +public class WSDLModelResolver implements ModelResolver { + //Schema element names + public static final String ELEM_SCHEMA = "schema"; + + //Schema URI + public static final String NS_URI_XSD_1999 = "http://www.w3.org/1999/XMLSchema"; + public static final String NS_URI_XSD_2000 = "http://www.w3.org/2000/10/XMLSchema"; + public static final String NS_URI_XSD_2001 = "http://www.w3.org/2001/XMLSchema"; + + //Schema QNames + public static final QName Q_ELEM_XSD_1999 = new QName(NS_URI_XSD_1999, ELEM_SCHEMA); + public static final QName Q_ELEM_XSD_2000 = new QName(NS_URI_XSD_2000, ELEM_SCHEMA); + public static final QName Q_ELEM_XSD_2001 = new QName(NS_URI_XSD_2001, ELEM_SCHEMA); + public static final List<QName> XSD_QNAME_LIST = + Arrays.asList(new QName[] {Q_ELEM_XSD_1999, Q_ELEM_XSD_2000, Q_ELEM_XSD_2001}); + + // ---- Policy WSDL Attachments + + public static final QName Q_POLICY_ATTRIBUTE_EXTENSION = new QName("http://www.osoa.org/xmlns/sca/1.0", "requires"); + public static final QName Q_POLICY_END_CONVERSATION_ATTRIBUTE_EXTENSION = new QName("http://www.osoa.org/xmlns/sca/1.0", "endsConversation"); + + // ---- Stuff added for BPEL extension elements --- Mike Edwards 01/05/2008 + public static final String ELEM_PLINKTYPE = "partnerLinkType"; + public static final String NS_BPEL_1_1 = "http://schemas.xmlsoap.org/ws/2004/03/partner-link/"; + public static final QName BPEL_PLINKTYPE = new QName( NS_BPEL_1_1, ELEM_PLINKTYPE ); + // ---- end of BPEL extension stuff + + private Contribution contribution; + private Map<String, List<WSDLDefinition>> map = new HashMap<String, List<WSDLDefinition>>(); + + private ExtensionRegistry wsdlExtensionRegistry; + + private WSDLFactory wsdlFactory; + private javax.wsdl.factory.WSDLFactory wsdl4jFactory; + private ContributionFactory contributionFactory; + private XSDFactory xsdFactory; + + public WSDLModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) { + this.contribution = contribution; + + this.wsdlFactory = modelFactories.getFactory(WSDLFactory.class); + this.wsdl4jFactory = modelFactories.getFactory(javax.wsdl.factory.WSDLFactory.class); + this.contributionFactory = modelFactories.getFactory(ContributionFactory.class); + this.xsdFactory = modelFactories.getFactory(XSDFactory.class); + + wsdlExtensionRegistry = this.wsdl4jFactory.newPopulatedExtensionRegistry(); + // REVIEW: [rfeng] Disable the schema extension for WSDL4J to avoid aggressive loading + ExtensionDeserializer deserializer = new UnknownExtensionDeserializer(); + ExtensionSerializer serializer = new UnknownExtensionSerializer(); + for (QName schema : XSD_QNAME_LIST) { + wsdlExtensionRegistry.registerSerializer(Types.class, schema, serializer); + wsdlExtensionRegistry.registerDeserializer(Types.class, schema, deserializer); + } + // ---- Policy WSDL Extensions + try { + wsdlExtensionRegistry.registerExtensionAttributeType(PortType.class, Q_POLICY_ATTRIBUTE_EXTENSION, AttributeExtensible.LIST_OF_QNAMES_TYPE); + wsdlExtensionRegistry.registerExtensionAttributeType(Operation.class, Q_POLICY_END_CONVERSATION_ATTRIBUTE_EXTENSION, AttributeExtensible.STRING_TYPE); + } catch (NoSuchMethodError e) { + // That method does not exist on older WSDL4J levels + } + + // ---- BPEL additions + serializer = new BPELExtensionHandler(); + deserializer = new BPELExtensionHandler(); + wsdlExtensionRegistry.registerSerializer(Definition.class, BPEL_PLINKTYPE, serializer); + wsdlExtensionRegistry.registerDeserializer(Definition.class, BPEL_PLINKTYPE, deserializer); + // ---- end of BPEL additions + } + + /** + * Implementation of a WSDL locator. + */ + private class WSDLLocatorImpl implements WSDLLocator { + private InputStream inputStream; + private URL base; + private String latestImportURI; + + public WSDLLocatorImpl(URL base, InputStream is) { + this.base = base; + this.inputStream = is; + } + + public void close() { + try { + inputStream.close(); + } catch (IOException e) { + // Ignore + } + } + + public InputSource getBaseInputSource() { + try { + return XMLDocumentHelper.getInputSource(base, inputStream); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + public String getBaseURI() { + return base.toString(); + } + + public InputSource getImportInputSource(String parentLocation, String importLocation) { + try { + if (importLocation == null) { + throw new IllegalArgumentException("Required attribute 'location' is missing."); + } + + URL url = null; + if (importLocation.startsWith("/")) { + // The URI is relative to the contribution + String uri = importLocation.substring(1); + + Artifact proxyArtifact = contributionFactory.createArtifact(); + proxyArtifact.setURI(uri); + + //use contribution resolution (this supports import/export) + Artifact importedArtifact = + contribution.getModelResolver().resolveModel(Artifact.class, proxyArtifact); + if (importedArtifact.getLocation() != null) { + //get the artifact URL + url = new URL(importedArtifact.getLocation()); + } + } else { + url = new URL(new URL(parentLocation), importLocation); + } + if (url == null) { + return null; + } + latestImportURI = url.toString(); + return XMLDocumentHelper.getInputSource(url); + } catch (Exception e) { + throw new ContributionRuntimeException(e); + } + } + + public String getLatestImportURI() { + return latestImportURI; + } + + } + + public void addModel(Object resolved) { + WSDLDefinition definition = (WSDLDefinition)resolved; + for (XSDefinition d : definition.getXmlSchemas()) { + if (contribution != null) { + contribution.getModelResolver().addModel(d); + } + } + List<WSDLDefinition> list = map.get(definition.getNamespace()); + if (list == null) { + list = new ArrayList<WSDLDefinition>(); + map.put(definition.getNamespace(), list); + } + list.add(definition); + } + + public Object removeModel(Object resolved) { + WSDLDefinition definition = (WSDLDefinition)resolved; + List<WSDLDefinition> list = map.get(definition.getNamespace()); + if (list == null) { + return null; + } else { + return list.remove(definition); + } + } + + /** + * Create a facade Definition which imports all the definitions + * + * @param definitions A list of the WSDL definitions under the same target namespace + * @return The aggregated WSDL definition + */ + private WSDLDefinition aggregate(List<WSDLDefinition> definitions) { + if (definitions == null || definitions.size() == 0) { + return null; + } + if (definitions.size() == 1) { + WSDLDefinition d = definitions.get(0); + loadOnDemand(d); + return d; + } + WSDLDefinition aggregated = wsdlFactory.createWSDLDefinition(); + for (WSDLDefinition d : definitions) { + loadOnDemand(d); + } + Definition facade = wsdl4jFactory.newDefinition(); + String ns = definitions.get(0).getNamespace(); + facade.setQName(new QName(ns, "$aggregated$")); + facade.setTargetNamespace(ns); + + for (WSDLDefinition d : definitions) { + if (d.getDefinition() != null) { + javax.wsdl.Import imp = facade.createImport(); + imp.setNamespaceURI(d.getNamespace()); + imp.setDefinition(d.getDefinition()); + imp.setLocationURI(d.getDefinition().getDocumentBaseURI()); + facade.addImport(imp); + aggregated.getXmlSchemas().addAll(d.getXmlSchemas()); + aggregated.getImportedDefinitions().add(d); + } + } + aggregated.setDefinition(facade); + definitions.clear(); + definitions.add(aggregated); + return aggregated; + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved) { + + // Lookup a definition for the given namespace + String namespace = ((WSDLDefinition)unresolved).getNamespace(); + if (namespace == null) { + return modelClass.cast(unresolved); + } + List<WSDLDefinition> list = map.get(namespace); + WSDLDefinition resolved = aggregate(list); + if (resolved != null && !resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + + // No definition found, delegate the resolution to the imports + for (Import import_ : this.contribution.getImports()) { + if (import_ instanceof NamespaceImport) { + NamespaceImport namespaceImport = (NamespaceImport)import_; + if (namespaceImport.getNamespace().equals(namespace)) { + + // Delegate the resolution to the namespace import resolver + resolved = + namespaceImport.getModelResolver().resolveModel(WSDLDefinition.class, + (WSDLDefinition)unresolved); + if (!resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + } + } else if (import_ instanceof DefaultImport) { + + // Delegate the resolution to the default import resolver + resolved = + import_.getModelResolver().resolveModel(WSDLDefinition.class, + (WSDLDefinition)unresolved); + if (!resolved.isUnresolved()) { + return modelClass.cast(resolved); + } + } + } + return modelClass.cast(unresolved); + } + + /** + * Load the WSDL definition on demand + * @param def + */ + private void loadOnDemand(WSDLDefinition def) { + if (def.getDefinition() == null && def.getLocation() != null) { + // Load the definition on-demand + try { + loadDefinition(def); + } catch (ContributionReadException e) { + throw new RuntimeException(e); + } + } + } + + // private Map<String, WSDLDefinition> loadedDefinitions = new Hashtable<String, WSDLDefinition>(); + + /** + * Load the WSDL definition and inline schemas + * + * @param wsdlDef + * @throws ContributionReadException + */ + private void loadDefinition(WSDLDefinition wsdlDef) throws ContributionReadException { + if (wsdlDef.getDefinition() != null || wsdlDef.getLocation() == null) { + return; + } + try { + URL artifactURL = wsdlDef.getLocation().toURL(); + // Read a WSDL document + InputStream is = artifactURL.openStream(); + WSDLReader reader = wsdl4jFactory.newWSDLReader(); + reader.setFeature("javax.wsdl.verbose", false); + reader.setFeature("javax.wsdl.importDocuments", true); + // FIXME: We need to decide if we should disable the import processing by WSDL4J + // reader.setFeature("javax.wsdl.importDocuments", false); + reader.setExtensionRegistry(wsdlExtensionRegistry); // use a custom registry + + WSDLLocatorImpl locator = new WSDLLocatorImpl(artifactURL, is); + Definition definition = reader.readWSDL(locator); + wsdlDef.setDefinition(definition); + + // If this definition imports any definitions from other namespaces, + // set the correct WSDLDefinition import relationships. + for (Map.Entry<String, List<javax.wsdl.Import>> entry : + ((Map<String, List<javax.wsdl.Import>>)definition.getImports()).entrySet()) { + if (!entry.getKey().equals(definition.getTargetNamespace())) { + WSDLDefinition wsdlDefinition = wsdlFactory.createWSDLDefinition(); + wsdlDefinition.setUnresolved(true); + wsdlDefinition.setNamespace(entry.getKey()); + WSDLDefinition resolved = resolveModel(WSDLDefinition.class, wsdlDefinition); + if (!resolved.isUnresolved()) { + for (javax.wsdl.Import imp : entry.getValue()) { + if (resolved.getDefinition().getDocumentBaseURI().equals(imp.getDefinition().getDocumentBaseURI())) { + // this WSDLDefinition contains the imported document + wsdlDef.getImportedDefinitions().add(resolved); + } else { + // this is a facade, so look in its imported definitions + for (WSDLDefinition def : resolved.getImportedDefinitions()) { + if (def.getDefinition().getDocumentBaseURI().equals(imp.getDefinition().getDocumentBaseURI())) { + wsdlDef.getImportedDefinitions().add(def); + break; + } + } + } + } + } + } + } + + //Read inline schemas + readInlineSchemas(wsdlDef, definition); + } catch (WSDLException e) { + throw new ContributionReadException(e); + } catch (IOException e) { + throw new ContributionReadException(e); + } + } + + private Document promote(Element element) { + Document doc = (Document)element.getOwnerDocument().cloneNode(false); + Element schema = (Element)doc.importNode(element, true); + doc.appendChild(schema); + Node parent = element.getParentNode(); + while (parent instanceof Element) { + Element root = (Element)parent; + NamedNodeMap nodeMap = root.getAttributes(); + if (nodeMap != null) { + for (int i = 0; i < nodeMap.getLength(); i++) { + Attr attr = (Attr)nodeMap.item(i); + String name = attr.getName(); + if ("xmlns".equals(name) || name.startsWith("xmlns:")) { + if (schema.getAttributeNode(name) == null) { + schema.setAttributeNodeNS((Attr)doc.importNode(attr, true)); + } + } + } + } + parent = parent.getParentNode(); + } + doc.setDocumentURI(element.getOwnerDocument().getDocumentURI()); + return doc; + } + + /** + * Populate the inline schemas including those from the imported definitions + * + * @param definition + * @param schemaCollection + */ + private void readInlineSchemas(WSDLDefinition wsdlDefinition, Definition definition) { + if (contribution == null) { + // Check null for test cases + return; + } + Types types = definition.getTypes(); + if (types != null) { + int index = 0; + for (Object ext : types.getExtensibilityElements()) { + ExtensibilityElement extElement = (ExtensibilityElement)ext; + Element element = null; + if (XSD_QNAME_LIST.contains(extElement.getElementType())) { + if (extElement instanceof Schema) { + element = ((Schema)extElement).getElement(); + } else if (extElement instanceof UnknownExtensibilityElement) { + element = ((UnknownExtensibilityElement)extElement).getElement(); + } + } + if (element != null) { + Document doc = promote(element); + XSDefinition xsDefinition = xsdFactory.createXSDefinition(); + xsDefinition.setUnresolved(true); + xsDefinition.setNamespace(element.getAttribute("targetNamespace")); + xsDefinition.setDocument(doc); + xsDefinition.setLocation(URI.create(doc.getDocumentURI() + "#" + index)); + XSDefinition resolved = + contribution.getModelResolver().resolveModel(XSDefinition.class, xsDefinition); + if (resolved != null && !resolved.isUnresolved()) { + if (!wsdlDefinition.getXmlSchemas().contains(resolved)) { + // Don't add resolved because it may be an aggregate that + // contains more than we need. The resolver will have + // set the specific schema we need into unresolved. + wsdlDefinition.getXmlSchemas().add(xsDefinition); + } + } + index++; + } + } + } + for (Object imports : definition.getImports().values()) { + List impList = (List)imports; + for (Object i : impList) { + javax.wsdl.Import anImport = (javax.wsdl.Import)i; + // Read inline schemas + if (anImport.getDefinition() != null) { + readInlineSchemas(wsdlDefinition, anImport.getDefinition()); + } + } + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..9666a6dbd8 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,19 @@ +# 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. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLInterfaceProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#interface.wsdl,model=org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor new file mode 100644 index 0000000000..553c764233 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor @@ -0,0 +1,19 @@ +# 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. + +# Implementation class for the artifact processor extension +org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLDocumentProcessor;type=.wsdl,model=org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver new file mode 100644 index 0000000000..30d2039e80 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLModelResolver;model=org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/interface-wsdlxml-validation-messages.properties b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/interface-wsdlxml-validation-messages.properties new file mode 100644 index 0000000000..2f8c3e0500 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/main/resources/interface-wsdlxml-validation-messages.properties @@ -0,0 +1,24 @@ +# +# +# 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. +# +# +ContributionReadException = ContributionReadException occured due to : +ContributionResolveException = ContributionResolveException occured due to : +InvalidWSDLInterfaceAttr = Invalid WSDL interface attribute: {0} +WsdlInterfaceDoesNotMatch = The #wsdl.interface({0}) specified does not match with WSDL Definitions
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/AbstractWSDLTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/AbstractWSDLTestCase.java new file mode 100644 index 0000000000..f0228edb1f --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/AbstractWSDLTestCase.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.xsd.XSDFactory; + +/** + * Test case for WSDLOperation. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractWSDLTestCase extends TestCase { + protected URLArtifactProcessor<Object> documentProcessor; + protected ModelResolver resolver; + protected WSDLFactory wsdlFactory; + protected XSDFactory xsdFactory; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + wsdlFactory = modelFactories.getFactory(WSDLFactory.class); + xsdFactory = modelFactories.getFactory(XSDFactory.class); + + ContributionFactory contributionFactory = modelFactories.getFactory(ContributionFactory.class); + Contribution contribution = contributionFactory.createContribution(); + ModelResolverExtensionPoint modelResolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class); + resolver = new ExtensibleModelResolver(contribution, modelResolvers, modelFactories); + contribution.setModelResolver(resolver); + + URLArtifactProcessorExtensionPoint documentProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors, null); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLInterfaceIntrospectorTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLInterfaceIntrospectorTestCase.java new file mode 100644 index 0000000000..dc7e1ced38 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLInterfaceIntrospectorTestCase.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.introspect; + +import java.net.URI; +import java.net.URL; +import java.util.List; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.interfacedef.wsdl.AbstractWSDLTestCase; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; + +/** + * Test case for InterfaceWSDLIntrospectorImpl. + * + * @version $Rev$ $Date$ + */ +public class WSDLInterfaceIntrospectorTestCase extends AbstractWSDLTestCase { + private static final QName PORTTYPE_NAME = new QName("http://example.com/stockquote.wsdl", "StockQuotePortType"); + + private PortType portType; + private WSDLDefinition definition; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + URL url = getClass().getResource("../xml/stockquote.wsdl"); + definition = (WSDLDefinition)documentProcessor.read(null, new URI("stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + } + + @SuppressWarnings("unchecked") + public final void testIntrospectPortType() throws InvalidInterfaceException { + WSDLInterface contract = wsdlFactory.createWSDLInterface(portType, definition, resolver); + Assert.assertEquals(contract.getName().getLocalPart(), "StockQuotePortType"); + List<Operation> operations = contract.getOperations(); + Assert.assertEquals(1, operations.size()); + Operation operation = operations.get(0); + Assert.assertEquals("getLastTradePrice", operation.getName()); + DataType<List<DataType>> inputType = operation.getInputType(); + Assert.assertEquals(1, inputType.getLogical().size()); + DataType<XMLType> returnType = operation.getOutputType(); + Assert.assertNotNull(returnType); + Assert.assertEquals(0, operation.getFaultTypes().size()); + // Assert.assertEquals(1, + // operation.getWrapper().getInputChildElements().size()); + // Assert.assertEquals(1, + // operation.getWrapper().getOutputChildElements().size()); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLOperationIntrospectorTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLOperationIntrospectorTestCase.java new file mode 100644 index 0000000000..c392b92f8a --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLOperationIntrospectorTestCase.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.introspect; + +import java.net.URI; +import java.net.URL; +import java.util.List; + +import javax.wsdl.Operation; +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.interfacedef.wsdl.AbstractWSDLTestCase; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLOperationIntrospectorImpl; + +/** + * Test case for WSDLOperation. + * + * @version $Rev$ $Date$ + */ +public class WSDLOperationIntrospectorTestCase extends AbstractWSDLTestCase { + private static final QName PORTTYPE_NAME = + new QName("http://example.com/stockquote.wsdl", "StockQuotePortType"); + + + @SuppressWarnings("unchecked") + public final void testWrappedOperation() throws Exception { + URL url = getClass().getResource("../xml/stockquote.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, new URI("stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + PortType portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + Operation operation = portType.getOperation("getLastTradePrice", null, null); + + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + + DataType<List<DataType>> inputType = op.getInputType(); + Assert.assertEquals(1, inputType.getLogical().size()); + DataType<XMLType> type = inputType.getLogical().get(0); + Assert.assertEquals(new QName("http://example.com/stockquote.xsd", "getLastTradePrice"), type.getLogical().getElementName()); + + DataType<XMLType> outputType = op.getOutputType(); + Assert.assertEquals(new QName("http://example.com/stockquote.xsd", "getLastTradePriceResponse"), + outputType.getLogical().getElementName()); + Assert.assertTrue(op.isWrapperStyle()); + + DataType<List<DataType>> unwrappedInputType = op.getWrapper().getWrapperInfo().getUnwrappedInputType(); + List<DataType> childTypes = unwrappedInputType.getLogical(); + Assert.assertEquals(1, childTypes.size()); + DataType<XMLType> childType = childTypes.get(0); + Assert.assertEquals(new QName(null, "tickerSymbol"), childType.getLogical().getElementName()); + + childType = op.getWrapper().getWrapperInfo().getUnwrappedOutputType(); + Assert.assertEquals(new QName(null, "price"), childType.getLogical().getElementName()); + } + + public final void testUnwrappedOperation() throws Exception { + URL url = getClass().getResource("../xml/unwrapped-stockquote.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, new URI("unwrapped-stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + PortType portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + + Operation operation = portType.getOperation("getLastTradePrice1", null, null); + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + Assert.assertFalse(op.isWrapperStyle()); + Assert.assertEquals(1, op.getInputType().getLogical().size()); + + operation = portType.getOperation("getLastTradePrice2", null, null); + op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + Assert.assertFalse(op.isWrapperStyle()); + Assert.assertEquals(2, op.getInputType().getLogical().size()); + } + + public final void testInvalidWSDL() throws Exception { + URL url = getClass().getResource("../xml/invalid-stockquote.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, new URI("invalid-stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + PortType portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + + Operation operation = portType.getOperation("getLastTradePrice", null, null); + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + + try { + op.isWrapperStyle(); + fail("InvalidWSDLException should have been thrown"); + } catch (InvalidInterfaceException e) { + // Expected + } + + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLPolicyAnnotatedInterfaceIntrospectorTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLPolicyAnnotatedInterfaceIntrospectorTestCase.java new file mode 100644 index 0000000000..cf379a1b11 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WSDLPolicyAnnotatedInterfaceIntrospectorTestCase.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.introspect; + +import java.net.URI; +import java.net.URL; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.wsdl.AbstractWSDLTestCase; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; +import org.apache.tuscany.sca.policy.Intent; + +/** + * Test case for InterfaceWSDLIntrospectorImpl. + * + * @version $Rev$ $Date$ + */ +public class WSDLPolicyAnnotatedInterfaceIntrospectorTestCase extends AbstractWSDLTestCase { + private static final QName PORTTYPE_NAME = new QName("http://example.com/stockquote.wsdl", "StockQuotePortType"); + private static final QName INTENT = new QName("http://example.com/stockquote.wsdl", "PolicyIntent"); + + private PortType portType; + private WSDLDefinition definition; + + /** + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + URL url = getClass().getResource("/policy/stockquote_policy.wsdl"); + definition = (WSDLDefinition)documentProcessor.read(null, new URI("stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + } + + @SuppressWarnings("unchecked") + public final void testIntrospectPortType() throws InvalidInterfaceException { + WSDLInterface contract = wsdlFactory.createWSDLInterface(portType, definition, resolver); + Assert.assertEquals(contract.getName().getLocalPart(), "StockQuotePortType"); + Assert.assertTrue(contract.isConversational()); + + boolean foundIntent = false; + + for(Intent intent : contract.getRequiredIntents()) { + if(INTENT.equals(intent.getName())) { + foundIntent = true; + } + } + + Assert.assertTrue(foundIntent); + + for(Operation operation : contract.getOperations()) { + if(operation.getName().equals("cancel")) { + Assert.assertEquals(operation.getConversationSequence(), ConversationSequence.CONVERSATION_END); + } + } + + } +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WrapperStyleOperationTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WrapperStyleOperationTestCase.java new file mode 100644 index 0000000000..ff18c65c69 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/introspect/WrapperStyleOperationTestCase.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.introspect; + +import java.net.URI; +import java.net.URL; + +import javax.wsdl.Operation; +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.wsdl.AbstractWSDLTestCase; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLOperationIntrospectorImpl; + +/** + * Test case for WSDLOperation. + * + * @version $Rev$ $Date$ + */ +public class WrapperStyleOperationTestCase extends AbstractWSDLTestCase { + private static final QName PORTTYPE_NAME = new QName("http://example.com/stockquote.wsdl", "StockQuotePortType"); + + public final void testWrappedOperation() throws Exception { + URL url = getClass().getResource("../xml/stockquote.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, new URI("stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + PortType portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + Operation operation = portType.getOperation("getLastTradePrice", null, null); + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + Assert.assertTrue(op.isWrapperStyle()); + Assert.assertEquals(1, op.getWrapper().getInputChildElements().size()); + Assert.assertEquals(1, op.getWrapper().getOutputChildElements().size()); + } + + public final void testUnwrappedOperation() throws Exception { + URL url = getClass().getResource("../xml/unwrapped-stockquote.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, new URI("unwrapped-stockquote.wsdl"), url); + resolver.addModel(definition); + definition = resolver.resolveModel(WSDLDefinition.class, definition); + PortType portType = definition.getDefinition().getPortType(PORTTYPE_NAME); + Operation operation = portType.getOperation("getLastTradePrice1", null, null); + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + Assert.assertFalse(op.isWrapperStyle()); + operation = portType.getOperation("getLastTradePrice2", null, null); + op = new WSDLOperationIntrospectorImpl(xsdFactory, operation, definition, "org.w3c.dom.Node", resolver); + Assert.assertFalse(op.isWrapperStyle()); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/ReadTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/ReadTestCase.java new file mode 100644 index 0000000000..f23b0d2b59 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/ReadTestCase.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; + +/** + * Test reading WSDL interfaces. + * + * @version $Rev$ $Date$ + */ +public class ReadTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private StAXArtifactProcessor<Object> staxProcessor; + private CompositeBuilder compositeBuilder; + + @Override + public void setUp() throws Exception { + DefaultExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + inputFactory = XMLInputFactory.newInstance(); + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(extensionPoints); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, null, null); + + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + SCABindingFactory scaBindingFactory = modelFactories.getFactory(SCABindingFactory.class); + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + InterfaceContractMapper mapper = utilities.getUtility(InterfaceContractMapper.class); + IntentAttachPointTypeFactory attachPointTypeFactory = modelFactories.getFactory(IntentAttachPointTypeFactory.class); + compositeBuilder = new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, attachPointTypeFactory, mapper, null); + } + + public void testReadComponentType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ComponentType componentType = (ComponentType)staxProcessor.read(reader); + assertNotNull(componentType); + } + + public void testReadConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + ConstrainingType constrainingType = (ConstrainingType)staxProcessor.read(reader); + assertNotNull(constrainingType); + } + + public void testReadComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + XMLStreamReader reader = inputFactory.createXMLStreamReader(is); + Composite composite = (Composite)staxProcessor.read(reader); + assertNotNull(composite); + + compositeBuilder.build(composite); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessorTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessorTestCase.java new file mode 100644 index 0000000000..2d3a3a54ff --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLDocumentProcessorTestCase.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.interfacedef.wsdl.xml; + +import java.net.URI; +import java.net.URL; +import java.util.List; + +import javax.wsdl.Import; +import javax.xml.namespace.QName; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.wsdl.AbstractWSDLTestCase; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class WSDLDocumentProcessorTestCase extends AbstractWSDLTestCase { + + /** + * @throws java.lang.Exception + */ + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + } + + /** + * @throws java.lang.Exception + */ + @After + @Override + public void tearDown() throws Exception { + } + + @Test + public void testWSDL() throws Exception { + + URL url = getClass().getResource("/wsdl/helloworld-service.wsdl"); + WSDLDefinition definition = (WSDLDefinition)documentProcessor.read(null, URI.create("wsdl/helloworld-service.wsdl"), url); + + Assert.assertNull(definition.getDefinition()); + Assert.assertEquals("http://helloworld", definition.getNamespace()); + URL url1 = getClass().getResource("/wsdl/helloworld-interface.wsdl"); + WSDLDefinition definition1 = (WSDLDefinition)documentProcessor.read(null, URI.create("wsdl/helloworld-interface.wsdl"), url1); + Assert.assertNull(definition1.getDefinition()); + Assert.assertEquals("http://helloworld", definition1.getNamespace()); + + resolver.addModel(definition); + resolver.addModel(definition1); + resolver.resolveModel(WSDLDefinition.class, definition); + resolver.resolveModel(WSDLDefinition.class, definition1); + WSDLDefinition resolved = resolver.resolveModel(WSDLDefinition.class, definition); + List imports = (List)definition.getDefinition().getImports().get("http://helloworld"); + Assert.assertNotNull(imports); + Assert.assertNotNull(((Import)imports.get(0)).getDefinition()); + Assert.assertNotNull(resolved.getDefinition().getPortType(new QName("http://helloworld", "HelloWorld"))); + Assert.assertNotNull(resolved.getDefinition().getService(new QName("http://helloworld", "HelloWorldService"))); + + assertNotNull(resolved.getXmlSchemaType(new QName("http://greeting", "Name"))); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLTestCase.java new file mode 100644 index 0000000000..c27a1dbd70 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WSDLTestCase.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.net.URI; +import java.net.URL; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; + +/** + * Test reading WSDL interfaces. + * + * @version $Rev$ $Date$ + */ +public class WSDLTestCase extends TestCase { + + private ExtensibleURLArtifactProcessor documentProcessor; + private WSDLModelResolver wsdlResolver; + + @Override + public void setUp() throws Exception { + ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + URLArtifactProcessorExtensionPoint documentProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors, null); + + ModelFactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(ModelFactoryExtensionPoint.class); + wsdlResolver = new WSDLModelResolver(null, modelFactories); + } + + public void testReadWSDLDocument() throws Exception { + URL url = getClass().getResource("example.wsdl"); + WSDLDefinition definition = documentProcessor.read(null, new URI("example.wsdl"), url, WSDLDefinition.class); + assertNotNull(definition); + assertNull(definition.getDefinition()); + assertEquals(definition.getNamespace(), "http://www.example.org"); + } + + public void testReadWSDLImports() throws Exception { + QName aBinding = new QName("http://helloworld", "HelloWorldSoapBinding"); + QName aPortType = new QName("http://helloworld", "HelloWorld"); + + URL url = getClass().getResource("test1.wsdl"); + WSDLDefinition test1Defn = documentProcessor.read(null, new URI("test1.wsdl"), url, WSDLDefinition.class); + assertNotNull(test1Defn); + wsdlResolver.addModel(test1Defn); + test1Defn = wsdlResolver.resolveModel(WSDLDefinition.class, test1Defn); + //binding is a part of test1.wsdl + assertNotNull(test1Defn.getDefinition().getBinding(aBinding)); + //porttype is part of test2.wsdl + assertNotNull(test1Defn.getDefinition().getPortType(aPortType)); + } + + public void testReadSameNamespaceWSDLDocument() throws Exception { + QName aBinding = new QName("http://helloworld", "HelloWorldSoapBinding"); + QName aPortType = new QName("http://helloworld", "HelloWorld"); + + URL url = getClass().getResource("test2.wsdl"); + WSDLDefinition test2Defn = documentProcessor.read(null, new URI("test2.wsdl"), url, WSDLDefinition.class); + assertNotNull(test2Defn); + wsdlResolver.addModel(test2Defn); + test2Defn = wsdlResolver.resolveModel(WSDLDefinition.class, test2Defn); + + //bindings are a part of test1.wsdl so should not be found + assertNull(test2Defn.getDefinition().getBinding(aBinding)); + assertNotNull(test2Defn.getDefinition().getPortType(aPortType)); + + url = getClass().getResource("test1.wsdl"); + WSDLDefinition test1Defn = documentProcessor.read(null, new URI("test1.wsdl"), url, WSDLDefinition.class); + assertNotNull(test1Defn); + wsdlResolver.addModel(test1Defn); + + test1Defn = wsdlResolver.resolveModel(WSDLDefinition.class, test1Defn); + + assertNotNull(test1Defn.getDefinition().getPortType(aPortType)); + assertNotNull(test1Defn.getDefinition().getBinding(aBinding)); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WriteTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WriteTestCase.java new file mode 100644 index 0000000000..6448291f41 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/WriteTestCase.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; + +/** + * Test reading/write WSDL interfaces. + * + * @version $Rev$ $Date$ + */ +public class WriteTestCase extends TestCase { + + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor<Object> staxProcessor; + + @Override + public void setUp() throws Exception { + DefaultExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + inputFactory = XMLInputFactory.newInstance(); + outputFactory = XMLOutputFactory.newInstance(); + StAXArtifactProcessorExtensionPoint staxProcessors = new DefaultStAXArtifactProcessorExtensionPoint(extensionPoints); + staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, null); + } + + public void testReadWriteComponentType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorImpl.componentType"); + ComponentType componentType = (ComponentType)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(componentType); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(componentType, outputFactory.createXMLStreamWriter(bos)); + } + + public void testReadWriteConstrainingType() throws Exception { + InputStream is = getClass().getResourceAsStream("CalculatorComponent.constrainingType"); + ConstrainingType constrainingType = (ConstrainingType)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(constrainingType); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(constrainingType, outputFactory.createXMLStreamWriter(bos)); + } + + public void testReadWriteComposite() throws Exception { + InputStream is = getClass().getResourceAsStream("Calculator.composite"); + Composite composite = (Composite)staxProcessor.read(inputFactory.createXMLStreamReader(is)); + assertNotNull(composite); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + staxProcessor.write(composite, outputFactory.createXMLStreamWriter(bos)); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/XMLDocumentHelperTestCase.java b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/XMLDocumentHelperTestCase.java new file mode 100644 index 0000000000..eb276a1908 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/java/org/apache/tuscany/sca/interfacedef/wsdl/xml/XMLDocumentHelperTestCase.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.xml; + +import java.net.URL; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.xsd.xml.XMLDocumentHelper; + +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class XMLDocumentHelperTestCase { + private URL wsdl; + private URL xsd; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + wsdl = getClass().getResource("/wsdl/helloworld-interface.wsdl"); + } + + @Test + public void testReadTNS() throws Exception { + String tns = XMLDocumentHelper.readTargetNamespace(wsdl, XMLDocumentHelper.WSDL11, true, "targetNamespace"); + Assert.assertEquals("http://helloworld", tns); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/Calculator.composite b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/Calculator.composite new file mode 100644 index 0000000000..875fdf35d2 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/Calculator.composite @@ -0,0 +1,55 @@ +<?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. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:calc="http://sample.calculator" + targetNamespace="http://calc" + xmlns:wsdli="http://www.w3.org/2004/08/wsdl-instance" + name="Calculator"> + + <service name="CalculatorService" promote="CalculatorServiceComponent"> + <interface.wsdl interface="http://sample/calculator#wsdl.interface(Calculator)" + wsdli:wsdlLocation="http://tempuri.org"/> + </service> + + <component name="CalculatorServiceComponent"> + <implementation.java class="calculator.CalculatorServiceImpl"/> + <reference name="addService" target="AddServiceComponent"/> + <reference name="subtractService" target="SubtractServiceComponent"/> + <reference name="multiplyService" target="MultiplyServiceComponent"/> + <reference name="divideService" target="DivideServiceComponent"/> + </component> + + <component name="AddServiceComponent"> + <implementation.java class="calculator.AddServiceImpl"/> + </component> + + <component name="SubtractServiceComponent"> + <implementation.java class="calculator.SubtractServiceImpl"/> + </component> + + <component name="MultiplyServiceComponent"> + <implementation.java class="calculator.MultiplyServiceImpl"/> + </component> + + <component name="DivideServiceComponent"> + <implementation.java class="calculator.DivideServiceImpl"/> + </component> + +</composite> diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorComponent.constrainingType b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorComponent.constrainingType new file mode 100644 index 0000000000..3eb81b61bd --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorComponent.constrainingType @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="ASCII"?> +<!-- + * 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. +--> +<constrainingType xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:calc="http://calc" + targetNamespace="http://calc" + xmlns:wsdli="http://www.w3.org/2004/08/wsdl-instance" + name="CalculatorComponent"> + + <service name="CalculatorService"> + <interface.wsdl interface="http://sample/calculator#wsdl.interface(Calculator)" + wsdli:wsdlLocation="http://tempuri.org"/> + </service> + + <reference name="divideService"> + <interface.wsdl interface="http://sample/calculator#wsdl.interface(Divide)"/> + </reference> + +</constrainingType> +
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorImpl.componentType b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorImpl.componentType new file mode 100644 index 0000000000..aea7046a3d --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/CalculatorImpl.componentType @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="ASCII"?> +<!-- + * 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. +--> +<componentType xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:wsdli="http://www.w3.org/2004/08/wsdl-instance"> + + <service name="CalculatorService"> + <interface.wsdl interface="http://sample/calculator#wsdl.interface(Calculator)" + wsdli:wsdlLocation="http://tempuri.org"/> + </service> + + <reference name="divideService"> + <interface.wsdl interface="http://sample/calculator#wsdl.interface(Divide)"/> + </reference> + +</componentType> +
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/example.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/example.wsdl new file mode 100644 index 0000000000..5e8e5dad0d --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/example.wsdl @@ -0,0 +1,26 @@ +<?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. +--> +<wsdl:definitions targetNamespace="http://www.example.org" + xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" + name="example"> + + <wsdl:portType name="HelloWorld"> + </wsdl:portType> +</wsdl:definitions> diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/invalid-stockquote.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/invalid-stockquote.wsdl new file mode 100644 index 0000000000..ad81fc7867 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/invalid-stockquote.wsdl @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl" + xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd" + xmlns="http://schemas.xmlsoap.org/wsdl/"> + + <types> + <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2001/XMLSchema"> + <element name="getLastTradePrice1"> + <complexType> + <sequence> + <element name="tickerSymbol" type="string" /> + </sequence> + </complexType> + </element> + <element name="getLastTradePriceResponse"> + <complexType> + <sequence> + <element name="price" type="float" /> + </sequence> + </complexType> + </element> + </schema> + </types> + + <message name="GetLastTradePriceInput"> + <part name="body" element="xsd1:getLastTradePrice" /> + </message> + + <message name="GetLastTradePriceOutput"> + <part name="body" element="xsd1:getLastTradePriceResponse" /> + </message> + + <portType name="StockQuotePortType"> + <operation name="getLastTradePrice"> + <input message="tns:GetLastTradePriceInput" /> + <output message="tns:GetLastTradePriceOutput" /> + </operation> + </portType> + +</definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/ipo.xsd b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/ipo.xsd new file mode 100644 index 0000000000..241ec15d36 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/stockquote.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/stockquote.wsdl new file mode 100644 index 0000000000..39cd5547d9 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/stockquote.wsdl @@ -0,0 +1,58 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl" + xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd" + xmlns="http://schemas.xmlsoap.org/wsdl/"> + + <types> + <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2001/XMLSchema"> + <element name="getLastTradePrice"> + <complexType> + <sequence> + <element name="tickerSymbol" type="string" /> + </sequence> + </complexType> + </element> + <element name="getLastTradePriceResponse"> + <complexType> + <sequence> + <element name="price" type="float" /> + </sequence> + </complexType> + </element> + </schema> + </types> + + <message name="GetLastTradePriceInput"> + <part name="body" element="xsd1:getLastTradePrice" /> + </message> + + <message name="GetLastTradePriceOutput"> + <part name="body" element="xsd1:getLastTradePriceResponse" /> + </message> + + <portType name="StockQuotePortType"> + <operation name="getLastTradePrice"> + <input message="tns:GetLastTradePriceInput" /> + <output message="tns:GetLastTradePriceOutput" /> + </operation> + </portType> + +</definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.wsdl new file mode 100644 index 0000000000..8e26f7b4b5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.wsdl @@ -0,0 +1,45 @@ +<?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. +--> +<wsdl:definitions targetNamespace="http://helloworld" xmlns:tns="http://helloworld" + xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="helloworld"> + + <wsdl:import location="test2.wsdl" namespace="http://helloworld"></wsdl:import> + + <wsdl:binding name="HelloWorldSoapBinding" type="tns:HelloWorld"> + <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> + <wsdl:operation name="getGreetings"> + <wsdlsoap:operation soapAction="" /> + <wsdl:input name="getGreetingsRequest"> + <wsdlsoap:body use="literal" /> + </wsdl:input> + <wsdl:output name="getGreetingsResponse"> + <wsdlsoap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + + <wsdl:service name="HelloWorldService"> + <wsdl:port binding="tns:HelloWorldSoapBinding" name="HelloWorldSoapPort"> + <wsdlsoap:address location="http://localhost:8085/sample-helloworldws-1.0-SNAPSHOT/services/HelloWorldWebService" /> + </wsdl:port> + </wsdl:service> + +</wsdl:definitions> diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.xsd b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.xsd new file mode 100644 index 0000000000..c2210f4a94 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test1.xsd @@ -0,0 +1,33 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<schema targetNamespace="http://www.example.com/Customer" xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO" xmlns:tns="http://www.example.com/Customer"> + <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd" /> + + <complexType name="Customer"> + <sequence> + <element name="customerID" type="string"></element> + <element name="name" type="string"></element> + <element name="order" type="ipo:PurchaseOrderType" /> + </sequence> + </complexType> + <element name="customer" type="tns:Customer"></element> + +</schema> + diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test2.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test2.wsdl new file mode 100644 index 0000000000..529b395fd5 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/test2.wsdl @@ -0,0 +1,63 @@ +<?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. +--> +<wsdl:definitions targetNamespace="http://helloworld" xmlns:tns="http://helloworld" + xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="helloworld"> + + <wsdl:types> + <schema elementFormDefault="qualified" targetNamespace="http://helloworld" xmlns="http://www.w3.org/2001/XMLSchema"> + + <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd" /> + + <element name="getGreetings"> + <complexType> + <sequence> + <element name="name" type="xsd:string" /> + </sequence> + </complexType> + </element> + + <element name="getGreetingsResponse"> + <complexType> + <sequence> + <element name="getGreetingsReturn" type="xsd:string" /> + </sequence> + </complexType> + </element> + + </schema> + </wsdl:types> + + <wsdl:message name="getGreetingsRequest"> + <wsdl:part element="tns:getGreetings" name="parameters" /> + </wsdl:message> + + <wsdl:message name="getGreetingsResponse"> + <wsdl:part element="tns:getGreetingsResponse" name="parameters" /> + </wsdl:message> + + <wsdl:portType name="HelloWorld"> + <wsdl:operation name="getGreetings"> + <wsdl:input message="tns:getGreetingsRequest" name="getGreetingsRequest" /> + <wsdl:output message="tns:getGreetingsResponse" name="getGreetingsResponse" /> + </wsdl:operation> + </wsdl:portType> + +</wsdl:definitions> diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/unwrapped-stockquote.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/unwrapped-stockquote.wsdl new file mode 100644 index 0000000000..666a7e4069 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/org/apache/tuscany/sca/interfacedef/wsdl/xml/unwrapped-stockquote.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<definitions name="StockQuote" targetNamespace="http://example.com/stockquote.wsdl" + xmlns:tns="http://example.com/stockquote.wsdl" xmlns:xsd1="http://example.com/stockquote.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns="http://schemas.xmlsoap.org/wsdl/"> + + <types> + <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2001/XMLSchema"> + <element name="getLastTradePrice"> + <complexType> + <sequence> + <element name="tickerSymbol" type="string" /> + </sequence> + </complexType> + </element> + <element name="getLastTradePriceResponse"> + <complexType> + <sequence> + <element name="price" type="float" /> + </sequence> + </complexType> + </element> + </schema> + </types> + + <message name="GetLastTradePriceInput1"> + <part name="body" element="xsd1:getLastTradePrice" /> + </message> + + <message name="GetLastTradePriceOutput1"> + <part name="body" element="xsd1:getLastTradePriceResponse" /> + </message> + + <message name="GetLastTradePriceInput2"> + <part name="body" element="xsd1:getLastTradePrice" /> + <part name="other" type="xsd:string"/> + </message> + + <message name="GetLastTradePriceOutput2"> + <part name="body" element="xsd1:getLastTradePriceResponse" /> + </message> + + <portType name="StockQuotePortType"> + <operation name="getLastTradePrice"> + <input message="tns:GetLastTradePriceInput1" /> + <output message="tns:GetLastTradePriceOutput1" /> + </operation> + <operation name="getLastTradePrice1"> + <input message="tns:GetLastTradePriceInput1" /> + <output message="tns:GetLastTradePriceOutput1" /> + </operation> + <operation name="getLastTradePrice2"> + <input message="tns:GetLastTradePriceInput2" /> + <output message="tns:GetLastTradePriceOutput2" /> + </operation> + </portType> + +</definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/policy/stockquote_policy.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/policy/stockquote_policy.wsdl new file mode 100644 index 0000000000..7cdf801692 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/policy/stockquote_policy.wsdl @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<!-- + * 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. +--> +<definitions name="StockQuote" + targetNamespace="http://example.com/stockquote.wsdl" + xmlns:tns="http://example.com/stockquote.wsdl" + xmlns:xsd="http://example.com/stockquote.xsd" + xmlns:sca="http://www.osoa.org/xmlns/sca/1.0" + xmlns="http://schemas.xmlsoap.org/wsdl/"> + + <types> + <schema targetNamespace="http://example.com/stockquote.xsd" xmlns="http://www.w3.org/2001/XMLSchema"> + <element name="getLastTradePrice"> + <complexType> + <sequence> + <element name="tickerSymbol" type="string" /> + </sequence> + </complexType> + </element> + <element name="getLastTradePriceResponse"> + <complexType> + <sequence> + <element name="price" type="float" /> + </sequence> + </complexType> + </element> + </schema> + </types> + + <message name="GetLastTradePriceInput"> + <part name="body" element="xsd:getLastTradePrice" /> + </message> + + <message name="GetLastTradePriceOutput"> + <part name="body" element="xsd:getLastTradePriceResponse" /> + </message> + + <portType name="StockQuotePortType" sca:requires="sca:conversational tns:PolicyIntent"> + <operation name="getLastTradePrice"> + <input message="tns:GetLastTradePriceInput" /> + <output message="tns:GetLastTradePriceOutput" /> + </operation> + <operation name="cancel" sca:endsConversation="true"/> + </portType> + +</definitions>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-interface.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-interface.wsdl new file mode 100644 index 0000000000..b0b6644e7f --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-interface.wsdl @@ -0,0 +1,67 @@ +<?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.
+-->
+<wsdl:definitions targetNamespace="http://helloworld" xmlns:tns="http://helloworld"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="helloworld">
+
+ <wsdl:types>
+ <schema elementFormDefault="qualified" targetNamespace="http://helloworld"
+ xmlns="http://www.w3.org/2001/XMLSchema" xmlns:g="http://greeting">
+
+ <!--
+ <import namespace="http://greeting" schemaLocation="../xsd/greeting.xsd" />
+ -->
+ <include schemaLocation="../xsd/helloworld.xsd" />
+
+ <element name="getGreetings">
+ <complexType>
+ <sequence>
+ <element name="name" type="g:Name" />
+ </sequence>
+ </complexType>
+ </element>
+
+ <element name="getGreetingsResponse">
+ <complexType>
+ <sequence>
+ <element name="getGreetingsReturn" type="g:Greeting" />
+ </sequence>
+ </complexType>
+ </element>
+
+ </schema>
+ </wsdl:types>
+
+ <wsdl:message name="getGreetingsRequest">
+ <wsdl:part element="tns:getGreetings" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:message name="getGreetingsResponse">
+ <wsdl:part element="tns:getGreetingsResponse" name="parameters" />
+ </wsdl:message>
+
+ <wsdl:portType name="HelloWorld">
+ <wsdl:operation name="getGreetings">
+ <wsdl:input message="tns:getGreetingsRequest" name="getGreetingsRequest" />
+ <wsdl:output message="tns:getGreetingsResponse" name="getGreetingsResponse" />
+ </wsdl:operation>
+ </wsdl:portType>
+
+</wsdl:definitions>
diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-service.wsdl b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-service.wsdl new file mode 100644 index 0000000000..0a7979e308 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/wsdl/helloworld-service.wsdl @@ -0,0 +1,49 @@ +<?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.
+-->
+<wsdl:definitions targetNamespace="http://helloworld" xmlns:tns="http://helloworld"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="helloworld">
+
+ <wsdl:import location="helloworld-interface.wsdl" namespace="http://helloworld"></wsdl:import>
+ <!--
+ <wsdl:import namespace="http://helloworld"></wsdl:import>
+ -->
+
+ <wsdl:binding name="HelloWorldSoapBinding" type="tns:HelloWorld">
+ <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
+ <wsdl:operation name="getGreetings">
+ <wsdlsoap:operation soapAction="" />
+ <wsdl:input name="getGreetingsRequest">
+ <wsdlsoap:body use="literal" />
+ </wsdl:input>
+ <wsdl:output name="getGreetingsResponse">
+ <wsdlsoap:body use="literal" />
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+
+ <wsdl:service name="HelloWorldService">
+ <wsdl:port binding="tns:HelloWorldSoapBinding" name="HelloWorldSoapPort">
+ <wsdlsoap:address
+ location="http://localhost:8085/sample-helloworldws-1.0-SNAPSHOT/services/HelloWorldWebService" />
+ </wsdl:port>
+ </wsdl:service>
+
+</wsdl:definitions>
diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/greeting.xsd b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/greeting.xsd new file mode 100644 index 0000000000..635ca25bfc --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/greeting.xsd @@ -0,0 +1,29 @@ +<?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. +--> +<schema targetNamespace="http://greeting" xmlns="http://www.w3.org/2001/XMLSchema"> + <include schemaLocation="name.xsd" /> + <complexType name="Greeting"> + <sequence> + <element name="message" type="string" /> + <element name="name" type="Name" /> + </sequence> + </complexType> + +</schema>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/helloworld.xsd b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/helloworld.xsd new file mode 100644 index 0000000000..bb0c9bc7b7 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/helloworld.xsd @@ -0,0 +1,22 @@ +<?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. +--> +<schema targetNamespace="http://helloworld" xmlns="http://www.w3.org/2001/XMLSchema"> + <import namespace="http://greeting" schemaLocation="greeting.xsd" /> +</schema>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/name.xsd b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/name.xsd new file mode 100644 index 0000000000..300de931ec --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl-xml/src/test/resources/xsd/name.xsd @@ -0,0 +1,29 @@ +<?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. +--> +<schema targetNamespace="http://greeting" xmlns="http://www.w3.org/2001/XMLSchema"> + + <complexType name="Name"> + <sequence> + <element name="firstName" type="string" /> + <element name="lastName" type="string" /> + </sequence> + </complexType> + +</schema>
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface-wsdl/LICENSE b/branches/trunk-20080910/modules/interface-wsdl/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/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/trunk-20080910/modules/interface-wsdl/NOTICE b/branches/trunk-20080910/modules/interface-wsdl/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/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/trunk-20080910/modules/interface-wsdl/pom.xml b/branches/trunk-20080910/modules/interface-wsdl/pom.xml new file mode 100644 index 0000000000..4d39d9e6f7 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/pom.xml @@ -0,0 +1,103 @@ +<?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-interface-wsdl</artifactId> + <name>Apache Tuscany SCA WSDL Interface Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface</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-contribution</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-policy</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.ws.commons.schema</groupId> + <artifactId>XmlSchema</artifactId> + <version>1.3.2</version> + </dependency> + + <dependency> + <groupId>wsdl4j</groupId> + <artifactId>wsdl4j</artifactId> + <version>1.6.2</version> + </dependency> + </dependencies> + + <repositories> + <!-- Apache repository for Web Services artifacts --> + <repository> + <id>apache.ws.zone</id> + <name>Apache WS Zone Repository</name> + <url>http://ws.zones.apache.org/repository2</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + + + <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.interface.wsdl</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef.wsdl*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/DefaultWSDLFactory.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/DefaultWSDLFactory.java new file mode 100644 index 0000000000..2a5dd07d08 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/DefaultWSDLFactory.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.interfacedef.wsdl.impl.WSDLFactoryImpl; + +/** + * A factory for the WSDL model. + * + * @version $Rev$ $Date$ + */ +public class DefaultWSDLFactory extends WSDLFactoryImpl implements WSDLFactory { + + public DefaultWSDLFactory(ModelFactoryExtensionPoint modelFactories) { + super(modelFactories); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLDefinition.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLDefinition.java new file mode 100644 index 0000000000..039e75f437 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLDefinition.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl; + +import java.net.URI; +import java.util.List; + +import javax.wsdl.Binding; +import javax.wsdl.Definition; +import javax.wsdl.WSDLElement; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaType; + +/** + * Represents a WSDL definition. + * WSDLDefinition + * + * @version $Rev$ $Date$ + */ +public interface WSDLDefinition extends Base { + + /** + * Returns the WSDL definition model, if there are more than one WSDL definition under the + * same namespace, the definition will be a facade which imports all the physical WSDL + * definitions + * + * @return the WSDL definition model + */ + Definition getDefinition(); + + /** + * Sets the WSDL definition model + * @param definition the WSDL definition model + */ + void setDefinition(Definition definition); + + /** + * Returns the namespace of this WSDL definition. + * @return the namespace of this WSDL definition + */ + String getNamespace(); + + /** + * Sets the namespace of this WSDL definition. + * @param namespace the namespace of this WSDL definition + */ + void setNamespace(String namespace); + + /** + * Get a list of inline XML schema definitions + * @return A list of inline XML schema definitions + */ + List<XSDefinition> getXmlSchemas(); + + /** + * Get the location of the WSDL file + * @return The location of the WSDL file + */ + URI getLocation(); + + /** + * Set the location of the WSDL file + * @param url + */ + void setLocation(URI url); + + /** + * Get the contribution artifact URI of the WSDL document + * @return The URI of the WSDL document + */ + URI getURI(); + + /** + * Set the contribution artifact URI of the WSDL document + * @param uri + */ + void setURI(URI uri); + + /** + * Get the WSDL definitions imported by this definition + * @return A list of imported WSDL definitions + */ + List<WSDLDefinition> getImportedDefinitions(); + + /** + * Get an XSD element by QName + * @param name + * @return + */ + XmlSchemaElement getXmlSchemaElement(QName name); + + /** + * Get an XSD type by QName + * @param name + * @return + */ + XmlSchemaType getXmlSchemaType(QName name); + + /** + * Get the WSDL object by type and name + * @param <T> + * @param type javax.wsdl.Service/PortType/Binding/Message.class + * @param name The QName of the object + * @return WSDLObject + */ + <T extends WSDLElement> WSDLObject<T> getWSDLObject(Class<T> type, QName name); + + /** + * Get the generated binding for a WSDLDefinition + * @return the WSDL binding + */ + Binding getBinding(); + + /** + * Set the generated binding for a WSDLDefinition + * @param binding the WSDL binding + */ + void setBinding(Binding binding); +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLFactory.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLFactory.java new file mode 100644 index 0000000000..95985dcc28 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLFactory.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl; + +import javax.wsdl.PortType; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; + +/** + * Factory for the WSDL model. + * + * @version $Rev$ $Date$ + */ +public interface WSDLFactory { + + /** + * Creates a new WSDL interface. + * + * @return a new WSDL interface + */ + WSDLInterface createWSDLInterface(); + + /** + * Creates a new WSDL interface from a WSDL portType. + * + * @param portType the portType to inspect + * @return a WSDLInterface corresponding to the WSDL portType + */ + WSDLInterface createWSDLInterface(PortType portType, WSDLDefinition wsdlDefinition, ModelResolver resolver) throws InvalidInterfaceException; + + /** + * Creates the contents of a WSDL interface from a WSDL portType. + * + * @param portType the portType to inspect + * @return a WSDLInterface corresponding to the WSDL portType + */ + void createWSDLInterface(WSDLInterface wsdlInterface, PortType portType, WSDLDefinition wsdlDefinition, ModelResolver resolver) throws InvalidInterfaceException; + + /** + * Creates a new WSDL definition. + * + * @return a new WSDL definition + */ + WSDLDefinition createWSDLDefinition(); + + /** + * Creates a new WSDL interface contract. + * + * @return + */ + WSDLInterfaceContract createWSDLInterfaceContract(); + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterface.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterface.java new file mode 100644 index 0000000000..c0da060af2 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterface.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Base; +import org.apache.tuscany.sca.interfacedef.Interface; + + +/** + * Represents a WSDL interface. + * + * @version $Rev$ $Date$ + */ +public interface WSDLInterface extends Interface, Base { + + /** + * Returns the name of the WSDL interface. + * + * @return the name of the WSDL interface + */ + QName getName(); + + /** + * Sets the name of the WSDL interface. + * + * @param interfaceName the name of the WSDL interface + */ + void setName(QName interfaceName); + + /** + * Returns the WSDL interface portType. + * + * @return the WSDL interface portType + */ + PortType getPortType(); + + /** + * Sets the WSDL interface portType + * + * @param portType the WSDL interface portType + */ + void setPortType(PortType portType); + + WSDLDefinition getWsdlDefinition(); + + void setWsdlDefinition(WSDLDefinition wsdlDefinition); + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterfaceContract.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterfaceContract.java new file mode 100644 index 0000000000..59db17116b --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLInterfaceContract.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + + +/** + * Represents a WSDL interface contract. + * + * @version $Rev$ $Date$ + */ +public interface WSDLInterfaceContract extends InterfaceContract { + + /** + * Sets the WSDL location. + * @param location the WSDL location + */ + void setLocation(String location); + + /** + * Returns the WSDL location + * @return the WSDL location + */ + String getLocation(); + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLObject.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLObject.java new file mode 100644 index 0000000000..0b707163da --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLObject.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.interfacedef.wsdl; + +import java.io.Serializable; + +import javax.wsdl.Definition; + +/** + * Model for objects in a WSDL definition + * @version $Rev$ $Date$ + */ +public interface WSDLObject<T extends Serializable> { + /** + * Get the owning definition where the element is declared + * @return The owning definition + */ + Definition getDefinition(); + + /** + * Set the owning definition + * @param definition + */ + void setDefinition(Definition definition); + + /** + * Get the WSDL element such as Service, PortType, Binding or Message + * @return The WSDL element + */ + T getElement(); + + /** + * Set the WSDL element + * @param element + */ + void setElement(T element); +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLOperation.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLOperation.java new file mode 100644 index 0000000000..d73cccb714 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/WSDLOperation.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl; + +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * WSDL 1.1 Operation + * @version $Rev$ $Date$ + */ +public interface WSDLOperation extends Operation { + /** + * Get the underlying WSDL operation + * @return + */ + javax.wsdl.Operation getWsdlOperation(); + + /** + * Set the underlying WSDL operation + * @param operation + */ + void setWsdlOperation(javax.wsdl.Operation operation); +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/InvalidWSDLException.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/InvalidWSDLException.java new file mode 100644 index 0000000000..1e7b4faa32 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/InvalidWSDLException.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; + +/** + * An exception to indicate the WSDL definition is invalid + * + * @version $Rev$ $Date$ + */ +public class InvalidWSDLException extends InvalidInterfaceException { + private static final long serialVersionUID = 3742887584293256519L; + + public InvalidWSDLException(String message) { + super(message); + } +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLDefinitionImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLDefinitionImpl.java new file mode 100644 index 0000000000..16e9cf43f3 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLDefinitionImpl.java @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import static org.apache.tuscany.sca.xsd.impl.XSDefinitionImpl.getXmlSchemaObject; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.wsdl.Binding; +import javax.wsdl.Definition; +import javax.wsdl.Import; +import javax.wsdl.Message; +import javax.wsdl.PortType; +import javax.wsdl.Service; +import javax.wsdl.WSDLElement; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLObject; +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.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaType; + +/** + * Represents a WSDL definition. + * + * @version $Rev$ $Date$ + */ +public class WSDLDefinitionImpl implements WSDLDefinition { + + private Definition definition; + private String namespace; + private URI location; + private URI uri; + private List<WSDLDefinition> imported = new ArrayList<WSDLDefinition>(); + private List<XSDefinition> schemas = new ArrayList<XSDefinition>(); + private boolean unresolved; + private Binding binding; + + protected WSDLDefinitionImpl() { + } + + public Definition getDefinition() { + return definition; + } + + public void setDefinition(Definition definition) { + this.definition = definition; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean undefined) { + this.unresolved = undefined; + } + + public String getNamespace() { + if (isUnresolved()) { + return namespace; + } else if (definition != null) { + return definition.getTargetNamespace(); + } else { + return namespace; + } + } + + public void setNamespace(String namespace) { + if (!isUnresolved()) { + throw new IllegalStateException(); + } else { + this.namespace = namespace; + } + } + + /* + @Override + public int hashCode() { + return String.valueOf(getNamespace()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof WSDLDefinition) { + WSDLDefinition def = (WSDLDefinition)obj; + if (getNamespace() != null) { + return getNamespace().equals(def.getNamespace()); + } else { + return def.getNamespace() == null; + } + } else { + return false; + } + } + */ + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getXmlSchemas() + */ + public List<XSDefinition> getXmlSchemas() { + return schemas; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getLocation() + */ + public URI getLocation() { + return location; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#setLocation(java.net.URI) + */ + public void setLocation(URI url) { + this.location = url; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getURI() + */ + public URI getURI() { + return uri; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#setURI(java.net.URI) + */ + public void setURI(URI uri) { + this.uri = uri; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getImportedDefinitions() + */ + public List<WSDLDefinition> getImportedDefinitions() { + return imported; + } + + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((location == null) ? 0 : location.hashCode()); + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + return result; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof WSDLDefinitionImpl)) + return false; + final WSDLDefinitionImpl other = (WSDLDefinitionImpl)obj; + if (location == null) { + if (other.location != null) + return false; + } else if (!location.equals(other.location)) + return false; + if (namespace == null) { + if (other.namespace != null) + return false; + } else if (!namespace.equals(other.namespace)) + return false; + return true; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getXmlSchemaElement(javax.xml.namespace.QName) + */ + public XmlSchemaElement getXmlSchemaElement(QName name) { + XmlSchemaCollection schemaCollection = null; + for (XSDefinition xsd : schemas) { + if (schemaCollection == null && xsd.getSchemaCollection() != null) { + schemaCollection = xsd.getSchemaCollection(); + } + XmlSchema schema = xsd.getSchema(); + XmlSchemaElement element = getXmlSchemaObject(schema, name, XmlSchemaElement.class); + if (element != null) { + return element; + } + } + if (schemaCollection != null) { + return schemaCollection.getElementByQName(name); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition#getXmlSchemaType(javax.xml.namespace.QName) + */ + public XmlSchemaType getXmlSchemaType(QName name) { + XmlSchemaCollection schemaCollection = null; + for (XSDefinition xsd : schemas) { + if (xsd.getSchemaCollection() != null) { + schemaCollection = xsd.getSchemaCollection(); + } + XmlSchema schema = xsd.getSchema(); + XmlSchemaType type = getXmlSchemaObject(schema, name, XmlSchemaType.class); + if (type != null) { + return type; + } + } + if (schemaCollection != null) { + return schemaCollection.getTypeByQName(name); + } + return null; + } + + @SuppressWarnings("unchecked") + private static <T extends WSDLElement> WSDLObject<T> getWSDLObject(Definition definition, Class<T> type, QName name) { + if (definition == null) { + return null; + } + Map<QName, WSDLElement> map = null; + if (type == PortType.class) { + map = definition.getPortTypes(); + } else if (type == Service.class) { + map = definition.getServices(); + } else if (type == Binding.class) { + map = definition.getBindings(); + } else if (type == Message.class) { + map = definition.getMessages(); + } else { + throw new IllegalArgumentException("Invalid type: " + type.getName()); + } + if (map.containsKey(name)) { + return (WSDLObject<T>)new WSDLObjectImpl(definition, map.get(name)); + } else { + for (Object imports : definition.getImports().values()) { + List<Import> importList = (List<Import>)imports; + for (Import i : importList) { + definition = i.getDefinition(); + WSDLObject<T> element = getWSDLObject(definition, type, name); + if (element != null) { + return element; + } + } + } + } + return null; + } + + public <T extends WSDLElement> WSDLObject<T> getWSDLObject(Class<T> type, QName name) { + return getWSDLObject(definition, type, name); + } + + public Binding getBinding() { + return binding; + } + + public void setBinding(Binding binding) { + this.binding = binding; + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLFactoryImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLFactoryImpl.java new file mode 100644 index 0000000000..1f2263e1c9 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLFactoryImpl.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import javax.wsdl.PortType; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +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; + +/** + * A factory for the WSDL model. + * + * @version $Rev$ $Date$ + */ +public abstract class WSDLFactoryImpl implements WSDLFactory { + + private WSDLInterfaceIntrospectorImpl introspector; + + public WSDLFactoryImpl(ModelFactoryExtensionPoint modelFactories) { + introspector = new WSDLInterfaceIntrospectorImpl(modelFactories); + } + + public WSDLInterface createWSDLInterface() { + return new WSDLInterfaceImpl(); + } + + public WSDLInterface createWSDLInterface(PortType portType, + WSDLDefinition wsdlDefinition, + ModelResolver resolver) throws InvalidInterfaceException { + WSDLInterface wsdlInterface = createWSDLInterface(); + introspector.introspectPortType(wsdlInterface, portType, wsdlDefinition, resolver); + return wsdlInterface; + } + + public void createWSDLInterface(WSDLInterface wsdlInterface, + PortType portType, + WSDLDefinition wsdlDefinition, + ModelResolver resolver) throws InvalidInterfaceException { + introspector.introspectPortType(wsdlInterface, portType, wsdlDefinition, resolver); + } + + public WSDLDefinition createWSDLDefinition() { + return new WSDLDefinitionImpl(); + } + + public WSDLInterfaceContract createWSDLInterfaceContract() { + return new WSDLInterfaceContractImpl(); + } + + public WSDLInterfaceIntrospectorImpl getWSDLInterfaceIntrospector() { + return introspector; + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceContractImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceContractImpl.java new file mode 100644 index 0000000000..e10bc0d178 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceContractImpl.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.interfacedef.wsdl.impl; + +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractImpl; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterfaceContract; + +/** + * Represents a WSDL interface contract. + * + * @version $Rev$ $Date$ + */ +public class WSDLInterfaceContractImpl extends InterfaceContractImpl implements WSDLInterfaceContract { + private String location; + + protected WSDLInterfaceContractImpl() { + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + @Override + public WSDLInterfaceContractImpl clone() throws CloneNotSupportedException { + return (WSDLInterfaceContractImpl) super.clone(); + } +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceImpl.java new file mode 100644 index 0000000000..3719bbd79a --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceImpl.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLDefinition; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface; + +/** + * Represents a WSDL interface. + * + * @version $Rev$ $Date$ + */ +public class WSDLInterfaceImpl extends InterfaceImpl implements WSDLInterface { + + private QName name; + private PortType portType; + private WSDLDefinition wsdlDefinition; + + protected WSDLInterfaceImpl() { + setRemotable(true); + } + + public QName getName() { + if (isUnresolved()) { + return name; + } else { + return portType.getQName(); + } + } + + public void setName(QName interfaceName) { + if (!isUnresolved()) { + throw new IllegalStateException(); + } + this.name = interfaceName; + } + + public PortType getPortType() { + return portType; + } + + public void setPortType(PortType portType) { + this.portType = portType; + } + + @Override + public int hashCode() { + return String.valueOf(getName()).hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (obj instanceof WSDLInterface) { + if (getName() != null) { + return getName().equals(((WSDLInterface)obj).getName()); + } else { + return ((WSDLInterface)obj).getName() == null; + } + } else { + return false; + } + } + + public WSDLDefinition getWsdlDefinition() { + return wsdlDefinition; + } + + public void setWsdlDefinition(WSDLDefinition wsdlDefinition) { + this.wsdlDefinition = wsdlDefinition; + } + + @Override + public WSDLInterfaceImpl clone() throws CloneNotSupportedException { + return (WSDLInterfaceImpl) super.clone(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceIntrospectorImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceIntrospectorImpl.java new file mode 100644 index 0000000000..18fce72f90 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLInterfaceIntrospectorImpl.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Vector; + +import javax.wsdl.PortType; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +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.policy.Intent; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.xsd.XSDFactory; + +/** + * Introspector for creating WSDLInterface definitions from WSDL PortTypes. + * + * @version $Rev$ $Date$ + */ +public class WSDLInterfaceIntrospectorImpl { + private static final QName POLICY_REQUIRES = new QName("http://www.osoa.org/xmlns/sca/1.0", "requires"); + private static final QName POLICY_CONVERSATIONAL = new QName("http://www.osoa.org/xmlns/sca/1.0", "conversational"); + public static final QName POLICY_END_CONVERSATION = new QName("http://www.osoa.org/xmlns/sca/1.0", "endsConversation"); + + private XSDFactory xsdFactory; + private PolicyFactory policyFactory; + + public WSDLInterfaceIntrospectorImpl(ModelFactoryExtensionPoint modelFactories) { + this.xsdFactory = modelFactories.getFactory(XSDFactory.class);; + this.policyFactory = modelFactories.getFactory(PolicyFactory.class);; + } + + // FIXME: Do we want to deal with document-literal wrapped style based on the JAX-WS Specification? + private List<Operation> introspectOperations(PortType portType, WSDLDefinition wsdlDefinition, ModelResolver resolver) throws InvalidWSDLException { + List<Operation> operations = new ArrayList<Operation>(); + for (Object o : portType.getOperations()) { + javax.wsdl.Operation wsdlOp = (javax.wsdl.Operation)o; + Operation operation = getOperation(wsdlOp, wsdlDefinition, resolver, xsdFactory); + if(isEndConversation(wsdlOp)) { + operation.setConversationSequence(ConversationSequence.CONVERSATION_END); + } + operations.add(operation); + } + return operations; + } + + public void introspectPortType(WSDLInterface wsdlInterface, PortType portType, WSDLDefinition wsdlDefinition, ModelResolver resolver) throws InvalidWSDLException { + processIntents(wsdlInterface, portType); + wsdlInterface.setPortType(portType); + wsdlInterface.getOperations().addAll(introspectOperations(portType, wsdlDefinition, resolver)); + wsdlInterface.setConversational(isConversational(portType)); + } + + public static Operation getOperation(javax.wsdl.Operation wsdlOp, + WSDLDefinition wsdlDefinition, + ModelResolver resolver, + XSDFactory xsdFactory) throws InvalidWSDLException { + WSDLOperationIntrospectorImpl op = new WSDLOperationIntrospectorImpl(xsdFactory, wsdlOp, wsdlDefinition, null, resolver); + return op.getOperation(); + } + + private void processIntents(WSDLInterface wsdlInterface, PortType portType) { + Object o; + try { + o = portType.getExtensionAttribute(POLICY_REQUIRES); + } catch (NoSuchMethodError e) { + // That method does not exist on older WSDL4J levels + o = null; + } + if(o != null && o instanceof Vector) { + Vector<QName> policyAttributes = (Vector<QName>) o; + + Enumeration<QName> policyItents = policyAttributes.elements(); + while(policyItents.hasMoreElements()) { + QName intentName = policyItents.nextElement(); + + //ignores conversational, as it will have it's own + //attribute in the wsdl interface model + if(! intentName.equals(POLICY_CONVERSATIONAL)) { + //process the intent + System.out.println(">>> Intent : " + intentName); + + // Add each intent to the list + Intent intent = policyFactory.createIntent(); + intent.setName(intentName); + + wsdlInterface.getRequiredIntents().add(intent); + } + } + + } + } + + private boolean isConversational(PortType portType) { + boolean conversational = false; + + Object o; + try { + o = portType.getExtensionAttribute(POLICY_REQUIRES); + } catch (NoSuchMethodError e) { + // That method does not exist on older WSDL4J levels + o =null; + } + if(o != null && o instanceof Vector) { + Vector<QName> policyAttributes = (Vector<QName>) o; + + if(policyAttributes.contains(POLICY_CONVERSATIONAL)) { + return true; + } + + } + + return conversational; + } + + private boolean isEndConversation(javax.wsdl.Operation operation) { + boolean endConversation = false; + + Object o; + try { + o = operation.getExtensionAttribute(POLICY_END_CONVERSATION); + } catch (NoSuchMethodError e) { + // That method does not exist on older WSDL4J levels + o = null; + } + if(o != null && o instanceof String) { + endConversation = Boolean.valueOf((String)o); + } + + return endConversation; + + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLObjectImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLObjectImpl.java new file mode 100644 index 0000000000..f18eaef27b --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLObjectImpl.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import java.io.Serializable; + +import javax.wsdl.Definition; + +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLObject; + +/** + * @version $Rev$ $Date$ + */ +public class WSDLObjectImpl<T extends Serializable> implements WSDLObject<T> { + private Definition definition; + private T element; + + public WSDLObjectImpl() { + super(); + } + + public WSDLObjectImpl(Definition definition, T element) { + super(); + this.definition = definition; + this.element = element; + } + + public Definition getDefinition() { + return definition; + } + + public void setDefinition(Definition definition) { + this.definition = definition; + } + + public T getElement() { + return element; + } + + public void setElement(T element) { + this.element = element; + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationImpl.java new file mode 100644 index 0000000000..317b9cce81 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationImpl.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import javax.wsdl.Operation; + +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.interfacedef.wsdl.WSDLOperation; + +/** + * @version $Rev$ $Date$ + */ +public class WSDLOperationImpl extends OperationImpl implements WSDLOperation { + private Operation operation; + + public WSDLOperationImpl() { + super(); + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLOperation#getWsdlOperation() + */ + public Operation getWsdlOperation() { + return operation; + } + + /** + * @see org.apache.tuscany.sca.interfacedef.wsdl.WSDLOperation#setWsdlOperation(javax.wsdl.Operation) + */ + public void setWsdlOperation(Operation operation) { + this.operation = operation; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((operation == null) ? 0 : operation.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + final WSDLOperationImpl other = (WSDLOperationImpl)obj; + if (operation == null) { + if (other.operation != null) + return false; + } else if (!operation.equals(other.operation)) + return false; + return true; + } + + @Override + public String toString() { + return operation == null ? null : operation.toString(); + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationIntrospectorImpl.java b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationIntrospectorImpl.java new file mode 100644 index 0000000000..ab6467bfd7 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/java/org/apache/tuscany/sca/interfacedef/wsdl/impl/WSDLOperationIntrospectorImpl.java @@ -0,0 +1,602 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.wsdl.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.wsdl.Fault; +import javax.wsdl.Input; +import javax.wsdl.Message; +import javax.wsdl.Output; +import javax.wsdl.Part; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.FaultException; +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.WSDLOperation; +import org.apache.tuscany.sca.xsd.XSDefinition; +import org.apache.tuscany.sca.xsd.XSDFactory; + +import org.apache.ws.commons.schema.XmlSchemaComplexType; +import org.apache.ws.commons.schema.XmlSchemaElement; +import org.apache.ws.commons.schema.XmlSchemaObject; +import org.apache.ws.commons.schema.XmlSchemaObjectCollection; +import org.apache.ws.commons.schema.XmlSchemaParticle; +import org.apache.ws.commons.schema.XmlSchemaSequence; +import org.apache.ws.commons.schema.XmlSchemaSimpleType; +import org.apache.ws.commons.schema.XmlSchemaType; + +/** + * Metadata for a WSDL operation + * + * @version $Rev$ $Date$ + */ +public class WSDLOperationIntrospectorImpl { + private static final Logger logger = Logger.getLogger(WSDLOperationIntrospectorImpl.class.getName()); + private static final QName ANY = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "any"); + + private XSDFactory xsdFactory; + private ModelResolver resolver; + private WSDLDefinition wsdlDefinition; + private javax.wsdl.Operation operation; + private WSDLOperation operationModel; + private DataType<List<DataType>> inputType; + private DataType outputType; + private List<DataType> faultTypes; + private String dataBinding; + + /** + * @param wsdlFactory The WSDLFactory to use + * @param operation The WSDL4J operation + * @param wsdlDefinition The WSDL Definition + * @param dataBinding The default databinding + * @param resolver The ModelResolver to use + */ + public WSDLOperationIntrospectorImpl(XSDFactory xsdFactory, + javax.wsdl.Operation operation, + WSDLDefinition wsdlDefinition, + String dataBinding, + ModelResolver resolver) { + super(); + this.xsdFactory = xsdFactory; + this.operation = operation; + this.wsdlDefinition = wsdlDefinition; + this.resolver = resolver; + this.dataBinding = dataBinding; + this.wrapper = new Wrapper(); + } + + private Wrapper wrapper; + + private Boolean wrapperStyle; + + /** + * Test if the operation qualifies wrapper style as defined by the JAX-WS + * 2.0 Specification + * + * @return true if the operation qualifies wrapper style, otherwise false + */ + public boolean isWrapperStyle() throws InvalidWSDLException { + if (wrapperStyle == null) { + wrapperStyle = + (operation.getInput() == null || operation.getInput().getMessage() == null + || operation.getInput().getMessage().getParts().size() == 0 || wrapper.getInputChildElements() != null) && (operation + .getOutput() == null || operation.getOutput().getMessage() == null + || operation.getOutput().getMessage().getParts().size() == 0 || wrapper.getOutputChildElements() != null); + } + return wrapperStyle; + } + + public Wrapper getWrapper() throws InvalidWSDLException { + if (!isWrapperStyle()) { + throw new IllegalStateException("The operation is not wrapper style."); + } else { + return wrapper; + } + } + + /** + * @return + * @throws InvalidServiceContractException + */ + public DataType<List<DataType>> getInputType() throws InvalidWSDLException { + if (inputType == null) { + Input input = operation.getInput(); + Message message = (input == null) ? null : input.getMessage(); + inputType = getMessageType(message); + inputType.setDataBinding("idl:input"); + } + return inputType; + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + @SuppressWarnings("unchecked") + public DataType<XMLType> getOutputType() throws InvalidWSDLException { + if (outputType == null) { + Output output = operation.getOutput(); + Message outputMsg = (output == null) ? null : output.getMessage(); + + List outputParts = (outputMsg == null) ? null : outputMsg.getOrderedParts(null); + if (outputParts != null && outputParts.size() > 0) { + if (outputParts.size() > 1) { + // We don't support output with multiple parts + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Multi-part output is not supported, please use BARE parameter style."); + } + // throw new InvalidWSDLException("Multi-part output is not supported"); + } + Part part = (Part)outputParts.get(0); + outputType = new WSDLPart(part, Object.class).getDataType(); + // outputType.setMetadata(WSDLOperation.class.getName(), this); + } + } + return outputType; + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + public List<DataType> getFaultTypes() throws InvalidWSDLException { + if (faultTypes == null) { + Collection faults = operation.getFaults().values(); + faultTypes = new ArrayList<DataType>(); + for (Object f : faults) { + Fault fault = (Fault)f; + Message faultMsg = fault.getMessage(); + List faultParts = faultMsg.getOrderedParts(null); + if (faultParts.size() != 1) { + throw new InvalidWSDLException("The fault message MUST have a single part"); + } + Part part = (Part)faultParts.get(0); + WSDLPart wsdlPart = new WSDLPart(part, Object.class); + faultTypes.add(new DataTypeImpl<DataType>(FaultException.class, wsdlPart.getDataType())); + } + } + return faultTypes; + } + + private DataType<List<DataType>> getMessageType(Message message) throws InvalidWSDLException { + List<DataType> partTypes = new ArrayList<DataType>(); + if (message != null) { + Collection parts = message.getOrderedParts(null); + for (Object p : parts) { + WSDLPart part = new WSDLPart((Part)p, Object.class); + DataType<XMLType> partType = part.getDataType(); + partTypes.add(partType); + } + } + return new DataTypeImpl<List<DataType>>(dataBinding, Object[].class, partTypes); + } + + /** + * @return + * @throws NotSupportedWSDLException + */ + public Operation getOperation() throws InvalidWSDLException { + if (operationModel == null) { + boolean oneway = (operation.getOutput() == null); + operationModel = new WSDLOperationImpl(); + operationModel.setWsdlOperation(operation); + operationModel.setName(operation.getName()); + operationModel.setFaultTypes(getFaultTypes()); + operationModel.setNonBlocking(oneway); + operationModel.setConversationSequence(ConversationSequence.CONVERSATION_NONE); + operationModel.setInputType(getInputType()); + operationModel.setOutputType(getOutputType()); + + operationModel.setWrapperStyle(isWrapperStyle()); + if (isWrapperStyle()) { + WrapperInfo wrapperInfo = getWrapper().getWrapperInfo(); + operationModel.setWrapper(wrapperInfo); + } + } + return operationModel; + } + + private XmlSchemaElement getElement(QName elementName) { + + XmlSchemaElement element = wsdlDefinition.getXmlSchemaElement(elementName); + if (element == null) { + XSDefinition definition = xsdFactory.createXSDefinition(); + definition.setUnresolved(true); + definition.setNamespace(elementName.getNamespaceURI()); + definition = resolver.resolveModel(XSDefinition.class, definition); + if (definition.getSchema() != null) { + element = definition.getSchema().getElementByName(elementName); + } + } + return element; + } + + private XmlSchemaType getType(QName typeName) { + XmlSchemaType type = wsdlDefinition.getXmlSchemaType(typeName); + if (type == null) { + XSDefinition definition = xsdFactory.createXSDefinition(); + definition.setUnresolved(true); + definition.setNamespace(typeName.getNamespaceURI()); + definition = resolver.resolveModel(XSDefinition.class, definition); + if (definition.getSchema() != null) { + type = definition.getSchema().getTypeByName(typeName); + } + } + return type; + } + + /** + * Metadata for a WSDL part + */ + public class WSDLPart { + private Part part; + + private XmlSchemaElement element; + + private DataType dataType; + + public WSDLPart(Part part, Class javaType) throws InvalidWSDLException { + this.part = part; + QName elementName = part.getElementName(); + if (elementName != null) { + element = WSDLOperationIntrospectorImpl.this.getElement(elementName); + if (element == null) { + throw new InvalidWSDLException("Element cannot be resolved: " + elementName.toString()); + } + } else { + // Create an faked XSD element to host the metadata + element = new XmlSchemaElement(); + element.setName(part.getName()); + element.setQName(new QName(null, part.getName())); + QName typeName = part.getTypeName(); + if (typeName != null) { + XmlSchemaType type = WSDLOperationIntrospectorImpl.this.getType(typeName); + if (type == null) { + throw new InvalidWSDLException("Type cannot be resolved: " + typeName.toString()); + } + element.setSchemaType(type); + element.setSchemaTypeName(type.getQName()); + } + } + XMLType xmlType = new XMLType(getElementInfo(element)); + xmlType.setNillable(element.isNillable()); + xmlType.setMany(element.getMaxOccurs() > 1); + dataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType); + } + + /** + * @return the element + */ + public XmlSchemaElement getElement() { + return element; + } + + /** + * @return the part + */ + public Part getPart() { + return part; + } + + /** + * @return the dataType + */ + public DataType<XMLType> getDataType() { + return dataType; + } + } + + /** + * The "Wrapper Style" WSDL operation is defined by The Java API for + * XML-Based Web Services (JAX-WS) 2.0 specification, section 2.3.1.2 + * Wrapper Style. <p/> A WSDL operation qualifies for wrapper style mapping + * only if the following criteria are met: + * <ul> + * <li>(i) The operation�s input and output messages (if present) each + * contain only a single part + * <li>(ii) The input message part refers to a global element declaration + * whose localname is equal to the operation name + * <li>(iii) The output message part refers to a global element declaration + * <li>(iv) The elements referred to by the input and output message parts + * (henceforth referred to as wrapper elements) are both complex types + * defined using the xsd:sequence compositor + * <li>(v) The wrapper elements only contain child elements, they must not + * contain other structures such as wildcards (element or attribute), + * xsd:choice, substitution groups (element references are not permitted) or + * attributes; furthermore, they must not be nillable. + * </ul> + */ + public class Wrapper { + private XmlSchemaElement inputWrapperElement; + + private XmlSchemaElement outputWrapperElement; + + private List<XmlSchemaElement> inputElements; + + private List<XmlSchemaElement> outputElements; + + // private DataType<List<DataType<XMLType>>> unwrappedInputType; + // + // private DataType<XMLType> unwrappedOutputType; + + private transient WrapperInfo wrapperInfo; + + private List<XmlSchemaElement> getChildElements(XmlSchemaElement element) throws InvalidWSDLException { + if (element == null) { + return null; + } + if (element.isNillable()) { + // Wrapper element cannot be nillable + return null; + } + XmlSchemaType type = element.getSchemaType(); + if (type == null) { + String qName = element.getQName().toString(); + throw new InvalidWSDLException("The XML schema element does not have a type: " + qName); + } + if (!(type instanceof XmlSchemaComplexType)) { + // Has to be a complexType + return null; + } + XmlSchemaComplexType complexType = (XmlSchemaComplexType)type; + if (complexType.getAttributes().getCount() != 0 || complexType.getAnyAttribute() != null) { + // No attributes + return null; + } + XmlSchemaParticle particle = complexType.getParticle(); + if (particle == null) { + // No particle + return Collections.emptyList(); + } + if (!(particle instanceof XmlSchemaSequence)) { + return null; + } + XmlSchemaSequence sequence = (XmlSchemaSequence)complexType.getParticle(); + XmlSchemaObjectCollection items = sequence.getItems(); + List<XmlSchemaElement> childElements = new ArrayList<XmlSchemaElement>(); + for (int i = 0; i < items.getCount(); i++) { + XmlSchemaObject schemaObject = items.getItem(i); + if (!(schemaObject instanceof XmlSchemaElement)) { + // Should contain elements only + return null; + } + XmlSchemaElement childElement = (XmlSchemaElement)schemaObject; + /* + if (childElement.getSubstitutionGroup() != null) { + return null; + } + */ + if (childElement.getName() == null || childElement.getRefName() != null) { + XmlSchemaElement ref = getElement(childElement.getRefName()); + if (ref == null) { + throw new InvalidWSDLException("XML schema element ref cannot be resolved: " + childElement); + } + childElement = ref; + } + if (ANY.equals(childElement.getQName())) { + // Wildcard is not allowed + return null; + } + // TODO: Do we support maxOccurs >1 ? + if (childElement.getMaxOccurs() > 1) { + // TODO: [rfeng] To be implemented + /* + if(logger.isLoggable(Level.WARNING)) { + logger.warning("Support for elements with maxOccurs>1 is not implemented."); + } + */ + // return null; + } + childElements.add(childElement); + } + return childElements; + } + + /** + * Return a list of child XSD elements under the wrapped request element + * + * @return a list of child XSD elements or null if if the request + * element is not wrapped + */ + public List<XmlSchemaElement> getInputChildElements() throws InvalidWSDLException { + if (inputElements != null) { + return inputElements; + } + Input input = operation.getInput(); + if (input != null) { + Message inputMsg = input.getMessage(); + Collection parts = inputMsg.getParts().values(); + if (parts.size() != 1) { + return null; + } + Part part = (Part)parts.iterator().next(); + QName elementName = part.getElementName(); + if (elementName == null) { + return null; + } + if (!operation.getName().equals(elementName.getLocalPart())) { + return null; + } + inputWrapperElement = getElement(elementName); + if (inputWrapperElement == null) { + throw new InvalidWSDLException("The element is not declared in a XML schema: " + elementName + .toString()); + } + if (inputWrapperElement.isNillable()) { + // The wrapper element cannot be nilable + return null; + } + inputElements = getChildElements(inputWrapperElement); + return inputElements; + } else { + return null; + } + } + + /** + * Return a list of child XSD elements under the wrapped response + * element + * + * @return a list of child XSD elements or null if if the response + * element is not wrapped + */ + public List<XmlSchemaElement> getOutputChildElements() throws InvalidWSDLException { + if (outputElements != null) { + return outputElements; + } + Output output = operation.getOutput(); + if (output != null) { + Message outputMsg = output.getMessage(); + Collection parts = outputMsg.getParts().values(); + if (parts.size() != 1) { + return null; + } + Part part = (Part)parts.iterator().next(); + QName elementName = part.getElementName(); + if (elementName == null) { + throw new InvalidWSDLException("The element is not declared in the XML schema: " + part.getName()); + } + outputWrapperElement = WSDLOperationIntrospectorImpl.this.getElement(elementName); + if (outputWrapperElement == null) { + return null; + } + if (outputWrapperElement.isNillable()) { + // The wrapper element cannot be nilable + return null; + } + outputElements = getChildElements(outputWrapperElement); + // FIXME: Do we support multiple child elements for the response? + return outputElements; + } else { + return null; + } + } + + /** + * @return the inputWrapperElement + */ + public XmlSchemaElement getInputWrapperElement() { + return inputWrapperElement; + } + + /** + * @return the outputWrapperElement + */ + public XmlSchemaElement getOutputWrapperElement() { + return outputWrapperElement; + } + + /* + public DataType<List<DataType<XMLType>>> getUnwrappedInputType() throws InvalidWSDLException { + if (unwrappedInputType == null) { + List<DataType<XMLType>> childTypes = new ArrayList<DataType<XMLType>>(); + for (XmlSchemaElement element : getInputChildElements()) { + DataType<XMLType> type = + new DataType<XMLType>(dataBinding, Object.class, new XMLType(getElementInfo(element))); + // type.setMetadata(ElementInfo.class.getName(), getElementInfo(element)); + childTypes.add(type); + } + unwrappedInputType = + new DataType<List<DataType<XMLType>>>("idl:unwrapped.input", Object[].class, childTypes); + } + return unwrappedInputType; + } + + public DataType<XMLType> getUnwrappedOutputType() throws InvalidServiceContractException { + if (unwrappedOutputType == null) { + List<XmlSchemaElement> elements = getOutputChildElements(); + if (elements != null && elements.size() > 0) { + if (elements.size() > 1) { + // We don't support output with multiple parts + throw new NotSupportedWSDLException("Multi-part output is not supported"); + } + XmlSchemaElement element = elements.get(0); + unwrappedOutputType = + new DataType<XMLType>(dataBinding, Object.class, new XMLType(getElementInfo(element))); + // unwrappedOutputType.setMetadata(ElementInfo.class.getName(), getElementInfo(element)); + } + } + return unwrappedOutputType; + } + */ + + public WrapperInfo getWrapperInfo() throws InvalidWSDLException { + if (wrapperInfo == null) { + ElementInfo in = getElementInfo(getInputWrapperElement()); + ElementInfo out = getElementInfo(getOutputWrapperElement()); + List<ElementInfo> inChildren = new ArrayList<ElementInfo>(); + if (in != null) { + for (XmlSchemaElement e : getInputChildElements()) { + inChildren.add(getElementInfo(e)); + } + } + List<ElementInfo> outChildren = new ArrayList<ElementInfo>(); + if (out != null) { + for (XmlSchemaElement e : getOutputChildElements()) { + outChildren.add(getElementInfo(e)); + } + } + wrapperInfo = new WrapperInfo(dataBinding, in, out, inChildren, outChildren); + } + return wrapperInfo; + } + } + + private static ElementInfo getElementInfo(XmlSchemaElement element) { + if (element == null) { + return null; + } + ElementInfo elementInfo = new ElementInfo(element.getQName(), getTypeInfo(element.getSchemaType())); + elementInfo.setMany(element.getMaxOccurs() > 1); + elementInfo.setNillable(element.isNillable()); + return elementInfo; + } + + private static TypeInfo getTypeInfo(XmlSchemaType type) { + if (type == null) { + return null; + } + XmlSchemaType baseType = (XmlSchemaType)type.getBaseSchemaType(); + QName name = type.getQName(); + boolean simple = (type instanceof XmlSchemaSimpleType); + if (baseType == null) { + return new TypeInfo(name, simple, null); + } else { + return new TypeInfo(name, simple, getTypeInfo(baseType)); + } + } + +} diff --git a/branches/trunk-20080910/modules/interface-wsdl/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory b/branches/trunk-20080910/modules/interface-wsdl/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory new file mode 100644 index 0000000000..c11d22d7b2 --- /dev/null +++ b/branches/trunk-20080910/modules/interface-wsdl/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.wsdl.WSDLFactory @@ -0,0 +1,18 @@ +# 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. + +org.apache.tuscany.sca.interfacedef.wsdl.DefaultWSDLFactory
\ No newline at end of file diff --git a/branches/trunk-20080910/modules/interface/LICENSE b/branches/trunk-20080910/modules/interface/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/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/trunk-20080910/modules/interface/NOTICE b/branches/trunk-20080910/modules/interface/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/trunk-20080910/modules/interface/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/trunk-20080910/modules/interface/pom.xml b/branches/trunk-20080910/modules/interface/pom.xml new file mode 100644 index 0000000000..7c75e66767 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/pom.xml @@ -0,0 +1,57 @@ +<?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-interface</artifactId> + <name>Apache Tuscany SCA Interface Model</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-policy</artifactId> + <version>1.4-SNAPSHOT</version> + </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.interface</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.interfacedef*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/ConversationSequence.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/ConversationSequence.java new file mode 100644 index 0000000000..247a432330 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/ConversationSequence.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef; + +/** + * Enum of the Conversation Sequence values. + * + * @version $Rev$ $Date$ + */ +public enum ConversationSequence { + CONVERSATION_NONE, CONVERSATION_START, CONVERSATION_CONTINUE, CONVERSATION_END +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/DataType.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/DataType.java new file mode 100644 index 0000000000..1f5620c0b9 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/DataType.java @@ -0,0 +1,119 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +import java.lang.reflect.Type; + +/** + * Representation of the type of data associated with an operation. Data is + * represented in two forms: the physical form used by the runtime and a logical + * form used by the assembly. The physical form is a Java Type because the + * runtime is written in Java. This may be the same form used by the application + * but it may not; for example, an application that is performing stream + * processing may want a physical form such as an + * {@link java.io.InputStream InputStream} to semantially operate on application + * data such as a purchase order. The logical description is that used by the + * assembly model and is an identifier into some well-known type space; examples + * may be a Java type represented by its Class or an XML type represented by its + * QName. Every data type may also contain metadata describing the expected + * data; for example, it could specify a preferred data binding technology or + * the size of a typical instance. + * + * @version $Rev$ $Date$ + */ +public interface DataType<L> extends Cloneable { + /** + * Set the java type for the data + * @param cls + */ + void setPhysical(Class<?> cls); + + /** + * Returns the physical type used by the runtime. + * + * @return the physical type used by the runtime + */ + Class<?> getPhysical(); + + /** + * Get the java generic type + * @return The java generic type + */ + Type getGenericType(); + + /** + * Set the java generic type + * @param genericType + */ + void setGenericType(Type genericType); + + /** + * Returns the logical identifier used by the assembly. The type of this + * value identifies the logical type system in use. Known values are: + * <ul> + * <li>a Class identifies a Java type by name and + * ClassLoader; this includes Java Classes as they are specializations of + * Type</li> + * <li>a XMLType identifies an XML type by local name and + * namespace</li> + * </ul> + * + * @return the logical type name + */ + L getLogical(); + + /** + * Get the databinding for the given data type + * @return the databinding + */ + String getDataBinding(); + + /** + * Set the databinding for the given data type + * @param dataBinding the dataBinding to set + */ + void setDataBinding(String dataBinding); + + /** + * Clone a data type + * @return The cloned data type + * @throws CloneNotSupportedException + */ + Object clone() throws CloneNotSupportedException; + + /** + * Set the logical type of the data type + * @param logical the logical to set + */ + void setLogical(L logical); + + /** + * Get the databinding-specific metadata + * @param type The java type of the metadata + * @return the databinding-specific metadata + */ + <T> T getMetaData(Class<T> type); + /** + * Set the databinding-specific metadata + * @param type The java type of the metadata + * @param metaData the databinding-specific metadata, such as SDO's commonj.sdo.Type or + * JAXB's javax.xml.bind.JAXBContext + */ + <T> void setMetaData(Class<T> type, T metaData); +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/FaultExceptionMapper.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/FaultExceptionMapper.java new file mode 100644 index 0000000000..70f6d5b403 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/FaultExceptionMapper.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef; + +/** + * This interface represents the mapping between WSDL faults and Java exceptions + * + * @version $Rev$ $Date$ + */ +@SuppressWarnings("unchecked") +public interface FaultExceptionMapper { + /** + * Introspect an exception class to find out the fault data type following the WSDL2Java + * mapping rules. The result will be populated into the logical type of the exception data + * type + * + * @param exceptionDataType The data type representing a java exception class + * @param operation TODO + * @param generatingFaultBean If JAXWS Section 3.7 Fault Bean will be generated + * @return true if the introspection can recognize the exception data type + */ + boolean introspectFaultDataType(DataType<DataType> exceptionDataType, Operation operation, boolean generatingFaultBean); + + /** + * Create a java exception to wrap the fault data + * + * @param exceptionType The DataType for the exception + * @param message message for the exception + * @param faultInfo The fault data + * @param cause of the exception + * @param operation TODO + * @return An instance of java exception to represent the fault + */ + Throwable wrapFaultInfo(DataType<DataType> exceptionType, String message, Object faultInfo, Throwable cause, Operation operation); + + /** + * Retrieve the fault info from a java exception + * + * @param exception The java exception that represents the fault data + * @param faultBeanClass + * @param operation TODO + * @return The fault data + */ + Object getFaultInfo(Throwable exception, Class<?> faultBeanClass, Operation operation); +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/IncompatibleInterfaceContractException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/IncompatibleInterfaceContractException.java new file mode 100644 index 0000000000..179dc1755e --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/IncompatibleInterfaceContractException.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef; + +/** + * Denotes incompatible service contracts for a wire + * + * @version $Rev$ $Date$ + */ +public class IncompatibleInterfaceContractException extends Exception { + private static final long serialVersionUID = 5127478601823295587L; + private final InterfaceContract source; + private final InterfaceContract target; + private final Operation sourceOperation; + private final Operation targetOperation; + + public IncompatibleInterfaceContractException(String message, InterfaceContract source, InterfaceContract target) { + super(message); + this.source = source; + this.target = target; + this.sourceOperation = null; + this.targetOperation = null; + } + + public IncompatibleInterfaceContractException(String message, + InterfaceContract source, + InterfaceContract target, + Operation sourceOperation, + Operation targetOperation) { + super(message); + this.source = source; + this.target = target; + this.sourceOperation = sourceOperation; + this.targetOperation = targetOperation; + } + + public InterfaceContract getTarget() { + return target; + } + + public InterfaceContract getSource() { + return source; + } + + public Operation getSourceOperation() { + return sourceOperation; + } + + public Operation getTargetOperation() { + return targetOperation; + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Interface.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Interface.java new file mode 100644 index 0000000000..f9de645a6e --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Interface.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +import java.util.List; + +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents a service interface. This interface will typically be extended to + * support concrete interface type systems, such as Java interfaces, WSDL 1.1 + * portTypes and WSDL 2.0 interfaces. + * + * @version $Rev$ $Date$ + */ +public interface Interface extends Cloneable, PolicySetAttachPoint { + + /** + * Returns true if the interface is a remotable interface.. + * + * @return true if the interface is a remotable interface + */ + boolean isRemotable(); + + /** + * Sets whether the interface is a remotable or local interface. + * + * @param remotable indicates whether the interface is remotable or local + */ + void setRemotable(boolean remotable); + + + // FIXME: [rfeng] We need to re-consider the conversational as an intent + /** + * Test if the interface is conversational + * @return + */ + boolean isConversational(); + + /** + * Set whether the interface is conversational + * @param conversational + */ + void setConversational(boolean conversational); + + /** + * Returns the operations defined on this interface. + * + * @return the operations defined on this interface + */ + List<Operation> getOperations(); + + /** + * Set the databinding for the interface + * @param dataBinding + * @deprecated Please use resetDataBinding + */ + @Deprecated + void setDefaultDataBinding(String dataBinding); + + /** + * Reset the databinding for the interface + * @param dataBinding + */ + void resetDataBinding(String dataBinding); + + /** + * Returns true if the Interface is dynamic. + * + * @return true if the Interface is dynamic. + */ + boolean isDynamic(); + + /** + * Implementations must support cloning. + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContract.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContract.java new file mode 100644 index 0000000000..568a6c595c --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContract.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + + +/** + * Interface contracts define one or more business functions. These business + * functions are provided by services and are used by references. + * + * @version $Rev$ $Date$ + */ +public interface InterfaceContract extends Cloneable { + + /** + * Returns the interface definition representing the interface for + * invocations from the requestor to the provider. + * + * @return the interface definition representing the interface for + * invocations from the requestor to the provider + */ + Interface getInterface(); + + /** + * Sets the interface definition representing the interface for invocations + * from the requestor to the provider. + * + * @param callInterface the interface definition representing the interface + * for invocations from the requestor to the provider + */ + void setInterface(Interface callInterface); + + /** + * Returns the interface definition representing the interface for + * invocations from the provider to the requestor. + * + * @return the interface definition representing the interface for + * invocations from the provider to the requestor. + */ + Interface getCallbackInterface(); + + /** + * Sets the interface definition representing the interface for invocations + * from the provider to the requestor. + * + * @param callbackInterface the interface definition representing the + * interface for invocations from the provider to the requestor. + */ + void setCallbackInterface(Interface callbackInterface); + + // FIXME: We need a better way to do this + /** + * Convert an interface contract to a unidirectional interface contract + * + * @param isCallback true for a callback interface contract, false for + * a forward interface contract + * @return A unidirectional interface contract, cloned if necessary + */ + InterfaceContract makeUnidirectional(boolean isCallback); + + /** + * Implementations must support cloning. + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContractMapper.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContractMapper.java new file mode 100644 index 0000000000..5601b09660 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InterfaceContractMapper.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef; + +/** + * The InterfaceContractMapper is responsible to match interfaces + * + * @version $Rev$ $Date$ + */ +public interface InterfaceContractMapper { + /** + * Check the compatibility of the source and the target interface contracts. + * <p> + * A wire may only connect a source to a target if the target implements an + * interface that is compatible with the interface required by the source. + * The source and the target are compatible if: <p/> + * <ol> + * <li>the source interface and the target interface MUST either both be + * remotable or they are both local + * <li>the methods on the target interface MUST be the same as or be a + * superset of the methods in the interface specified on the source + * <li>compatibility for the individual method is defined as compatibility + * of the signature, that is method name, input types, and output types MUST + * BE the same. + * <li>the order of the input and output types also MUST BE the same. + * <li>the set of Faults and Exceptions expected by the source MUST BE the + * same or be a superset of those specified by the service. + * <li>other specified attributes of the two interfaces MUST match, + * including Scope and Callback interface + * </ol> + * <p/> + * <p> + * Please note this test is not symmetric: the success of isCompatible(A, B) + * does NOT imply isCompatible(B, A) + * + * @param source The source interface contract + * @param target The target interface contract + * @return true if the source contract can be supported by the target + * contract + */ + boolean isCompatible(InterfaceContract source, InterfaceContract target); + + /** + * @param source + * @param target + * @param ignoreCallback + * @param silent + * @return + * @throws IncompatibleInterfaceContractException + */ + boolean checkCompatibility(InterfaceContract source, + InterfaceContract target, + boolean ignoreCallback, + boolean silent) throws IncompatibleInterfaceContractException; + + /** + * Test if the source data type is compatible with the target data type. The + * compatibility is defined as follows. + * <ul> + * <li>source's logical type is either the same or subtype of the target's + * logical type + * </ul> + * For example, if the source type is a SDO Customer and the target type is + * a JAXB Customer and both Customer are generated from the same XSD type. + * + * @param source The source data type + * @param target The target data type + * @return + */ + boolean isCompatible(DataType source, DataType target, boolean remotable); + + /** + * Check if source operation is compatible with the target operation + * + * @param source The source operation + * @param target The target operation + * @return true if the source operation is compatible with the target + * operation + */ + boolean isCompatible(Operation source, Operation target, boolean remotable); + + /** + * @param source + * @param target + * @return + */ + boolean isCompatible(Interface source, Interface target); + + /** + * Map the source operation to a compatible operation in the target + * interface + * + * @param target The target interface + * @param source The source operation + * @return A compatible operation + */ + Operation map(Interface target, Operation source); +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidCallbackException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidCallbackException.java new file mode 100644 index 0000000000..f952a86478 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidCallbackException.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.interfacedef; + + +/** + * Denotes an illegal callback interface + * + * @version $Rev$ $Date$ + */ + +public class InvalidCallbackException extends InvalidInterfaceException { + private static final long serialVersionUID = 2727755895702116397L; + + public InvalidCallbackException(String message) { + super(message); + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidInterfaceException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidInterfaceException.java new file mode 100644 index 0000000000..2a273c9a26 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidInterfaceException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +/** + * @version $Rev$ $Date$ + */ +public abstract class InvalidInterfaceException extends Exception { + + public InvalidInterfaceException() { + super(); + } + + public InvalidInterfaceException(String message) { + super(message); + } + + public InvalidInterfaceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidInterfaceException(Throwable cause) { + super(cause); + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidOperationException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidOperationException.java new file mode 100644 index 0000000000..b19805c5b1 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/InvalidOperationException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +import java.lang.reflect.Method; + +/** + * Denotes an invalid conversational interface definition + * + * @version $Rev$ $Date$ + */ +public class InvalidOperationException extends InvalidInterfaceException { + + private static final long serialVersionUID = -1797615361821517091L; + private final Method operation; + + public InvalidOperationException(String message, Method operation) { + super(message); + this.operation = operation; + } + + public Method getOperation() { + return operation; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java new file mode 100644 index 0000000000..4676e35f80 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.policy.PolicySetAttachPoint; + +/** + * Represents an operation on a service interface. + * + * @version $Rev$ $Date$ + */ +public interface Operation extends Cloneable, PolicySetAttachPoint { + /** + * Returns the name of the operation. + * + * @return the name of the operation + */ + String getName(); + + /** + * Sets the name of the operation. + * + * @param name the name of the operation + */ + void setName(String name); + + /** + * Returns true if the model element is unresolved. + * + * @return true if the model element is unresolved. + */ + boolean isUnresolved(); + + /** + * Sets whether the model element is unresolved. + * + * @param unresolved whether the model element is unresolved + */ + void setUnresolved(boolean unresolved); + + /** + * Get the data type that represents the input of this operation. The logic + * type is a list of data types and each element represents a parameter + * + * @return the inputType + */ + DataType<List<DataType>> getInputType(); + + /** + * @param inputType + */ + void setInputType(DataType<List<DataType>> inputType); + + /** + * Get the data type for the output + * + * @return the outputType + */ + DataType getOutputType(); + + /** + * @param outputType + */ + void setOutputType(DataType outputType); + + /** + * Get a list of data types to represent the faults/exceptions + * + * @return the faultTypes + */ + List<DataType> getFaultTypes(); + + /** + * @param faultTypes + */ + void setFaultTypes(List<DataType> faultTypes); + + /** + * Get the owning interface + * @return + */ + Interface getInterface(); + + /** + * Set the owning interface + * @param interfaze + */ + void setInterface(Interface interfaze); + + /** + * Get the sequence of the conversation + * @return + */ + ConversationSequence getConversationSequence(); + + /** + * Set the sequence of conversation for the operation + * @param sequence + */ + void setConversationSequence(ConversationSequence sequence); + + /** + * Indicate if the operation is non-blocking + * @return + */ + boolean isNonBlocking(); + + /** + * Set the operation to be non-blocking + */ + void setNonBlocking(boolean nonBlocking); + + /** + * @return the wrapperInfo + */ + WrapperInfo getWrapper(); + + /** + * @param wrapperInfo the wrapperInfo to set + */ + void setWrapper(WrapperInfo wrapperInfo); + + /** + * @return the wrapperStyle + */ + boolean isWrapperStyle(); + + /** + * @param wrapperStyle the wrapperStyle to set + */ + void setWrapperStyle(boolean wrapperStyle); + + /** + * @deprecated This should be the WrapperInfo.getDataBinding() + * Get the databinding for the operation + * @return + */ + @Deprecated + String getDataBinding(); + + /** + * @deprecated This should be the WrapperInfo.setDataBinding() + * Set the databinding for the operation + * @param dataBinding + */ + @Deprecated + void setDataBinding(String dataBinding); + + /** + * Returns true if the operation is dynamic. + * + * @return true if the operation is dynamic otherwise false + */ + boolean isDynamic(); + + /** + * Set if the operation is dynamic + * @param b + */ + void setDynamic(boolean b); + + /** + * Get the synthesized fault beans for this operation + * + * @return the fault beans + */ + Map<QName, List<DataType<XMLType>>> getFaultBeans(); + + /** + * Set the synthesized fault beans for this operation + * @param faultBeans + */ + void setFaultBeans(Map<QName, List<DataType<XMLType>>> faultBeans); + + /** + * Implementations must support cloning. + */ + Object clone() throws CloneNotSupportedException; + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/OverloadedOperationException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/OverloadedOperationException.java new file mode 100644 index 0000000000..6773b29088 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/OverloadedOperationException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef; + +import java.lang.reflect.Method; + +/** + * Exception thrown to indicate that a service contract specification contains + * an overloaded method. + * + * @version $Rev$ $Date$ + */ +public class OverloadedOperationException extends InvalidInterfaceException { + private static final long serialVersionUID = -4658711318608885638L; + private final Method operation; + + public OverloadedOperationException(Method operation) { + super(operation == null ? + null : "Cannot overload operation " + operation.getName() + + " on " + operation.getDeclaringClass().getName() + + " as it is a @Remotable interface"); + this.operation = operation; + } + + public Method getOperation() { + return operation; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java new file mode 100644 index 0000000000..c1c8400b71 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.impl; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * Representation of the type of data associated with an operation. Data is + * represented in two forms: the physical form used by the runtime and a logical + * form used by the assembly. The physical form is a Java Type because the + * runtime is written in Java. This may be the same form used by the application + * but it may not; for example, an application that is performing stream + * processing may want a physical form such as an + * {@link java.io.InputStream InputStream} to semantially operate on application + * data such as a purchase order. The logical description is that used by the + * assembly model and is an identifier into some well-known type space; examples + * may be a Java type represented by its Class or an XML type represented by its + * QName. Every data type may also contain metadata describing the expected + * data; for example, it could specify a preferred data binding technology or + * the size of a typical instance. + * + * @version $Rev$ $Date$ + */ +public class DataTypeImpl<L> implements DataType<L> { + private String dataBinding; + private Class<?> physical; + private Type genericType; + private L logical; + private Map<Class<?>, Object> metaDataMap; + + /** + * Construct a data type specifying the physical and logical types. + * + * @param physical the physical class used by the runtime + * @param logical the logical type + * @see #getLogical() + */ + public DataTypeImpl(Class<?> physical, L logical) { + this(null, physical, physical, logical); + } + + /** + * @param dataBinding + * @param physical + * @param logical + */ + public DataTypeImpl(String dataBinding, Class<?> physical, L logical) { + this(dataBinding, physical, physical, logical); + } + + /** + * @param dataBinding + * @param physical + * @param genericType + * @param logical + */ + public DataTypeImpl(String dataBinding, Class<?> physical, Type genericType, L logical) { + super(); + this.dataBinding = dataBinding; + this.physical = physical; + this.genericType = genericType; + this.logical = logical; + } + + /** + * Returns the physical type used by the runtime. + * + * @return the physical type used by the runtime + */ + public Class<?> getPhysical() { + return physical; + } + + /** + * @param physical the physical to set + */ + public void setPhysical(Class<?> physical) { + this.physical = physical; + } + + /** + * Get the java generic type + * @return The java generic type + */ + public Type getGenericType() { + return genericType; + } + + /** + * Set the java generic type + * @param genericType + */ + public void setGenericType(Type genericType) { + this.genericType = genericType; + } + + /** + * Returns the logical identifier used by the assembly. The type of this + * value identifies the logical type system in use. Known values are: + * <ul> + * <li>a java.lang.reflect.Type identifies a Java type by name and + * ClassLoader; this includes Java Classes as they are specializations of + * Type</li> + * <li>a javax.xml.namespace.QName identifies an XML type by local name and + * namespace</li> + * </ul> + * + * @return the logical type name + */ + public L getLogical() { + return logical; + } + + /** + * @param logical the logical to set + */ + public void setLogical(L logical) { + this.logical = logical; + } + + public String getDataBinding() { + return dataBinding; + } + + /** + * @param dataBinding the dataBinding to set + */ + public void setDataBinding(String dataBinding) { + this.dataBinding = dataBinding; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(physical).append(" ").append(dataBinding).append(" ").append(logical); + return sb.toString(); + } + + @SuppressWarnings("unchecked") + @Override + public Object clone() throws CloneNotSupportedException { + DataTypeImpl copy = (DataTypeImpl)super.clone(); + return copy; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dataBinding == null) ? 0 : dataBinding.hashCode()); + result = prime * result + ((genericType == null) ? 0 : genericType.hashCode()); + result = prime * result + ((logical == null) ? 0 : logical.hashCode()); + result = prime * result + ((physical == null) ? 0 : physical.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final DataTypeImpl other = (DataTypeImpl)obj; + if (dataBinding == null) { + if (other.dataBinding != null) + return false; + } else if (!dataBinding.equals(other.dataBinding)) + return false; + if (genericType == null) { + if (other.genericType != null) + return false; + } else if (!genericType.equals(other.genericType)) + return false; + if (logical == null) { + if (other.logical != null) + return false; + } else if (!logical.equals(other.logical)) + return false; + if (physical == null) { + if (other.physical != null) + return false; + } else if (!physical.equals(other.physical)) + return false; + return true; + } + + public <T> T getMetaData(Class<T> type) { + return metaDataMap == null ? null : type.cast(metaDataMap.get(type)); + } + + public <T> void setMetaData(Class<T> type, T metaData) { + if (metaDataMap == null) { + metaDataMap = new ConcurrentHashMap<Class<?>, Object>(); + } + metaDataMap.put(type, metaData); + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractImpl.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractImpl.java new file mode 100644 index 0000000000..15581b5e04 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractImpl.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.impl; + +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * Represents an interface contract. InterfaceContractImpl + * + * @version $Rev$ $Date$ + */ +public abstract class InterfaceContractImpl implements InterfaceContract { + private Interface callInterface; + private Interface callbackInterface; + + public Interface getCallbackInterface() { + return callbackInterface; + } + + public Interface getInterface() { + return callInterface; + } + + public void setCallbackInterface(Interface callbackInterface) { + this.callbackInterface = callbackInterface; + } + + public void setInterface(Interface callInterface) { + this.callInterface = callInterface; + } + + public InterfaceContract makeUnidirectional(boolean isCallback) { + if (!isCallback && callbackInterface == null) + return this; // already a unidirectional forward interface contract + + if (isCallback && callInterface == null) + return this; // already a unidirectional callback interface contract + + // contract is bidirectional, so create a new unidirectional contract + try { + InterfaceContract newContract = clone(); + if (!isCallback) { + newContract.setCallbackInterface(null); // create unidirectional forward interface contract + } else { + newContract.setInterface(null); // create unidirectional callback interface contract + } + return newContract; + } catch (CloneNotSupportedException e) { + // will not happen + return null; + } + } + + @Override + public InterfaceContractImpl clone() throws CloneNotSupportedException { + InterfaceContractImpl copy = (InterfaceContractImpl)super.clone(); + if (this.callbackInterface != null) { + copy.callbackInterface = (Interface)this.callbackInterface.clone(); + } + if (this.callInterface != null) { + copy.callInterface = (Interface)this.callInterface.clone(); + } + return copy; + } + + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((callInterface == null) ? 0 : callInterface.hashCode()); + result = prime * result + ((callbackInterface == null) ? 0 : callbackInterface.hashCode()); + return result; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final InterfaceContractImpl other = (InterfaceContractImpl)obj; + if (callInterface == null) { + if (other.callInterface != null) { + return false; + } + } else if (!callInterface.equals(other.callInterface)) { + return false; + } + if (callbackInterface == null) { + if (other.callbackInterface != null) { + return false; + } + } else if (!callbackInterface.equals(other.callbackInterface)) { + return false; + } + return true; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractMapperImpl.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractMapperImpl.java new file mode 100644 index 0000000000..9e7d6882f7 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractMapperImpl.java @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.impl; + +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.IncompatibleInterfaceContractException; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * @version $Rev$ $Date$ + */ +public class InterfaceContractMapperImpl implements InterfaceContractMapper { + + public boolean isCompatible(DataType source, DataType target, boolean remotable) { + if (source == target) { + return true; + } + if (!remotable) { + if (source == null || target == null) { + return false; + } + // For local case + return target.getPhysical().isAssignableFrom(source.getPhysical()); + } else { + // FIXME: How to test if two remotable data type is compatible? + // return target.getLogical().equals(source.getLogical()); + return true; + } + + } + + public boolean isCompatible(Operation source, Operation target, boolean remotable) { + if (source == target) { + return true; + } + + if (source.isDynamic() || target.isDynamic()) { + return true; + } + + // Check name + if (!source.getName().equals(target.getName())) { + return false; + } + + if (source.getInterface().isRemotable() != target.getInterface().isRemotable()) { + return false; + } + + // if (source.getInterface().isRemotable()) { + // return true; + // } + + // FIXME: We need to deal with wrapped<-->unwrapped conversion + + // Check output type + DataType sourceOutputType = source.getOutputType(); + DataType targetOutputType = target.getOutputType(); + + // Note the target output type is now the source for checking + // compatibility + if (!isCompatible(targetOutputType, sourceOutputType, remotable)) { + return false; + } + + boolean checkSourceWrapper = true; + List<DataType> sourceInputType = source.getInputType().getLogical(); + if (source.isWrapperStyle() && source.getWrapper() != null) { + sourceInputType = source.getWrapper().getUnwrappedInputType().getLogical(); + checkSourceWrapper = false; + } + boolean checkTargetWrapper = true; + List<DataType> targetInputType = target.getInputType().getLogical(); + if (target.isWrapperStyle() && target.getWrapper() != null) { + targetInputType = target.getWrapper().getUnwrappedInputType().getLogical(); + checkTargetWrapper = false; + } + + if (checkSourceWrapper != checkTargetWrapper) { + return true; + } + if (sourceInputType.size() != targetInputType.size()) { + return false; + } + + int size = sourceInputType.size(); + for (int i = 0; i < size; i++) { + if (!isCompatible(sourceInputType.get(i), targetInputType.get(i), remotable)) { + return false; + } + } + + // Check fault types + for (DataType targetFaultType : target.getFaultTypes()) { + // Source fault types must be the same or superset of target fault + // types + boolean found = true; + for (DataType sourceFaultType : source.getFaultTypes()) { + found = false; + if (isCompatible(targetFaultType, sourceFaultType, remotable)) { + // Target fault type can be covered by the source fault type + found = true; + break; + } + } + if (!found) { + return false; + } + } + + return true; + } + + // FIXME: How to improve the performance for the lookup + private Operation getOperation(List<Operation> operations, String name) { + for (Operation op : operations) { + if (op.getName().equals(name)) { + return op; + } + } + return null; + } + + public boolean checkCompatibility(InterfaceContract source, + InterfaceContract target, + boolean ignoreCallback, + boolean silent) throws IncompatibleInterfaceContractException { + if (source == target) { + // Shortcut for performance + return true; + } + + if (source.getInterface().isDynamic() || target.getInterface().isDynamic()) { + return true; + } + + if (source.getInterface().isRemotable() != target.getInterface().isRemotable()) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Remotable settings do not match", source, target); + } else { + return false; + } + } + if (source.getInterface().isConversational() != target.getInterface().isConversational()) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Interaction scopes do not match", source, target); + } else { + return false; + } + } + + for (Operation operation : source.getInterface().getOperations()) { + Operation targetOperation = map(target.getInterface(), operation); + if (targetOperation == null) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Operation not found on target", source, target); + } else { + return false; + } + } + if (!source.getInterface().isRemotable()) { + // FIXME: for remotable operation, only compare name for now + if (!isCompatible(operation, targetOperation, false)) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Target operations are not compatible", + source, target); + } else { + return false; + } + } + } + } + + if (ignoreCallback) { + return true; + } + + if (source.getCallbackInterface() == null && target.getCallbackInterface() == null) { + return true; + } + if (source.getCallbackInterface() == null || target.getCallbackInterface() == null) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Callback interface doesn't match", source, target); + } else { + return false; + } + } + + for (Operation operation : source.getCallbackInterface().getOperations()) { + Operation targetOperation = + getOperation(target.getCallbackInterface().getOperations(), operation.getName()); + if (targetOperation == null) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Callback operation not found on target", source, + target, null, targetOperation); + } else { + return false; + } + } + if (!source.getCallbackInterface().isRemotable()) { + // FIXME: for remotable operation, only compare name for now + if (!operation.equals(targetOperation)) { + if (!silent) { + throw new IncompatibleInterfaceContractException("Target callback operation is not compatible", + source, target, operation, targetOperation); + } else { + return false; + } + } + } + } + return true; + } + + public boolean isCompatible(Interface source, Interface target) { + if (source == target) { + // Shortcut for performance + return true; + } + if (source == null || target == null) { + return false; + } + + if (source.isDynamic() || target.isDynamic()) { + return true; + } + + if (source.isRemotable() != target.isRemotable()) { + return false; + } + if (source.isConversational() != target.isConversational()) { + return false; + } + + for (Operation operation : source.getOperations()) { + Operation targetOperation = getOperation(target.getOperations(), operation.getName()); + if (targetOperation == null) { + return false; + } + if (!isCompatible(operation, targetOperation, source.isRemotable())) { + return false; + } + } + return true; + } + + public boolean isCompatible(InterfaceContract source, InterfaceContract target) { + try { + return checkCompatibility(source, target, false, false); + } catch (IncompatibleInterfaceContractException e) { + return false; + } + } + + /** + * @see org.apache.tuscany.sca.interfacedef.InterfaceContractMapper#map(org.apache.tuscany.sca.interfacedef.Interface, + * org.apache.tuscany.sca.interfacedef.Operation) + */ + public Operation map(Interface target, Operation source) { + // TODO: How to handle the case that source operation is dynamic? + if (target == null || target.isDynamic()) { + return source; + } else if (target.isRemotable()) { + for (Operation op : target.getOperations()) { + if (op.getName().equals(source.getName())) { + return op; + } + } + return null; + } else { + for (Operation op : target.getOperations()) { + if (isCompatible(source, op, target.isRemotable())) { + return op; + } + } + return null; + } + + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceImpl.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceImpl.java new file mode 100644 index 0000000000..e2a524c5e0 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceImpl.java @@ -0,0 +1,296 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +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.util.WrapperInfo; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents a service interface. + * + * @version $Rev$ $Date$ + */ +public class InterfaceImpl implements Interface { + + private boolean remotable; + private boolean conversational; + private OperationList operations = new OperationList(); + private boolean unresolved; + + private List<PolicySet> applicablePolicySets = new ArrayList<PolicySet>(); + private IntentAttachPointType type; + private List<PolicySet> policySets = new ArrayList<PolicySet>(); + private List<Intent> requiredIntents = new ArrayList<Intent>(); + + + public boolean isRemotable() { + return remotable; + } + + public void setRemotable(boolean local) { + this.remotable = local; + } + + public List<Operation> getOperations() { + return operations; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean undefined) { + this.unresolved = undefined; + } + + /** + * @return the conversational + */ + public boolean isConversational() { + return conversational; + } + + /** + * @param conversational the conversational to set + */ + public void setConversational(boolean conversational) { + this.conversational = conversational; + } + + private class OperationList extends ArrayList<Operation> { + private static final long serialVersionUID = -903469106307606099L; + + @Override + public Operation set(int index, Operation element) { + element.setInterface(InterfaceImpl.this); + return super.set(index, element); + } + + @Override + public void add(int index, Operation element) { + element.setInterface(InterfaceImpl.this); + super.add(index, element); + } + + @Override + public boolean add(Operation o) { + o.setInterface(InterfaceImpl.this); + return super.add(o); + } + + @Override + public boolean addAll(Collection<? extends Operation> c) { + for (Operation op : c) { + op.setInterface(InterfaceImpl.this); + } + return super.addAll(c); + } + + @Override + public boolean addAll(int index, Collection<? extends Operation> c) { + for (Operation op : c) { + op.setInterface(InterfaceImpl.this); + } + return super.addAll(index, c); + } + + } + + @Deprecated + public void setDefaultDataBinding(String dataBinding) { + for (Operation op : getOperations()) { + if (op.getDataBinding() == null) { + op.setDataBinding(dataBinding); + DataType<List<DataType>> inputType = op.getInputType(); + if (inputType != null) { + for (DataType d : inputType.getLogical()) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBinding); + } + } + } + DataType outputType = op.getOutputType(); + if (outputType != null && outputType.getDataBinding() == null) { + outputType.setDataBinding(dataBinding); + } + List<DataType> faultTypes = op.getFaultTypes(); + if (faultTypes != null) { + for (DataType d : faultTypes) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBinding); + } + DataType ft = (DataType) d.getLogical(); + if (ft.getDataBinding() == null) { + ft.setDataBinding(dataBinding); + } + + } + } + if (op.isWrapperStyle()) { + WrapperInfo wrapper = op.getWrapper(); + if (wrapper != null) { + DataType<List<DataType>> unwrappedInputType = wrapper.getUnwrappedInputType(); + if (unwrappedInputType != null) { + for (DataType d : unwrappedInputType.getLogical()) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBinding); + } + } + } + DataType unwrappedOutputType = wrapper.getUnwrappedOutputType(); + if (unwrappedOutputType != null && unwrappedOutputType.getDataBinding() == null) { + unwrappedOutputType.setDataBinding(dataBinding); + } + } + } + } + } + } + + private void setDataBinding(DataType dataType, String dataBinding) { + if ("java:array".equals(dataType.getDataBinding())) { + setDataBinding((DataType)dataType.getLogical(), dataBinding); + } else { + dataType.setDataBinding(dataBinding); + } + } + + public void resetDataBinding(String dataBinding) { + for (Operation op : getOperations()) { + op.setDataBinding(dataBinding); + DataType<List<DataType>> inputType = op.getInputType(); + if (inputType != null) { + for (DataType d : inputType.getLogical()) { + setDataBinding(d, dataBinding); + } + } + DataType outputType = op.getOutputType(); + if (outputType != null) { + setDataBinding(outputType, dataBinding); + } + List<DataType> faultTypes = op.getFaultTypes(); + if (faultTypes != null) { + for (DataType d : faultTypes) { + setDataBinding(d, dataBinding); + setDataBinding((DataType) d.getLogical(), dataBinding); + } + } + if (op.isWrapperStyle()) { + WrapperInfo wrapper = op.getWrapper(); + if (wrapper != null) { + DataType<List<DataType>> unwrappedInputType = wrapper.getUnwrappedInputType(); + if (unwrappedInputType != null) { + for (DataType d : unwrappedInputType.getLogical()) { + setDataBinding(d, dataBinding); + } + } + DataType unwrappedOutputType = wrapper.getUnwrappedOutputType(); + if (unwrappedOutputType != null) { + setDataBinding(unwrappedOutputType, dataBinding); + } + } + } + } + } + + public boolean isDynamic() { + return false; + } + + public List<PolicySet> getApplicablePolicySets() { + return applicablePolicySets; + } + + public List<PolicySet> getPolicySets() { + return policySets; + } + + public List<Intent> getRequiredIntents() { + return requiredIntents; + } + + public IntentAttachPointType getType() { + return type; + } + + public void setType(IntentAttachPointType type) { + this.type = type; + } + + @Override + public Object clone() throws CloneNotSupportedException { + InterfaceImpl copy = (InterfaceImpl)super.clone(); + copy.operations = new OperationList(); + for (Operation operation : this.operations) { + Operation clonedOperation = (Operation)operation.clone(); + copy.operations.add(clonedOperation); + } + return copy; + } + + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (conversational ? 1231 : 1237); + result = prime * result + ((operations == null) ? 0 : operations.hashCode()); + result = prime * result + (remotable ? 1231 : 1237); + result = prime * result + (unresolved ? 1231 : 1237); + return result; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final InterfaceImpl other = (InterfaceImpl)obj; + if (conversational != other.conversational) + return false; + if (operations == null) { + if (other.operations != null) + return false; + } else if (!operations.equals(other.operations)) + return false; + if (remotable != other.remotable) + return false; + if (unresolved != other.unresolved) + return false; + return true; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java new file mode 100644 index 0000000000..00a5dc3065 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.interfacedef.ConversationSequence; +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.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.PolicySet; + +/** + * Represents an operation on a service interface. + * + * @version $Rev$ $Date$ + */ +public class OperationImpl implements Operation { + + private String name; + private boolean unresolved; + private DataType outputType; + private DataType<List<DataType>> inputType; + private List<DataType> faultTypes; + private Interface interfaze; + private ConversationSequence conversationSequence = ConversationSequence.CONVERSATION_NONE; + private boolean nonBlocking; + private boolean wrapperStyle; + private WrapperInfo wrapper; + private boolean dynamic; + private Map<QName, List<DataType<XMLType>>> faultBeans; + + private List<PolicySet> applicablePolicySets = new ArrayList<PolicySet>(); + private List<PolicySet> policySets = new ArrayList<PolicySet>(); + private List<Intent> requiredIntents = new ArrayList<Intent>(); + private IntentAttachPointType type; + + /** + * @param name + */ + public OperationImpl() { + inputType = new DataTypeImpl<List<DataType>>("idl:input", Object[].class, new ArrayList<DataType>()); + faultTypes = new ArrayList<DataType>(); + faultBeans = new HashMap<QName, List<DataType<XMLType>>>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isUnresolved() { + return unresolved; + } + + public void setUnresolved(boolean undefined) { + this.unresolved = undefined; + } + + /** + * @return the faultTypes + */ + public List<DataType> getFaultTypes() { + return faultTypes; + } + + /** + * @param faultTypes the faultTypes to set + */ + public void setFaultTypes(List<DataType> faultTypes) { + this.faultTypes = faultTypes; + } + + /** + * @return the inputType + */ + public DataType<List<DataType>> getInputType() { + return inputType; + } + + /** + * @param inputType the inputType to set + */ + public void setInputType(DataType<List<DataType>> inputType) { + this.inputType = inputType; + } + + /** + * @return the outputType + */ + public DataType getOutputType() { + return outputType; + } + + /** + * @param outputType the outputType to set + */ + public void setOutputType(DataType outputType) { + this.outputType = outputType; + } + + /** + * @return the interface + */ + public Interface getInterface() { + return interfaze; + } + + /** + * @param interfaze the interface to set + */ + public void setInterface(Interface interfaze) { + this.interfaze = interfaze; + } + + /** + * @return the conversationSequence + */ + public ConversationSequence getConversationSequence() { + return conversationSequence; + } + + /** + * @param conversationSequence the conversationSequence to set + */ + public void setConversationSequence(ConversationSequence conversationSequence) { + this.conversationSequence = conversationSequence; + } + + /** + * @return the nonBlocking + */ + public boolean isNonBlocking() { + return nonBlocking; + } + + /** + * @param nonBlocking the nonBlocking to set + */ + public void setNonBlocking(boolean nonBlocking) { + this.nonBlocking = nonBlocking; + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((conversationSequence == null) ? 0 : conversationSequence.hashCode()); + // result = PRIME * result + ((faultTypes == null) ? 0 : + // faultTypes.hashCode()); + result = PRIME * result + ((inputType == null) ? 0 : inputType.hashCode()); + result = PRIME * result + ((name == null) ? 0 : name.hashCode()); + result = PRIME * result + (nonBlocking ? 1231 : 1237); + result = PRIME * result + ((outputType == null) ? 0 : outputType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final OperationImpl other = (OperationImpl)obj; + if (conversationSequence == null) { + if (other.conversationSequence != null) { + return false; + } + } else if (!conversationSequence.equals(other.conversationSequence)) { + return false; + } + /* + * if (faultTypes == null) { if (other.faultTypes != null) { return + * false; } } else if (!faultTypes.equals(other.faultTypes)) { return + * false; } + */ + + if (inputType == null) { + if (other.inputType != null) { + return false; + } + } else if (!inputType.equals(other.inputType)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (nonBlocking != other.nonBlocking) { + return false; + } + if (outputType == null) { + if (other.outputType != null) { + return false; + } + } else if (!outputType.equals(other.outputType)) { + return false; + } + return true; + } + + /** + * @return the wrapperInfo + */ + public WrapperInfo getWrapper() { + return wrapper; + } + + /** + * @param wrapperInfo the wrapperInfo to set + */ + public void setWrapper(WrapperInfo wrapperInfo) { + this.wrapper = wrapperInfo; + } + + /** + * @return the wrapperStyle + */ + public boolean isWrapperStyle() { + return wrapperStyle; + } + + /** + * @param wrapperStyle the wrapperStyle to set + */ + public void setWrapperStyle(boolean wrapperStyle) { + this.wrapperStyle = wrapperStyle; + } + + public String getDataBinding() { + return wrapper != null ? wrapper.getDataBinding() : null; + } + + public void setDataBinding(String dataBinding) { + if (wrapper != null) { + wrapper.setDataBinding(dataBinding); + } + } + + public boolean isDynamic() { + return dynamic; + } + + public void setDynamic(boolean b) { + this.dynamic = b; + } + + public Map<QName, List<DataType<XMLType>>> getFaultBeans() { + return faultBeans; + } + + public void setFaultBeans(Map<QName, List<DataType<XMLType>>> faultBeans) { + this.faultBeans = faultBeans; + } + + @Override + public OperationImpl clone() throws CloneNotSupportedException { + OperationImpl copy = (OperationImpl) super.clone(); + + final List<DataType> clonedFaultTypes = new ArrayList<DataType>(this.faultTypes.size()); + for (DataType t : this.faultTypes) { + clonedFaultTypes.add((DataType) t.clone()); + } + copy.faultTypes = clonedFaultTypes; + + List<DataType> clonedLogicalTypes = new ArrayList<DataType>(); + for (DataType t : inputType.getLogical()) { + DataType type = (DataType) t.clone(); + clonedLogicalTypes.add(type); + } + DataType<List<DataType>> clonedInputType = + new DataTypeImpl<List<DataType>>(inputType.getPhysical(), clonedLogicalTypes); + clonedInputType.setDataBinding(inputType.getDataBinding()); + copy.inputType = clonedInputType; + + if (this.outputType != null) { + copy.outputType = (DataType) this.outputType.clone(); + } + + return copy; + } + + public List<PolicySet> getApplicablePolicySets() { + return applicablePolicySets; + } + + public List<PolicySet> getPolicySets() { + return policySets; + } + + public List<Intent> getRequiredIntents() { + return requiredIntents; + } + + public IntentAttachPointType getType() { + return type; + } + + public void setType(IntentAttachPointType type) { + this.type = type; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/ElementInfo.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/ElementInfo.java new file mode 100644 index 0000000000..777fa567f1 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/ElementInfo.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import javax.xml.namespace.QName; + +/** + * An abstraction of XML schema elements. + * + * @version $Rev$ $Date$ + */ +public class ElementInfo { + private final QName name; + private final TypeInfo type; + private boolean many = false; + private boolean nillable = false; + + /** + * @param name + * @param type + */ + public ElementInfo(QName name, TypeInfo type) { + super(); + this.name = name; + this.type = type; + } + + /** + * @return the name + */ + public QName getQName() { + return name; + } + + /** + * @return the type + */ + public TypeInfo getType() { + return type; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("Element: ").append(name).append(" ").append(type); + return sb.toString(); + } + + public boolean isMany() { + return many; + } + + public void setMany(boolean many) { + this.many = many; + } + + public boolean isNillable() { + return nillable; + } + + public void setNillable(boolean nillable) { + this.nillable = nillable; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final ElementInfo other = (ElementInfo)obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + /* + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + */ + return true; + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/FaultException.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/FaultException.java new file mode 100644 index 0000000000..844b0af509 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/FaultException.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import javax.xml.namespace.QName; + +/** + * The generic java exception to wrap service faults + * + * @version $Rev$ $Date$ + */ +public class FaultException extends Exception { + private static final long serialVersionUID = -8002583655240625792L; + private transient Object faultInfo; // FIXME: How to serialize it? + private QName faultName; + + /** + * @param message + * @param faultInfo + */ + public FaultException(String message, Object faultInfo) { + super(message); + this.faultInfo = faultInfo; + } + + /** + * @param message + * @param faultInfo + * @param cause + */ + public FaultException(String message, Object faultInfo, Throwable cause) { + super(message, cause); + this.faultInfo = faultInfo; + } + + /** + * @return the faultInfo + */ + public Object getFaultInfo() { + return faultInfo; + } + + public QName getFaultName() { + return faultName; + } + + public void setFaultName(QName logical) { + this.faultName = logical; + } + + public boolean isMatchingType(Object type) { + if (faultName == null) { + return false; + } + + if ((type instanceof QName) && faultName.equals(type)) { + return true; + } + if (type instanceof XMLType && faultName.equals(((XMLType)type).getElementName())) { + return true; + } + return false; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/JavaXMLMapper.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/JavaXMLMapper.java new file mode 100644 index 0000000000..54c0a3ec11 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/JavaXMLMapper.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * Utility class that can be used to map XSD types to Java classes and Java classes to XSD types. + * + * @version $Rev$ $Date$ + */ +public final class JavaXMLMapper { + public static final String URI_2001_SCHEMA_XSD = "http://www.w3.org/2001/XMLSchema"; + private static final Map<Class, QName> JAVA2XML = new HashMap<Class, QName>(); + private static final Map<String, Class> XML2JAVA = new HashMap<String, Class>(); + + private JavaXMLMapper() { + } + + static { + JAVA2XML.put(boolean.class, getTypeName("boolean")); + JAVA2XML.put(byte.class, getTypeName("byte")); + JAVA2XML.put(short.class, getTypeName("short")); + JAVA2XML.put(int.class, getTypeName("int")); + JAVA2XML.put(long.class, getTypeName("long")); + JAVA2XML.put(float.class, getTypeName("float")); + JAVA2XML.put(double.class, getTypeName("double")); + JAVA2XML.put(Boolean.class, getTypeName("boolean")); + JAVA2XML.put(Byte.class, getTypeName("byte")); + JAVA2XML.put(Short.class, getTypeName("short")); + JAVA2XML.put(Integer.class, getTypeName("int")); + JAVA2XML.put(Long.class, getTypeName("long")); + JAVA2XML.put(Float.class, getTypeName("float")); + JAVA2XML.put(Double.class, getTypeName("double")); + JAVA2XML.put(java.lang.String.class, getTypeName("string")); + JAVA2XML.put(java.math.BigInteger.class, getTypeName("integer")); + JAVA2XML.put(java.math.BigDecimal.class, getTypeName("decimal")); + JAVA2XML.put(java.util.Calendar.class, getTypeName("dateTime")); + JAVA2XML.put(java.util.Date.class, getTypeName("dateTime")); + JAVA2XML.put(javax.xml.namespace.QName.class, getTypeName("QName")); + JAVA2XML.put(java.net.URI.class, getTypeName("string")); + JAVA2XML.put(javax.xml.datatype.XMLGregorianCalendar.class, getTypeName("anySimpleType")); + JAVA2XML.put(javax.xml.datatype.Duration.class, getTypeName("duration")); + JAVA2XML.put(java.lang.Object.class, getTypeName("anyType")); + JAVA2XML.put(java.awt.Image.class, getTypeName("base64Binary")); + JAVA2XML.put(byte[].class, getTypeName("base64Binary")); + // java2XSD.put(javax.activation.DataHandler.class, getTypeName("base64Binary")); + JAVA2XML.put(javax.xml.transform.Source.class, getTypeName("base64Binary")); + JAVA2XML.put(java.util.UUID.class, getTypeName("string")); + } + + static { + XML2JAVA.put("string", java.lang.String.class); + XML2JAVA.put("integer", java.math.BigInteger.class); + XML2JAVA.put("int", int.class); + XML2JAVA.put("long", long.class); + XML2JAVA.put("short", short.class); + XML2JAVA.put("decimal", java.math.BigDecimal.class); + XML2JAVA.put("float", float.class); + XML2JAVA.put("double", double.class); + XML2JAVA.put("boolean", boolean.class); + XML2JAVA.put("byte", byte.class); + XML2JAVA.put("QName", javax.xml.namespace.QName.class); + XML2JAVA.put("dateTime", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("base64Binary", byte[].class); + XML2JAVA.put("hexBinary", byte[].class); + XML2JAVA.put("unsignedInt", long.class); + XML2JAVA.put("unsignedShort", int.class); + XML2JAVA.put("unsignedByte", short.class); + XML2JAVA.put("time", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("date", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gDay", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gMonth", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gYear", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gYearMonth", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("gMonthDay", javax.xml.datatype.XMLGregorianCalendar.class); + XML2JAVA.put("anySimpleType", java.lang.Object.class); // For elements + // XML2JAVA.put("anySimpleType", java.lang.String.class); // For + // attributes + XML2JAVA.put("duration", javax.xml.datatype.Duration.class); + XML2JAVA.put("NOTATION", javax.xml.namespace.QName.class); + } + + public static Class getJavaType(QName xmlType) { + if (URI_2001_SCHEMA_XSD.equals(xmlType.getNamespaceURI())) { + return XML2JAVA.get(xmlType.getLocalPart()); + } else { + return null; + } + } + + private static QName getTypeName(String name) { + return new QName(URI_2001_SCHEMA_XSD, name); + } + + public static QName getXMLType(Class javaType) { + return JAVA2XML.get(javaType); + } + + private static String getPackageName(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + public static String getNamespace(Class<?> cls) { + String packageName = getPackageName(cls); + if ("".equals(packageName)) { + return ""; + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = packageName.split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return ns.toString(); + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/TypeInfo.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/TypeInfo.java new file mode 100644 index 0000000000..2598dc8545 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/TypeInfo.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import javax.xml.namespace.QName; + +/** + * An abstraction of XML schema types + * + * @version $Rev$ $Date$ + */ +public class TypeInfo { + private QName name; + + private boolean isSimpleType; + + private TypeInfo baseType; + + /** + * @param name + * @param isSimpleType + */ + public TypeInfo(QName name, boolean isSimpleType, TypeInfo baseType) { + super(); + this.name = name; + this.isSimpleType = isSimpleType; + this.baseType = baseType; + } + + /** + * @return the isSimpleType + */ + public boolean isSimpleType() { + return isSimpleType; + } + + /** + * @return the name + */ + public QName getQName() { + return name; + } + + /** + * @return the baseType + */ + public TypeInfo getBaseType() { + return baseType; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("Type: ").append(name); + return sb.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final TypeInfo other = (TypeInfo)obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/WrapperInfo.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/WrapperInfo.java new file mode 100644 index 0000000000..12db460959 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/WrapperInfo.java @@ -0,0 +1,190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; + +/** + * The "Wrapper Style" WSDL operation is defined by The Java API for XML-Based + * Web Services (JAX-WS) 2.0 specification, section 2.3.1.2 Wrapper Style. <p/> + * A WSDL operation qualifies for wrapper style mapping only if the following + * criteria are met: + * <ul> + * <li>(i) The operation�s input and output messages (if present) each contain + * only a single part + * <li>(ii) The input message part refers to a global element declaration whose + * localname is equal to the operation name + * <li>(iii) The output message part refers to a global element declaration + * <li>(iv) The elements referred to by the input and output message parts + * (henceforth referred to as wrapper elements) are both complex types defined + * using the xsd:sequence compositor + * <li>(v) The wrapper elements only contain child elements, they must not + * contain other structures such as wildcards (element or attribute), + * xsd:choice, substitution groups (element references are not permitted) or + * attributes; furthermore, they must not be nillable. + * </ul> + * + * @version $Rev$ $Date$ + */ +public class WrapperInfo { + private ElementInfo inputWrapperElement; + + private ElementInfo outputWrapperElement; + + private List<ElementInfo> inputChildElements; + + private List<ElementInfo> outputChildElements; + + // The data type of the unwrapped input child elements + private DataType<List<DataType>> unwrappedInputType; + + // The data type of the unwrapped output child element (we only supports one child) + private DataType<XMLType> unwrappedOutputType; + + // The data for the input/output wrappers + private String dataBinding; + + // The data type for the input (request) wrapper bean + private DataType<XMLType> inputWrapperType; + // The data type for the output (response) wrapper bean + private DataType<XMLType> outputWrapperType; + + public WrapperInfo(String dataBinding, + ElementInfo inputWrapperElement, + ElementInfo outputWrapperElement, + List<ElementInfo> inputElements, + List<ElementInfo> outputElements) { + super(); + this.dataBinding = dataBinding; + this.inputWrapperElement = inputWrapperElement; + this.outputWrapperElement = outputWrapperElement; + this.inputChildElements = inputElements; + this.outputChildElements = outputElements; + } + + /** + * @return the inputElements + */ + public List<ElementInfo> getInputChildElements() { + return inputChildElements; + } + + /** + * @return the inputWrapperElement + */ + public ElementInfo getInputWrapperElement() { + return inputWrapperElement; + } + + /** + * @return the outputElements + */ + public List<ElementInfo> getOutputChildElements() { + return outputChildElements; + } + + /** + * @return the outputWrapperElement + */ + public ElementInfo getOutputWrapperElement() { + return outputWrapperElement; + } + + /** + * @return the unwrappedInputType + */ + public DataType<List<DataType>> getUnwrappedInputType() { + if (unwrappedInputType == null) { + List<DataType> childTypes = new ArrayList<DataType>(); + for (ElementInfo element : getInputChildElements()) { + DataType type = getDataType(element); + childTypes.add(type); + } + unwrappedInputType = new DataTypeImpl<List<DataType>>("idl:unwrapped.input", Object[].class, childTypes); + } + return unwrappedInputType; + } + + private DataType getDataType(ElementInfo element) { + DataType type = null; + if (element.isMany()) { + DataType logical = new DataTypeImpl<XMLType>(dataBinding, Object.class, new XMLType(element)); + type = new DataTypeImpl<DataType>("java:array", Object[].class, logical); + } else { + type = new DataTypeImpl<XMLType>(dataBinding, Object.class, new XMLType(element)); + } + return type; + } + + /** + * @return the unwrappedOutputType + */ + public DataType getUnwrappedOutputType() { + if (unwrappedOutputType == null) { + List<ElementInfo> elements = getOutputChildElements(); + if (elements != null && elements.size() > 0) { + if (elements.size() > 1) { + // We don't support output with multiple parts + // throw new IllegalArgumentException("Multi-part output is not supported"); + } + ElementInfo element = elements.get(0); + + unwrappedOutputType = getDataType(element); + } + } + return unwrappedOutputType; + } + + public Class<?> getInputWrapperClass() { + return inputWrapperType == null ? null : inputWrapperType.getPhysical(); + } + + public Class<?> getOutputWrapperClass() { + return outputWrapperType == null ? null : outputWrapperType.getPhysical(); + } + + public String getDataBinding() { + return dataBinding; + } + + public void setDataBinding(String dataBinding) { + this.dataBinding = dataBinding; + } + + public DataType<XMLType> getInputWrapperType() { + return inputWrapperType; + } + + public void setInputWrapperType(DataType<XMLType> inputWrapperType) { + this.inputWrapperType = inputWrapperType; + } + + public DataType<XMLType> getOutputWrapperType() { + return outputWrapperType; + } + + public void setOutputWrapperType(DataType<XMLType> outputWrapperType) { + this.outputWrapperType = outputWrapperType; + } +} diff --git a/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/XMLType.java b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/XMLType.java new file mode 100644 index 0000000000..26ecf6e352 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/util/XMLType.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.util; + +import javax.xml.namespace.QName; + +/** + * The metadata for an XML element or type. + * + * @version $Rev$ $Date$ + */ +public class XMLType { + public static final XMLType UNKNOWN = new XMLType(null, null); + protected QName element; + protected QName type; + protected boolean nillable = true; + protected boolean many = false; + + /** + * @param element + */ + public XMLType(ElementInfo element) { + super(); + this.element = element.getQName(); + if (element.getType() != null) { + this.type = element.getType().getQName(); + } + } + + /** + * @param element + */ + public XMLType(TypeInfo type) { + this.element = null; + this.type = type.getQName(); + } + + public XMLType(QName element, QName type) { + this.element = element; + this.type = type; + } + + /** + * @return the type + */ + public QName getTypeName() { + return type; + } + + public boolean isElement() { + return element != null; + } + + public QName getElementName() { + return element; + } + + public void setElementName(QName element) { + this.element = element; + } + + public void setTypeName(QName type) { + this.type = type; + } + + public static XMLType getType(QName type) { + return new XMLType(null, type); + } + + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ((element == null) ? 0 : element.hashCode()); + result = PRIME * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final XMLType other = (XMLType)obj; + if (element == null) { + if (other.element != null) { + return false; + } + } else if (!element.equals(other.element)) { + return false; + } + if (type == null) { + if (other.type != null) { + return false; + } + } else if (!type.equals(other.type)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "Element: " + element + " Type: " + type; + } + + public boolean isNillable() { + return nillable; + } + + public void setNillable(boolean niable) { + this.nillable = niable; + } + + public boolean isMany() { + return many; + } + + public void setMany(boolean many) { + this.many = many; + } + +} diff --git a/branches/trunk-20080910/modules/interface/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.InterfaceContractMapper b/branches/trunk-20080910/modules/interface/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.InterfaceContractMapper new file mode 100644 index 0000000000..821c58bde1 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.InterfaceContractMapper @@ -0,0 +1,18 @@ +# 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.
+
+org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl
diff --git a/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/ContractCompatibilityTestCase.java b/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/ContractCompatibilityTestCase.java new file mode 100644 index 0000000000..269a3dc038 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/ContractCompatibilityTestCase.java @@ -0,0 +1,380 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.interfacedef.impl; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.IncompatibleInterfaceContractException; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * TODO some tests commented out due to DataType.equals() needing to be strict + * + * @version $Rev$ $Date$ + */ +public class ContractCompatibilityTestCase extends TestCase { + + private InterfaceContractMapper mapper; + + @Override + protected void setUp() throws Exception { + ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry(); + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + mapper = utilities.getUtility(InterfaceContractMapper.class); + } + + public void testNoOperation() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + InterfaceContract target = new MockContract("FooContract"); + mapper.checkCompatibility(source, target, false, false); + } + + public void testBasic() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + Operation opSource1 = newOperation("op1"); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + InterfaceContract target = new MockContract("FooContract"); + Operation opSource2 = newOperation("op1"); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opSource2); + target.getInterface().getOperations().addAll(targetOperations.values()); + mapper.checkCompatibility(source, target, false, false); + } + + public void testBasicIncompatibleOperationNames() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + Operation opSource1 = newOperation("op1"); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + InterfaceContract target = new MockContract("FooContract"); + Operation opSource2 = newOperation("op2"); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op2", opSource2); + target.getInterface().getOperations().addAll(targetOperations.values()); + try { + mapper.checkCompatibility(source, target, false, false); + fail(); + } catch (IncompatibleInterfaceContractException e) { + // expected + } + } + + public void testInputTypes() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + List<DataType> sourceInputTypes = new ArrayList<DataType>(); + sourceInputTypes.add(new DataTypeImpl<Type>(Object.class, Object.class)); + DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(String.class, sourceInputTypes); + Operation opSource1 = newOperation("op1"); + opSource1.setInputType(inputType); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + List<DataType> targetInputTypes = new ArrayList<DataType>(); + targetInputTypes.add(new DataTypeImpl<Type>(Object.class, Object.class)); + DataType<List<DataType>> targetInputType = new DataTypeImpl<List<DataType>>(String.class, targetInputTypes); + + Operation opTarget = newOperation("op1"); + opTarget.setInputType(targetInputType); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + mapper.checkCompatibility(source, target, false, false); + } + + public void testIncompatibleInputTypes() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + List<DataType> sourceInputTypes = new ArrayList<DataType>(); + sourceInputTypes.add(new DataTypeImpl<Type>(Integer.class, Integer.class)); + DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(String.class, sourceInputTypes); + Operation opSource1 = newOperation("op1"); + opSource1.setInputType(inputType); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + List<DataType> targetInputTypes = new ArrayList<DataType>(); + targetInputTypes.add(new DataTypeImpl<Type>(String.class, String.class)); + DataType<List<DataType>> targetInputType = new DataTypeImpl<List<DataType>>(String.class, targetInputTypes); + + Operation opTarget = newOperation("op1"); + opTarget.setInputType(targetInputType); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + try { + mapper.checkCompatibility(source, target, false, false); + fail(); + } catch (IncompatibleInterfaceContractException e) { + // expected + } + } + + /** + * Verfies source input types can be super types of the target + */ + public void testSourceSuperTypeInputCompatibility() throws Exception { + // InterfaceContract source = new MockContract("FooContract"); + // List<DataType> sourceInputTypes = new ArrayList<DataType>(); + // sourceInputTypes.add(new DataTypeImpl<Type>(Object.class, + // Object.class)); + // DataType<List<DataType>> inputType = new + // DataTypeImpl<List<DataType>>(String.class, sourceInputTypes); + // Operation opSource1 = newOperationImpl("op1", inputType, null, null, + // false, null); + // Map<String, Operation> sourceOperations = new HashMap<String, + // Operation>(); + // sourceOperations.put("op1", opSource1); + // source.getInterface().getOperations().addAll(sourceOperations.values()); + // + // InterfaceContract target = new MockContract("FooContract"); + // List<DataType> targetInputTypes = new ArrayList<DataType>(); + // targetInputTypes.add(new DataTypeImpl<Type>(String.class, + // String.class)); + // DataType<List<DataType>> targetInputType = + // new DataTypeImpl<List<DataType>>(String.class, targetInputTypes); + // + // Operation opTarget = newOperationImpl("op1", targetInputType, null, + // null, false, null); + // Map<String, Operation> targetOperations = new HashMap<String, + // Operation>(); + // targetOperations.put("op1", opTarget); + // target.getInterface().getOperations().addAll(targetOperations.values()); + // wireService.checkCompatibility(source, target, false); + } + + public void testOutputTypes() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + DataType sourceOutputType = new DataTypeImpl<Type>(String.class, String.class); + Operation opSource1 = newOperation("op1"); + opSource1.setOutputType(sourceOutputType); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + DataType targetOutputType = new DataTypeImpl<Type>(String.class, String.class); + Operation opTarget = newOperation("op1"); + opTarget.setOutputType(targetOutputType); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + mapper.checkCompatibility(source, target, false, false); + } + + /** + * Verifies a return type that is a supertype of of the target is compatible + */ + public void testSupertypeOutputTypes() throws Exception { + // InterfaceContract source = new MockContract("FooContract"); + // DataType sourceOutputType = new DataTypeImpl<Type>(Object.class, + // Object.class); + // Operation opSource1 = newOperationImpl("op1", null, + // sourceOutputType, null, false, null); + // Map<String, Operation> sourceOperations = new HashMap<String, + // Operation>(); + // sourceOperations.put("op1", opSource1); + // source.getInterface().getOperations().addAll(sourceOperations.values()); + // + // InterfaceContract target = new MockContract("FooContract"); + // DataType targetOutputType = new DataTypeImpl<Type>(String.class, + // String.class); + // Operation opTarget = newOperationImpl("op1", null, targetOutputType, + // null, false, null); + // Map<String, Operation> targetOperations = new HashMap<String, + // Operation>(); + // targetOperations.put("op1", opTarget); + // target.getInterface().getOperations().addAll(targetOperations.values()); + // wireService.checkCompatibility(source, target, false); + } + + public void testIncompatibleOutputTypes() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + DataType sourceOutputType = new DataTypeImpl<Type>(String.class, String.class); + Operation opSource1 = newOperation("op1"); + opSource1.setOutputType(sourceOutputType); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + DataType targetOutputType = new DataTypeImpl<Type>(Integer.class, Integer.class); + Operation opTarget = newOperation("op1"); + opTarget.setOutputType(targetOutputType); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + try { + mapper.checkCompatibility(source, target, false, false); + fail(); + } catch (IncompatibleInterfaceContractException e) { + // expected + } + } + + public void testFaultTypes() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + DataType sourceFaultType = new DataTypeImpl<Type>(String.class, String.class); + List<DataType> sourceFaultTypes = new ArrayList<DataType>(); + sourceFaultTypes.add(0, sourceFaultType); + Operation opSource1 = newOperation("op1"); + opSource1.setFaultTypes(sourceFaultTypes); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + DataType targetFaultType = new DataTypeImpl<Type>(String.class, String.class); + List<DataType> targetFaultTypes = new ArrayList<DataType>(); + targetFaultTypes.add(0, targetFaultType); + + Operation opTarget = newOperation("op1"); + opTarget.setFaultTypes(targetFaultTypes); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + mapper.checkCompatibility(source, target, false, false); + } + + public void testSourceFaultTargetNoFaultCompatibility() throws Exception { + InterfaceContract source = new MockContract("FooContract"); + DataType sourceFaultType = new DataTypeImpl<Type>(String.class, String.class); + List<DataType> sourceFaultTypes = new ArrayList<DataType>(); + sourceFaultTypes.add(0, sourceFaultType); + Operation opSource1 = newOperation("op1"); + opSource1.setFaultTypes(sourceFaultTypes); + Map<String, Operation> sourceOperations = new HashMap<String, Operation>(); + sourceOperations.put("op1", opSource1); + source.getInterface().getOperations().addAll(sourceOperations.values()); + + InterfaceContract target = new MockContract("FooContract"); + Operation opTarget = newOperation("op1"); + Map<String, Operation> targetOperations = new HashMap<String, Operation>(); + targetOperations.put("op1", opTarget); + target.getInterface().getOperations().addAll(targetOperations.values()); + mapper.checkCompatibility(source, target, false, false); + } + + /** + * Verifies a source's fault which is a supertype of the target's fault are + * compatible + * + * @throws Exception + */ + public void testFaultSuperTypes() throws Exception { + // InterfaceContract source = new MockContract("FooContract"); + // DataType sourceFaultType = new DataTypeImpl<Type>(Exception.class, + // Exception.class); + // List<DataType> sourceFaultTypes = new ArrayList<DataType>(); + // sourceFaultTypes.add(0, sourceFaultType); + // Operation opSource1 = newOperationImpl("op1", null, null, + // sourceFaultTypes, false, null); + // Map<String, Operation> sourceOperations = new HashMap<String, + // Operation>(); + // sourceOperations.put("op1", opSource1); + // source.getInterface().getOperations().addAll(sourceOperations.values()); + // + // InterfaceContract target = new MockContract("FooContract"); + // DataType targetFaultType = new + // DataTypeImpl<Type>(TuscanyException.class, TuscanyException.class); + // List<DataType> targetFaultTypes = new ArrayList<DataType>(); + // targetFaultTypes.add(0, targetFaultType); + // + // Operation opTarget = newOperationImpl("op1", null, null, + // targetFaultTypes, false, null); + // Map<String, Operation> targetOperations = new HashMap<String, + // Operation>(); + // targetOperations.put("op1", opTarget); + // target.getInterface().getOperations().addAll(targetOperations.values()); + // wireService.checkCompatibility(source, target, false); + } + + /** + * Verifies a source's faults which are supertypes and a superset of the + * target's faults are compatible + */ + public void testFaultSuperTypesAndSuperset() throws Exception { + // InterfaceContract source = new MockContract("FooContract"); + // DataType sourceFaultType = new DataTypeImpl<Type>(Exception.class, + // Exception.class); + // DataType sourceFaultType2 = new + // DataTypeImpl<Type>(RuntimeException.class, RuntimeException.class); + // List<DataType> sourceFaultTypes = new ArrayList<DataType>(); + // sourceFaultTypes.add(0, sourceFaultType); + // sourceFaultTypes.add(1, sourceFaultType2); + // Operation opSource1 = newOperationImpl("op1", null, null, + // sourceFaultTypes, false, null); + // Map<String, Operation> sourceOperations = new HashMap<String, + // Operation>(); + // sourceOperations.put("op1", opSource1); + // source.getInterface().getOperations().addAll(sourceOperations.values()); + // + // InterfaceContract target = new MockContract("FooContract"); + // DataType targetFaultType = new + // DataTypeImpl<Type>(TuscanyException.class, TuscanyException.class); + // List<DataType> targetFaultTypes = new ArrayList<DataType>(); + // targetFaultTypes.add(0, targetFaultType); + // + // Operation opTarget = newOperationImpl("op1", null, null, + // targetFaultTypes, false, null); + // Map<String, Operation> targetOperations = new HashMap<String, + // Operation>(); + // targetOperations.put("op1", opTarget); + // target.getInterface().getOperations().addAll(targetOperations.values()); + // wireService.checkCompatibility(source, target, false); + } + + private static class MockInterface extends InterfaceImpl { + + } + + private class MockContract<T> extends InterfaceContractImpl { + public MockContract() { + } + + public MockContract(String interfaceClass) { + Interface jInterface = new MockInterface(); + setInterface(jInterface); + } + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractTestCase.java b/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractTestCase.java new file mode 100644 index 0000000000..338170da52 --- /dev/null +++ b/branches/trunk-20080910/modules/interface/src/test/java/org/apache/tuscany/sca/interfacedef/impl/InterfaceContractTestCase.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.impl; + + +import junit.framework.Assert; + +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class InterfaceContractTestCase { + private InterfaceContract contract; + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + contract = new MockInterfaceContract(); + Interface i1 = new MockInterface(); + contract.setInterface(i1); + Operation op1 = newOperation("op1"); + i1.getOperations().add(op1); + Interface i2 = new MockInterface(); + contract.setCallbackInterface(i2); + Operation callbackOp1 = newOperation("callbackOp1"); + i2.getOperations().add(callbackOp1); + } + + @Test + public void testClone() throws Exception { + InterfaceContract copy = (InterfaceContract) contract.clone(); + Assert.assertEquals(contract, copy); + } + + private static class MockInterfaceContract extends InterfaceContractImpl implements InterfaceContract { + } + + private static class MockInterface extends InterfaceImpl implements Interface { + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} |