From 5b64dcc7be2bcd3f48922895ad963f36edb245db Mon Sep 17 00:00:00 2001 From: rfeng Date: Fri, 28 May 2010 06:17:24 +0000 Subject: Add a workaround for TUSCANY-3572 git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@949110 13f79535-47bb-0310-9956-ffa450edef68 --- .../rest/provider/DataBindingJAXRSProvider.java | 6 +- .../rest/provider/DataBindingJAXRSReader.java | 1 + .../rest/provider/DataBindingJAXRSWriter.java | 2 +- .../rest/provider/RESTServiceBindingProvider.java | 2 +- .../binding/rest/provider/TuscanyRESTServlet.java | 69 ++++++++++++++++------ .../java/services/store/FruitsCatalogImpl.java | 8 ++- .../java/jaxrs/RootResourceClassGenerator.java | 45 ++++++++++++-- 7 files changed, 104 insertions(+), 29 deletions(-) (limited to 'sca-java-2.x/trunk') diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSProvider.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSProvider.java index d7eeede240..1ccdb868d7 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSProvider.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSProvider.java @@ -90,8 +90,10 @@ public abstract class DataBindingJAXRSProvider { } protected boolean supports(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return MediaType.APPLICATION_JSON_TYPE.equals(mediaType) || MediaType.APPLICATION_XML_TYPE.equals(mediaType) - || MediaType.TEXT_XML_TYPE.equals(mediaType); + // Some media types have parameters + mediaType = new MediaType(mediaType.getType(), mediaType.getSubtype()); + return MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType) || MediaType.APPLICATION_XML_TYPE.isCompatible(mediaType) + || MediaType.TEXT_XML_TYPE.isCompatible(mediaType); } protected Object convert(InputStream content, String contentType, Class type) throws IOException { diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSReader.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSReader.java index 035af0aedf..d6df778feb 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSReader.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSReader.java @@ -62,6 +62,7 @@ public class DataBindingJAXRSReader extends DataBindingJAXRSProvider implemen String dataBinding = null; + mediaType = new MediaType(mediaType.getType(), mediaType.getSubtype()); // FIXME: [rfeng] This is a hack to handle application/json if (MediaType.APPLICATION_JSON_TYPE.equals(mediaType)) { dataBinding = mediaType.toString() + "#" + InputStream.class.getName(); diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java index 8503d089eb..740b685b22 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/DataBindingJAXRSWriter.java @@ -62,7 +62,7 @@ public class DataBindingJAXRSWriter extends DataBindingJAXRSProvider implemen MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { DataType dataType = createDataType(type, genericType); - + mediaType = new MediaType(mediaType.getType(), mediaType.getSubtype()); String dataBinding = OutputStream.class.getName(); // FIXME: [rfeng] This is a hack to handle application/json if (MediaType.APPLICATION_JSON_TYPE.equals(mediaType)) { diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/RESTServiceBindingProvider.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/RESTServiceBindingProvider.java index fdabb13ce5..b672c3ee2d 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/RESTServiceBindingProvider.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/RESTServiceBindingProvider.java @@ -221,7 +221,7 @@ public class RESTServiceBindingProvider implements EndpointProvider { if (isJAXRS) { application = new SimpleApplication(interfaze); - TuscanyRESTServlet restServlet = new TuscanyRESTServlet(extensionPoints); + TuscanyRESTServlet restServlet = new TuscanyRESTServlet(extensionPoints, application.resourceClass); // Create our HTTP service listener Servlet and register it with the // Servlet host diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/TuscanyRESTServlet.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/TuscanyRESTServlet.java index 3d561bf21f..13f13e4dde 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/TuscanyRESTServlet.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/main/java/org/apache/tuscany/sca/binding/rest/provider/TuscanyRESTServlet.java @@ -24,14 +24,15 @@ import java.util.Enumeration; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.HttpMethod; +import javax.ws.rs.core.MediaType; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.wink.common.internal.registry.ProvidersRegistry; +import org.apache.wink.common.internal.registry.metadata.MethodMetadata; import org.apache.wink.server.internal.DeploymentConfiguration; import org.apache.wink.server.internal.RequestProcessor; -import org.apache.wink.server.internal.handlers.ServerMessageContext; +import org.apache.wink.server.internal.registry.ResourceRecord; import org.apache.wink.server.internal.servlet.RestServlet; /** @@ -40,10 +41,13 @@ import org.apache.wink.server.internal.servlet.RestServlet; public class TuscanyRESTServlet extends RestServlet { private static final long serialVersionUID = 89997233133964915L; private ExtensionPointRegistry registry; + private Class resourceClass; + private boolean fixed; - public TuscanyRESTServlet(ExtensionPointRegistry registry) { + public TuscanyRESTServlet(ExtensionPointRegistry registry, Class resourceClass) { super(); this.registry = registry; + this.resourceClass = resourceClass; } @Override @@ -52,19 +56,19 @@ public class TuscanyRESTServlet extends RestServlet { DeploymentConfiguration config = super.getDeploymentConfiguration(); // [rfeng] FIXME: This is a hack to fool Apache wink to not remove the servlet path config.setFilterConfig(new FilterConfig() { - + public ServletContext getServletContext() { return getServletContext(); } - + public Enumeration getInitParameterNames() { return getInitParameterNames(); } - + public String getInitParameter(String arg0) { return getInitParameter(arg0); } - + public String getFilterName() { return getServletName(); } @@ -72,23 +76,50 @@ public class TuscanyRESTServlet extends RestServlet { ProvidersRegistry providers = config.getProvidersRegistry(); providers.addProvider(new DataBindingJAXRSReader(registry), 0.001, true); providers.addProvider(new DataBindingJAXRSWriter(registry), 0.001, true); + return config; } - @Override - public RequestProcessor getRequestProcessor() { - return super.getRequestProcessor(); + private synchronized void fixMediaTypes(DeploymentConfiguration config) { + if (fixed) { + return; + } + // FIXME: A hacky workaround for https://issues.apache.org/jira/browse/TUSCANY-3572 + ResourceRecord record = config.getResourceRegistry().getRecord(resourceClass); + + for (MethodMetadata methodMetadata : record.getMetadata().getResourceMethods()) { + String method = methodMetadata.getHttpMethod(); + if (HttpMethod.GET.equals(method) || HttpMethod.HEAD.equals(method) || HttpMethod.DELETE.equals(method)) { + methodMetadata.addConsumes(MediaType.APPLICATION_OCTET_STREAM_TYPE); + methodMetadata.addConsumes(MediaType.WILDCARD_TYPE); + } + if (HttpMethod.HEAD.equals(method) || HttpMethod.DELETE.equals(method)) { + methodMetadata.addProduces(MediaType.APPLICATION_OCTET_STREAM_TYPE); + methodMetadata.addConsumes(MediaType.WILDCARD_TYPE); + } + } + for (MethodMetadata methodMetadata : record.getMetadata().getSubResourceMethods()) { + String method = methodMetadata.getHttpMethod(); + if (HttpMethod.GET.equals(method) || HttpMethod.HEAD.equals(method) || HttpMethod.DELETE.equals(method)) { + methodMetadata.addConsumes(MediaType.APPLICATION_OCTET_STREAM_TYPE); + methodMetadata.addConsumes(MediaType.WILDCARD_TYPE); + } + if (HttpMethod.HEAD.equals(method) || HttpMethod.DELETE.equals(method)) { + methodMetadata.addProduces(MediaType.APPLICATION_OCTET_STREAM_TYPE); + methodMetadata.addConsumes(MediaType.WILDCARD_TYPE); + } + } + fixed = true; } - public ServerMessageContext createMessageContext(HttpServletRequest request, HttpServletResponse response) { - ServerMessageContext messageContext; - try { - messageContext = new ServerMessageContext(request, response, getDeploymentConfiguration()); - } catch (Exception e) { - throw new IllegalArgumentException(e); + @Override + public RequestProcessor getRequestProcessor() { + RequestProcessor processor = super.getRequestProcessor(); + // The 1st call returns null + if (processor != null) { + fixMediaTypes(processor.getConfiguration()); } - return messageContext; + return processor; } - } diff --git a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/test/java/services/store/FruitsCatalogImpl.java b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/test/java/services/store/FruitsCatalogImpl.java index 126b8e7d7a..498576117b 100644 --- a/sca-java-2.x/trunk/modules/binding-rest-runtime/src/test/java/services/store/FruitsCatalogImpl.java +++ b/sca-java-2.x/trunk/modules/binding-rest-runtime/src/test/java/services/store/FruitsCatalogImpl.java @@ -21,6 +21,7 @@ package services.store; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.oasisopen.sca.annotation.Init; @@ -49,7 +50,12 @@ public class FruitsCatalogImpl implements Catalog { public Items getItem() { Items items = new Items(); - items.setItems(new ArrayList(catalog.values())); + // Add by order so that we can test in the json array + List list = new ArrayList(); + list.add(catalog.get("Pear")); + list.add(catalog.get("Apple")); + list.add(catalog.get("Orange")); + items.setItems(list); return items; } diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java b/sca-java-2.x/trunk/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java index 0d23295986..969efeb4f1 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxrs/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxrs/RootResourceClassGenerator.java @@ -22,6 +22,10 @@ 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; @@ -34,7 +38,8 @@ 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 { + 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."); } @@ -48,7 +53,7 @@ public class RootResourceClassGenerator implements Opcodes { 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); @@ -71,7 +76,7 @@ public class RootResourceClassGenerator implements Opcodes { for (Method method : interfaze.getMethods()) { if (!(method.getDeclaringClass() == Object.class)) { - generateMethod(cw, interfaceName, className, method); + generateMethod(cw, interfaceName, className, method, consumes, produces); } } cw.visitEnd(); @@ -80,11 +85,17 @@ public class RootResourceClassGenerator implements Opcodes { } // public method( arg0, ..., argN) throws , ..., - private static void generateMethod(ClassWriter cw, String interfaceName, String className, Method method) { + 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(); @@ -152,7 +163,7 @@ public class RootResourceClassGenerator implements Opcodes { av.visit("value", path); av.visitEnd(); } - + // @Consumes() // @Provides() private static void annotateContentTypes(ClassWriter cw, String consumes, String produces) { @@ -176,4 +187,28 @@ public class RootResourceClassGenerator implements Opcodes { 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(); + } + } } -- cgit v1.2.3