From c791fd804344b8719fb69be84b8174c84cc4f4dc Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Mon, 10 Jan 2011 19:51:07 +0000 Subject: Sandbox to experiment with Databinding automatic wrapper transformations. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1057335 13f79535-47bb-0310-9956-ffa450edef68 --- .../wrapped/modules/interface-java-jaxrs/LICENSE | 205 +++++++++++++++ .../interface-java-jaxrs/META-INF/MANIFEST.MF | 18 ++ .../wrapped/modules/interface-java-jaxrs/NOTICE | 6 + .../wrapped/modules/interface-java-jaxrs/pom.xml | 60 +++++ .../java/jaxrs/CodeGenerationHelper.java | 280 +++++++++++++++++++++ .../java/jaxrs/GeneratedClassLoader.java | 86 +++++++ .../java/jaxrs/JAXRSJavaInterfaceProcessor.java | 116 +++++++++ .../java/jaxrs/RootResourceClassGenerator.java | 210 ++++++++++++++++ ...terfacedef.java.introspect.JavaInterfaceVisitor | 17 ++ .../tuscany/sca/interfacedef/java/jaxrs/Bean.java | 31 +++ .../jaxrs/JAXRSInterfaceProcessorTestCase.java | 66 +++++ .../interfacedef/java/jaxrs/MockedResource.java | 44 ++++ .../sca/interfacedef/java/jaxrs/Resource.java | 44 ++++ .../interfacedef/java/jaxrs/ResourceWrapper.java | 54 ++++ .../jaxrs/RootResourceClassGeneratorTestCase.java | 69 +++++ 15 files changed, 1306 insertions(+) create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/LICENSE create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/META-INF/MANIFEST.MF create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/NOTICE create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/pom.xml create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/CodeGenerationHelper.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Bean.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSInterfaceProcessorTestCase.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/MockedResource.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Resource.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/ResourceWrapper.java create mode 100644 sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGeneratorTestCase.java (limited to 'sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs') diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/LICENSE b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/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/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/META-INF/MANIFEST.MF b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..f45e70ad23 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Export-Package: org.apache.tuscany.sca.interfacedef.java.jaxrs;version="2.0.0" +SCA-Version: 1.1 +Bundle-Name: Apache Tuscany Java Interface for JAX-RS +Bundle-Vendor: The Apache Software Foundation +Bundle-Version: 2.0.0 +Bundle-ManifestVersion: 2 +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-Description: Apache Tuscany Java Interface for JAXWS +Bundle-SymbolicName: org.apache.tuscany.sca.interface.java.jaxrs +Bundle-DocURL: http://www.apache.org/ +Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 +Import-Package: javax.ws.rs, + org.apache.tuscany.sca.interfacedef, + org.apache.tuscany.sca.interfacedef.java, + org.apache.tuscany.sca.interfacedef.java.impl, + org.apache.tuscany.sca.interfacedef.java.introspect, + org.objectweb.asm;version="3.1.0" diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/NOTICE b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/NOTICE new file mode 100644 index 0000000000..d69e595698 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/pom.xml b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/pom.xml new file mode 100644 index 0000000000..a04547f4e5 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/pom.xml @@ -0,0 +1,60 @@ + + + + 4.0.0 + + org.apache.tuscany.sca + tuscany-modules + 2.0-SNAPSHOT + ../pom.xml + + tuscany-interface-java-jaxrs + Apache Tuscany SCA Interface Java For JAX_RS + + + + javax.ws.rs + jsr311-api + 1.1.1 + + + + org.apache.tuscany.sca + tuscany-core-runtime-pom + pom + provided + 2.0-SNAPSHOT + + + + junit + junit + 4.8.1 + test + + + asm + asm + 3.1 + jar + provided + + + diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/CodeGenerationHelper.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/CodeGenerationHelper.java new file mode 100644 index 0000000000..e1891e6c0b --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/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.jaxrs; + +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 List> resovleTypeArguments(Class baseClass, Class childClass) { + Map resolvedTypes = new HashMap(); + 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> typeArgumentsAsClasses = new ArrayList>(); + // 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/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.java new file mode 100644 index 0000000000..5d296dfe12 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.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.java.jaxrs; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.HashMap; +import java.util.Map; + +public class GeneratedClassLoader extends URLClassLoader { + 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 generatedClasses = new HashMap(); + + public GeneratedClassLoader(ClassLoader parentLoader) { + super(new URL[0], 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(); + } + + @Override + public String toString() { + if( getParent() != null ) { + return "java.net.URLClassLoader:\n" + + "hashcode: " + hashCode() + "\n" + + "URLs: " + java.util.Arrays.asList( + getURLs() ) + "\n" + + "parent { " + getParent() + " }\n"; + } else { + return "java.net.URLClassLoader:\n" + + "hashcode: " + hashCode() + "\n" + + "URLs: " + java.util.Arrays.asList( + getURLs() ) + "\n"; + } + } +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java new file mode 100644 index 0000000000..83f88c98cb --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java @@ -0,0 +1,116 @@ +/* + * 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.jaxrs; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.OPTIONS; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; + +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; + +public class JAXRSJavaInterfaceProcessor implements JavaInterfaceVisitor { + private static Map> mapping = new HashMap>(); + static { + mapping.put(HttpMethod.GET, GET.class); + mapping.put(HttpMethod.POST, POST.class); + mapping.put(HttpMethod.PUT, PUT.class); + mapping.put(HttpMethod.DELETE, DELETE.class); + mapping.put(HttpMethod.HEAD, HEAD.class); + mapping.put(HttpMethod.OPTIONS, OPTIONS.class); + } + + private boolean introspectHTTPMethod(JavaOperation operation) { + Method method = operation.getJavaMethod(); + + String methodName = null; + + /** + * A request method designator is a runtime annotation that is annotated with the @HttpMethod annotation. + * JAX-RS defines a set of request method designators for the common HTTP methods: @GET, @POST, @PUT, + * @DELETE, @HEAD. Users may define their own custom request method designators including alternate + * designators for the common HTTP methods. + */ + for (Annotation a : method.getAnnotations()) { + Class annotationType = a.annotationType(); + if (annotationType == HttpMethod.class) { + methodName = ((HttpMethod)a).value(); + break; + } + // Http method related annotations such as @GET, @POST will have itself annotated with + // @HttpMethod + HttpMethod m = a.annotationType().getAnnotation(HttpMethod.class); + if (m != null) { + methodName = m.value(); + break; + } + } + + boolean jaxrs = false; + Class type = mapping.get(methodName); + if (type != null) { + jaxrs = true; + operation.getAttributes().put(type, Boolean.TRUE); + Map attrs = operation.getInterface().getAttributes(); + List operations = (List)attrs.get(type); + if (operations == null) { + operations = new ArrayList(); + attrs.put(type, operations); + operations.add(operation); + } else { + operations.add(operation); + } + } + + return jaxrs; + + } + + public void visitInterface(JavaInterface contract) throws InvalidInterfaceException { + + boolean hasJAXRSAnnotarions = false; + + for (Operation op : contract.getOperations()) { + final JavaOperation operation = (JavaOperation)op; + if (introspectHTTPMethod(operation)) { + hasJAXRSAnnotarions = true; + } + } + + // Always set JAX-RS annotated interfaces as remotables + if (hasJAXRSAnnotarions) { + contract.setRemotable(true); + } + } +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java new file mode 100644 index 0000000000..c3d1ec4421 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java @@ -0,0 +1,210 @@ +/* + * 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.jaxrs; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +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; +import org.objectweb.asm.Type; + +public class RootResourceClassGenerator implements Opcodes { + + private static final String DELEGATE_FIELD = "delegate"; + + public static Class generateRootResourceClass(Class interfaze, String path, String consumes, String produces) + throws Exception { + if (!interfaze.isInterface()) { + throw new IllegalArgumentException(interfaze + " is not an interface."); + } + GeneratedClassLoader classLoader = new GeneratedClassLoader(interfaze.getClassLoader()); + String interfaceName = interfaze.getName(); + int index = interfaze.getName().lastIndexOf('.'); + String className = + interfaceName.substring(0, index) + ".Generated" + interfaceName.substring(index + 1) + "Impl"; + + final byte[] content = generate(interfaze, path, consumes, produces); + Class cls = classLoader.getGeneratedClass(className, content); + return cls; + } + + public static void injectProxy(Class generatedResourceClass, Object proxy) throws Exception { + Field field = generatedResourceClass.getField("delegate"); + field.set(null, proxy); + } + + public static byte[] generate(Class interfaze, String path, String consumes, String produces) throws Exception { + String interfaceName = Type.getInternalName(interfaze); + int index = interfaceName.lastIndexOf('/'); + String className = + interfaceName.substring(0, index) + "/Generated" + interfaceName.substring(index + 1) + "Impl"; + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + + declareClass(cw, interfaceName, className); + + annotatePath(cw, path); + annotateContentTypes(cw, consumes, produces); + declareField(cw, interfaceName); + declareConstructor(cw, className); + + for (Method method : interfaze.getMethods()) { + if (!(method.getDeclaringClass() == Object.class)) { + generateMethod(cw, interfaceName, className, method, consumes, produces); + } + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + // public method( arg0, ..., argN) throws , ..., + private static void generateMethod(ClassWriter cw, + String interfaceName, + String className, + Method method, + String consumes, + String produces) { + String methodDescriptor = Type.getMethodDescriptor(method); + + MethodVisitor mv = + cw.visitMethod(ACC_PUBLIC, method.getName(), methodDescriptor, null, getExceptionInternalNames(method)); + + mv.visitCode(); + mv.visitFieldInsn(GETSTATIC, className, DELEGATE_FIELD, getSignature(interfaceName)); + Class[] paramTypes = method.getParameterTypes(); + for (int i = 0; i < paramTypes.length; i++) { + String signature = Type.getDescriptor(paramTypes[i]); + mv.visitVarInsn(CodeGenerationHelper.getLoadOPCode(signature), i + 1); + } + mv.visitMethodInsn(INVOKEINTERFACE, interfaceName, method.getName(), methodDescriptor); + + Class returnType = method.getReturnType(); + mv.visitInsn(CodeGenerationHelper.getReturnOPCode(Type.getDescriptor(returnType))); + int size = paramTypes.length + 1; + mv.visitMaxs(size, size); + mv.visitEnd(); + } + + private static String[] getExceptionInternalNames(Method method) { + Class[] types = method.getExceptionTypes(); + if (types.length == 0) { + return null; + } + String[] names = new String[types.length]; + for (int i = 0; i < types.length; i++) { + names[i] = Type.getInternalName(types[i]); + } + return names; + } + + private static String getSignature(String interfaceName) { + return "L" + interfaceName + ";"; + } + + private static void declareConstructor(ClassWriter cw, String className) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "", "()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", "", "()V"); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitLocalVariable("this", getSignature(className), null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + // public static delegate; + private static void declareField(ClassWriter cw, String interfaceName) { + FieldVisitor fv = + cw.visitField(ACC_PUBLIC + ACC_STATIC, DELEGATE_FIELD, getSignature(interfaceName), null, null); + fv.visitEnd(); + } + + // public class _Impl implements + private static void declareClass(ClassWriter cw, String interfaceName, String className) { + cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", new String[] {interfaceName}); + } + + // @Path() + private static void annotatePath(ClassWriter cw, String path) { + AnnotationVisitor av = cw.visitAnnotation("Ljavax/ws/rs/Path;", true); + av.visit("value", path); + av.visitEnd(); + } + + // @Consumes() + // @Provides() + private static void annotateContentTypes(ClassWriter cw, String consumes, String produces) { + AnnotationVisitor av = null; + if (consumes != null) { + av = cw.visitAnnotation("Ljavax/ws/rs/Consumes;", true); + AnnotationVisitor av1 = av.visitArray("value"); + for (String s : consumes.split("(,| )")) { + av1.visit(null, s.trim()); + } + av1.visitEnd(); + av.visitEnd(); + } + if (produces != null) { + av = cw.visitAnnotation("Ljavax/ws/rs/Produces;", true); + AnnotationVisitor av1 = av.visitArray("value"); + for (String s : produces.split("(,| )")) { + av1.visit(null, s.trim()); + } + av1.visitEnd(); + av.visitEnd(); + } + } + + // @Consumes() + // @Provides() + private static void annotateContentTypes(MethodVisitor mv, String consumes, String produces) { + AnnotationVisitor av = null; + if (consumes != null) { + av = mv.visitAnnotation("Ljavax/ws/rs/Consumes;", true); + AnnotationVisitor av1 = av.visitArray("value"); + for (String s : consumes.split("(,| )")) { + av1.visit(null, s.trim()); + } + av1.visitEnd(); + av.visitEnd(); + } + if (produces != null) { + av = mv.visitAnnotation("Ljavax/ws/rs/Produces;", true); + AnnotationVisitor av1 = av.visitArray("value"); + for (String s : produces.split("(,| )")) { + av1.visit(null, s.trim()); + } + av1.visitEnd(); + av.visitEnd(); + } + } +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor new file mode 100644 index 0000000000..9101d744b3 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor @@ -0,0 +1,17 @@ +# 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.jaxrs.JAXRSJavaInterfaceProcessor;ranking=100 diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Bean.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Bean.java new file mode 100644 index 0000000000..20a4276b8b --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Bean.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxrs; + +import javax.ws.rs.GET; + +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +public interface Bean { + + @GET + String[] get(); +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSInterfaceProcessorTestCase.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSInterfaceProcessorTestCase.java new file mode 100644 index 0000000000..b680eaa491 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSInterfaceProcessorTestCase.java @@ -0,0 +1,66 @@ +package org.apache.tuscany.sca.interfacedef.java.jaxrs; +/* + * 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. + */ + + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import javax.ws.rs.GET; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +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.junit.Before; +import org.junit.Test; + + +public class JAXRSInterfaceProcessorTestCase { + private ExtensionPointRegistry registry; + + @Before + public void setUp() throws Exception { + registry = new DefaultExtensionPointRegistry(); + } + + @Test + public final void testProcessor() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(registry); + JavaInterface contract = iFactory.createJavaInterface(Bean.class); + + assertTrue(contract.isRemotable()); + + Assert.assertEquals(1,contract.getOperations().size()); + + List getOperations = (List) contract.getAttributes().get(GET.class); + Assert.assertEquals(1,getOperations.size()); + + //list operation + System.out.println(">>> JAX-RS Operations"); + for(Operation o : contract.getOperations()) { + System.out.println(">>>>>>" + o); + } + + } +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/MockedResource.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/MockedResource.java new file mode 100644 index 0000000000..46d501d4be --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/MockedResource.java @@ -0,0 +1,44 @@ +/* + * 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.jaxrs; + +public class MockedResource implements Resource { + private String value; + + public MockedResource() { + super(); + } + + public String get() { + return value; + } + + public void create(String value) { + this.value = value; + } + + public void delete() { + value = null; + } + + public void update(String value) { + this.value = value; + } +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Resource.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Resource.java new file mode 100644 index 0000000000..ac9fd514bd --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/Resource.java @@ -0,0 +1,44 @@ +/* + * 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.jaxrs; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; + +import org.oasisopen.sca.annotation.Remotable; + +@Remotable +public interface Resource { + + @GET + String get(); + + @PUT + void update(String value); + + @POST + void create(String value); + + @DELETE + void delete(); + +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/ResourceWrapper.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/ResourceWrapper.java new file mode 100644 index 0000000000..23b674778e --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/ResourceWrapper.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.java.jaxrs; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + + +@Path("myURI") +@Produces({"application/xml", "application/json"}) +@Consumes({"application/xml", "application/json"}) +public class ResourceWrapper implements Resource { + public static Resource delegate; + + public ResourceWrapper() { + super(); + } + + + public String get() { + return delegate.get(); + } + + public void create(String value) { + delegate.create(value); + } + + public void delete() { + delegate.delete(); + } + + public void update(String value) { + delegate.update(value); + } + +} diff --git a/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGeneratorTestCase.java b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGeneratorTestCase.java new file mode 100644 index 0000000000..aa6abcd5f6 --- /dev/null +++ b/sandbox/sebastien/java/wrapped/modules/interface-java-jaxrs/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGeneratorTestCase.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.jaxrs; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +import org.junit.Assert; +import org.junit.Test; + +/** + * + */ +public class RootResourceClassGeneratorTestCase { + @Test + public void testGenerator() throws Exception { + Class cls = RootResourceClassGenerator.generateRootResourceClass(Resource.class, "myURI", "application/xml,application/json", "application/xml,application/json"); + Assert.assertTrue(cls.isAnnotationPresent(Path.class)); + Path path = cls.getAnnotation(Path.class); + Assert.assertEquals("myURI", path.value()); + + Produces produces = cls.getAnnotation(Produces.class); + Assert.assertEquals("application/xml", produces.value()[0]); + + Consumes consumes = cls.getAnnotation(Consumes.class); + Assert.assertEquals("application/json", consumes.value()[1]); + + Field field = cls.getField("delegate"); + Assert.assertSame(Resource.class, field.getType()); + + Assert.assertTrue(Modifier.isPublic(field.getModifiers())); + Assert.assertTrue(Modifier.isStatic(field.getModifiers())); + + Assert.assertTrue(Resource.class.isAssignableFrom(cls)); + + Resource resource = new MockedResource(); + field.set(null, resource); + + Resource resourceProxy = (Resource)cls.newInstance(); + Assert.assertNull(resourceProxy.get()); + resourceProxy.create("123"); + Assert.assertEquals("123", resourceProxy.get()); + resourceProxy.update("ABC"); + Assert.assertEquals("ABC", resourceProxy.get()); + resourceProxy.delete(); + Assert.assertNull(resourceProxy.get()); + } +} -- cgit v1.2.3