diff options
Diffstat (limited to '')
4 files changed, 675 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/CodeGenerationHelper.java b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/CodeGenerationHelper.java new file mode 100644 index 0000000000..9fffd93dca --- /dev/null +++ b/sca-java-2.x/tags/2.0-M5.1/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: 673298 $ $Date: 2008-07-01 23:47:40 -0700 (Tue, 01 Jul 2008) $ + */ +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/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.java b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.java new file mode 100644 index 0000000000..b679f34835 --- /dev/null +++ b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/GeneratedClassLoader.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.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<String, GeneratedClass> generatedClasses = new HashMap<String, GeneratedClass>(); + + 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(); + } +} diff --git a/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.java new file mode 100644 index 0000000000..71683ba2c4 --- /dev/null +++ b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/JAXRSJavaInterfaceProcessor.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.jaxrs; + +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<String, Class<?>> mapping = new HashMap<String, Class<?>>(); + 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; + HttpMethod httpMethod = method.getAnnotation(HttpMethod.class); + if (httpMethod != null) { + methodName = httpMethod.value(); + } + if (method.isAnnotationPresent(GET.class)) { + methodName = HttpMethod.GET; + } else if (method.isAnnotationPresent(POST.class)) { + methodName = HttpMethod.POST; + } else if (method.isAnnotationPresent(PUT.class)) { + methodName = HttpMethod.PUT; + } else if (method.isAnnotationPresent(DELETE.class)) { + methodName = HttpMethod.DELETE; + } else if (method.isAnnotationPresent(HEAD.class)) { + methodName = HttpMethod.HEAD; + } else if (method.isAnnotationPresent(OPTIONS.class)) { + methodName = HttpMethod.OPTIONS; + } + + boolean jaxrs = false; + Class<?> type = mapping.get(methodName); + if (type != null) { + jaxrs = true; + operation.getAttributes().put(type, Boolean.TRUE); + Map<Object, Object> attrs = operation.getInterface().getAttributes(); + List<Operation> operations = (List<Operation>)attrs.get(type); + if (operations == null) { + operations = new ArrayList<Operation>(); + 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/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java new file mode 100644 index 0000000000..969efeb4f1 --- /dev/null +++ b/sca-java-2.x/tags/2.0-M5.1/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.interfacedef.java.jaxrs; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; + +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"; + + 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 <ReturnType> method(<Type0> arg0, ..., <TypeN> argN) throws <ExpectionType0>, ..., <ExceptionTypeK> + 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, "<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", getSignature(className), null, l0, l1, 0); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + // public static <Interface> 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 _<Interface>Impl implements <Interface> + 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(<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(<contentTypes>) + // @Provides(<contentTypes>) + 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(<contentTypes>) + // @Provides(<contentTypes>) + 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(); + } + } +} |