You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2012/09/18 16:34:42 UTC

svn commit: r1387188 - in /cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs: impl/ReaderInterceptorMBR.java impl/WriterInterceptorMBW.java interceptor/JAXRSOutInterceptor.java provider/ProviderFactory.java utils/JAXRSUtils.java

Author: sergeyb
Date: Tue Sep 18 14:34:41 2012
New Revision: 1387188

URL: http://svn.apache.org/viewvc?rev=1387188&view=rev
Log:
[CXF-4455] Initial support for calling reader amd writer interceptors on the server side

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WriterInterceptorMBW.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java?rev=1387188&r1=1387187&r2=1387188&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ReaderInterceptorMBR.java Tue Sep 18 14:34:41 2012
@@ -25,12 +25,21 @@ import javax.ws.rs.ext.MessageBodyReader
 import javax.ws.rs.ext.ReaderInterceptor;
 import javax.ws.rs.ext.ReaderInterceptorContext;
 
+import org.apache.cxf.message.Message;
+
 public class ReaderInterceptorMBR implements ReaderInterceptor {
 
     private MessageBodyReader<?> reader;
+    private Message m;
     
-    public ReaderInterceptorMBR(MessageBodyReader<?> reader) {
+    public ReaderInterceptorMBR(MessageBodyReader<?> reader,
+                                Message m) {
         this.reader = reader;
+        this.m = m;
+    }
+    
+    public MessageBodyReader<?> getMBR() {
+        return reader;
     }
     
     @SuppressWarnings({
@@ -40,7 +49,8 @@ public class ReaderInterceptorMBR implem
     public Object aroundReadFrom(ReaderInterceptorContext c) throws IOException, WebApplicationException {
         return reader.readFrom((Class)c.getType(), c.getGenericType(),
                                c.getAnnotations(), c.getMediaType(),
-                               c.getHeaders(), c.getInputStream());
+                               new HttpHeadersImpl(m).getRequestHeaders(),
+                               c.getInputStream());
     }
 
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WriterInterceptorMBW.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WriterInterceptorMBW.java?rev=1387188&r1=1387187&r2=1387188&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WriterInterceptorMBW.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/WriterInterceptorMBW.java Tue Sep 18 14:34:41 2012
@@ -19,22 +19,37 @@
 package org.apache.cxf.jaxrs.impl;
 
 import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.WriterInterceptor;
 import javax.ws.rs.ext.WriterInterceptorContext;
 
+import org.apache.cxf.common.logging.LogUtils;
+
 public class WriterInterceptorMBW implements WriterInterceptor {
 
+    private static final Logger LOG = LogUtils.getL7dLogger(WriterInterceptorMBW.class);
+    
     private MessageBodyWriter<Object> writer;
     
     public WriterInterceptorMBW(MessageBodyWriter<Object> writer) {
         this.writer = writer;
     }
 
+    public MessageBodyWriter<Object> getMBW() {
+        return writer;
+    }
+    
     @Override
     public void aroundWriteTo(WriterInterceptorContext c) throws IOException, WebApplicationException {
+        
+        if (LOG.isLoggable(Level.FINE)) {
+            LOG.fine("Response EntityProvider is: " + writer.getClass().getName());
+        }
+        
         writer.writeTo(c.getEntity(), 
                        c.getType(), 
                        c.getGenericType(), 

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java?rev=1387188&r1=1387187&r2=1387188&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/JAXRSOutInterceptor.java Tue Sep 18 14:34:41 2012
@@ -42,6 +42,8 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.WriterInterceptor;
+import javax.ws.rs.ext.WriterInterceptorContext;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.stream.events.XMLEvent;
 
@@ -52,6 +54,8 @@ import org.apache.cxf.interceptor.Abstra
 import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.jaxrs.ext.ResponseHandler;
 import org.apache.cxf.jaxrs.impl.MetadataMap;
+import org.apache.cxf.jaxrs.impl.WriterInterceptorContextImpl;
+import org.apache.cxf.jaxrs.impl.WriterInterceptorMBW;
 import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
@@ -224,26 +228,26 @@ public class JAXRSOutInterceptor extends
         
         Annotation[] annotations = invoked != null ? invoked.getAnnotations() : new Annotation[]{};
         
-        MessageBodyWriter<?> writer = null;
+        List<WriterInterceptor> writers = null;
         MediaType responseType = null;
         for (MediaType type : availableContentTypes) { 
-            writer = ProviderFactory.getInstance(message)
-                .createMessageBodyWriter(targetType, genericType, annotations, type, message);
+            writers = ProviderFactory.getInstance(message)
+                .createMessageBodyWriterInterceptor(targetType, genericType, annotations, type, message);
             
-            if (writer != null) {
+            if (writers != null) {
                 responseType = type;
                 break;
             }
         }
     
         OutputStream outOriginal = message.getContent(OutputStream.class);
-        if (writer == null) {
+        if (writers == null) {
             message.put(Message.CONTENT_TYPE, "text/plain");
             message.put(Message.RESPONSE_CODE, 500);
             writeResponseErrorMessage(outOriginal, "NO_MSG_WRITER", targetType.getSimpleName());
             return;
         }
-        boolean enabled = checkBufferingMode(message, writer, firstTry);
+        boolean enabled = checkBufferingMode(message, writers, firstTry);
         Object entity = getEntity(responseObj);
         try {
             responseType = checkFinalContentType(responseType);
@@ -252,21 +256,15 @@ public class JAXRSOutInterceptor extends
             }
             message.put(Message.CONTENT_TYPE, responseType.toString());
             
-            long size = getSize(writer, entity, targetType, genericType, annotations, responseType);
-            if (size > 0) {
-                LOG.fine("Setting ContentLength to " + size + " as requested by " 
-                         + writer.getClass().getName());
-                responseHeaders.putSingle(HttpHeaders.CONTENT_LENGTH, Long.toString(size));
-            }
-            if (LOG.isLoggable(Level.FINE)) {
-                LOG.fine("Response EntityProvider is: " + writer.getClass().getName());
-            }
             try {
-                writeTo(writer, entity, targetType, genericType, 
+                writeTo(writers, 
+                        entity, 
+                        targetType, 
+                        genericType, 
                         annotations, 
-                        responseType, 
-                        responseHeaders, 
-                        message.getContent(OutputStream.class));
+                        responseType,
+                        responseHeaders,
+                        message);
                 
                 if (isResponseRedirected(message)) {
                     return;
@@ -292,27 +290,33 @@ public class JAXRSOutInterceptor extends
     }
     
     //CHECKSTYLE:OFF
-    private static <T> void writeTo(MessageBodyWriter<?> mwriter, 
-                                    T entity,
-                                    Class<?> type, Type genericType,
-                                    Annotation[] annotations, 
-                                    MediaType mediaType,
-                                    MultivaluedMap<String, Object> httpHeaders, 
-                                    OutputStream entityStream) 
+    private static void writeTo(List<WriterInterceptor> writers, 
+                                Object entity,
+                                Class<?> type, Type genericType,
+                                Annotation[] annotations, 
+                                MediaType mediaType,
+                                MultivaluedMap<String, Object> httpHeaders,
+                                Message message) 
         throws WebApplicationException, IOException {
-        @SuppressWarnings("unchecked")
-        MessageBodyWriter<T> writer = (MessageBodyWriter<T>)mwriter;
-        writer.writeTo(entity, type, genericType, annotations, mediaType,
+        
+        OutputStream entityStream = message.getContent(OutputStream.class);
+        if (writers.size() > 1) {
+            WriterInterceptor first = writers.remove(0);
+            WriterInterceptorContext context = new WriterInterceptorContextImpl(entity,
+                                                                                type, 
+                                                                            genericType, 
+                                                                            annotations, 
+                                                                            mediaType,
+                                                                            entityStream,
+                                                                            message,
+                                                                            writers);
+            
+            first.aroundWriteTo(context);
+        } else {
+            MessageBodyWriter<Object> writer = ((WriterInterceptorMBW)writers.get(0)).getMBW();
+            writer.writeTo(entity, type, genericType, annotations, mediaType,
                            httpHeaders, entityStream);
-    }
-
-    private static <T> long getSize(MessageBodyWriter<?> mwriter, T entity, 
-                                    Class<?> targetType, 
-                                    Type genericType,
-                                    Annotation[] annotations, MediaType responseType) {
-        @SuppressWarnings("unchecked")
-        MessageBodyWriter<T> writer = (MessageBodyWriter<T>)mwriter;
-        return writer.getSize(entity, targetType, genericType, annotations, responseType);
+        }
     }
     //CHECKSTYLE:ON
 
@@ -325,10 +329,12 @@ public class JAXRSOutInterceptor extends
         return GenericEntity.class.isAssignableFrom(o.getClass()) ? ((GenericEntity<?>)o).getEntity() : o; 
     }
     
-    private boolean checkBufferingMode(Message m, MessageBodyWriter<?> w, boolean firstTry) {
+    private boolean checkBufferingMode(Message m, List<WriterInterceptor> writers, boolean firstTry) {
         if (!firstTry) {
             return false;
         }
+        WriterInterceptor last = writers.get(writers.size() - 1);
+        MessageBodyWriter<Object> w = ((WriterInterceptorMBW)last).getMBW();
         Object outBuf = m.getContextualProperty(OUT_BUFFERING);
         boolean enabled = MessageUtils.isTrue(outBuf);
         boolean configurableProvider = w instanceof AbstractConfigurableProvider;

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=1387188&r1=1387187&r2=1387188&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ProviderFactory.java Tue Sep 18 14:34:41 2012
@@ -456,7 +456,7 @@ public final class ProviderFactory {
                                                       mediaType,
                                                       m);
         if (mr != null) {
-            ReaderInterceptor mbrReader = new ReaderInterceptorMBR(mr);
+            ReaderInterceptor mbrReader = new ReaderInterceptorMBR(mr, m);
             
             int size = readerInterceptors.size();
             List<ReaderInterceptor> interceptors = null;

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java?rev=1387188&r1=1387187&r2=1387188&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java Tue Sep 18 14:34:41 2012
@@ -82,6 +82,8 @@ import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Providers;
+import javax.ws.rs.ext.ReaderInterceptor;
+import javax.ws.rs.ext.ReaderInterceptorContext;
 import javax.xml.namespace.QName;
 
 import org.apache.cxf.common.i18n.BundleUtils;
@@ -102,6 +104,8 @@ import org.apache.cxf.jaxrs.impl.HttpSer
 import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
 import org.apache.cxf.jaxrs.impl.ProvidersImpl;
+import org.apache.cxf.jaxrs.impl.ReaderInterceptorContextImpl;
+import org.apache.cxf.jaxrs.impl.ReaderInterceptorMBR;
 import org.apache.cxf.jaxrs.impl.RequestImpl;
 import org.apache.cxf.jaxrs.impl.SecurityContextImpl;
 import org.apache.cxf.jaxrs.impl.UriInfoImpl;
@@ -1047,7 +1051,7 @@ public final class JAXRSUtils {
         }
     }
 
-    private static <T> T readFromMessageBody(Class<T> targetTypeClass,
+    private static Object readFromMessageBody(Class<?> targetTypeClass,
                                                   Type parameterType,
                                                   Annotation[] parameterAnnotations,
                                                   InputStream is, 
@@ -1057,20 +1061,23 @@ public final class JAXRSUtils {
         
         List<MediaType> types = JAXRSUtils.intersectMimeTypes(consumeTypes, contentType);
         
-        MessageBodyReader<T> provider = null;
+        final ProviderFactory pf = ProviderFactory.getInstance(m);
         for (MediaType type : types) { 
-            provider = ProviderFactory.getInstance(m)
-                .createMessageBodyReader(targetTypeClass,
+            List<ReaderInterceptor> readers = pf.createMessageBodyReaderInterceptor(
+                                         targetTypeClass,
                                          parameterType,
                                          parameterAnnotations,
                                          type,
                                          m);
-            if (provider != null) {
+            if (readers != null) {
                 try {
-                    HttpHeaders headers = new HttpHeadersImpl(m);
-                    return provider.readFrom(
-                              targetTypeClass, parameterType, parameterAnnotations, contentType,
-                              headers.getRequestHeaders(), is);
+                    return readFromMessageBodyReader(readers, 
+                                                     targetTypeClass, 
+                                                     parameterType, 
+                                                     parameterAnnotations, 
+                                                     is, 
+                                                     type,
+                                                     m);    
                 } catch (IOException e) {
                     throw e;
                 } catch (WebApplicationException ex) {
@@ -1090,6 +1097,37 @@ public final class JAXRSUtils {
 
         return null;
     }
+    
+    @SuppressWarnings("unchecked")
+    public static Object readFromMessageBodyReader(List<ReaderInterceptor> readers,
+                                                   Class<?> targetTypeClass,
+                                                   Type parameterType,
+                                                   Annotation[] parameterAnnotations,
+                                                   InputStream is, 
+                                                   MediaType mediaType, 
+                                                   Message m) throws IOException, WebApplicationException {
+        
+        // Verbose but avoids an extra context instantiation for the typical path
+        if (readers.size() > 1) {
+            ReaderInterceptor first = readers.remove(0);
+            ReaderInterceptorContext context = new ReaderInterceptorContextImpl(targetTypeClass, 
+                                                                            parameterType, 
+                                                                            parameterAnnotations, 
+                                                                            mediaType,
+                                                                            is,
+                                                                            m,
+                                                                            readers);
+            
+            return first.aroundReadFrom(context);
+        } else {
+            MessageBodyReader<?> provider = ((ReaderInterceptorMBR)readers.get(0)).getMBR();
+            @SuppressWarnings("rawtypes")
+            Class cls = (Class)targetTypeClass;
+            return provider.readFrom(
+                      cls, parameterType, parameterAnnotations, mediaType,
+                      new HttpHeadersImpl(m).getRequestHeaders(), is);
+        }
+    }