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 2013/05/03 22:30:47 UTC

svn commit: r1478963 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/interceptor/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/main...

Author: sergeyb
Date: Fri May  3 20:30:47 2013
New Revision: 1478963

URL: http://svn.apache.org/r1478963
Log:
[CXF-5000] Uodating the way reader and writer interceptors are selected

Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.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/provider/ServerProviderFactory.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
    cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
    cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProviderFactory.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java Fri May  3 20:30:47 2013
@@ -315,7 +315,8 @@ public final class ResponseImpl extends 
             
             List<ReaderInterceptor> readers = ProviderFactory.getInstance(responseMessage)
                 .createMessageBodyReaderInterceptor(cls, t, anns, mediaType, 
-                                                    responseMessage.getExchange().getOutMessage());
+                                                    responseMessage.getExchange().getOutMessage(), 
+                                                    null);
             if (readers != null) {
                 try {
                     responseMessage.put(Message.PROTOCOL_HEADERS, this.getMetadata());

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=1478963&r1=1478962&r2=1478963&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 Fri May  3 20:30:47 2013
@@ -245,7 +245,8 @@ public class JAXRSOutInterceptor extends
         annotations = ((ResponseImpl)response).getEntityAnnotations();        
         
         List<WriterInterceptor> writers = providerFactory
-            .createMessageBodyWriterInterceptor(targetType, genericType, annotations, responseMediaType, message);
+            .createMessageBodyWriterInterceptor(targetType, genericType, annotations, responseMediaType, message,
+                                                ori == null ? null : ori.getNameBindings());
         
         OutputStream outOriginal = message.getContent(OutputStream.class);
         if (writers == null || writers.isEmpty()) {

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=1478963&r1=1478962&r2=1478963&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 Fri May  3 20:30:47 2013
@@ -31,6 +31,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -41,6 +42,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.MessageBodyReader;
@@ -58,6 +60,7 @@ import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.jaxrs.ext.ContextProvider;
 import org.apache.cxf.jaxrs.impl.HttpHeadersImpl;
+import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.ReaderInterceptorMBR;
 import org.apache.cxf.jaxrs.impl.WriterInterceptorMBW;
 import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
@@ -82,10 +85,10 @@ public abstract class ProviderFactory {
     private static final String JSON_PROVIDER_NAME = "org.apache.cxf.jaxrs.provider.json.JSONProvider";
     private static final String BUS_PROVIDERS_ALL = "org.apache.cxf.jaxrs.bus.providers";
     
-    protected List<ProviderInfo<ReaderInterceptor>> readerInterceptors = 
-        new ArrayList<ProviderInfo<ReaderInterceptor>>(1);
-    protected List<ProviderInfo<WriterInterceptor>> writerInterceptors = 
-        new ArrayList<ProviderInfo<WriterInterceptor>>(1);
+    protected Map<NameKey, ProviderInfo<ReaderInterceptor>> readerInterceptors = 
+        new LinkedHashMap<NameKey, ProviderInfo<ReaderInterceptor>>();
+    protected Map<NameKey, ProviderInfo<WriterInterceptor>> writerInterceptors = 
+        new LinkedHashMap<NameKey, ProviderInfo<WriterInterceptor>>();
     
     private List<ProviderInfo<MessageBodyReader<?>>> messageReaders = 
         new ArrayList<ProviderInfo<MessageBodyReader<?>>>();
@@ -317,7 +320,8 @@ public abstract class ProviderFactory {
                                                             Type parameterType,
                                                             Annotation[] parameterAnnotations,
                                                             MediaType mediaType,
-                                                            Message m) {
+                                                            Message m,
+                                                            List<String> names) {
         MessageBodyReader<T> mr = createMessageBodyReader(bodyType,
                                                       parameterType,
                                                       parameterAnnotations,
@@ -330,7 +334,9 @@ public abstract class ProviderFactory {
             List<ReaderInterceptor> interceptors = null;
             if (size > 0) {
                 interceptors = new ArrayList<ReaderInterceptor>(size + 1);
-                for (ProviderInfo<ReaderInterceptor> p : readerInterceptors) {
+                List<ProviderInfo<ReaderInterceptor>> readers =
+                    getPostMatchContainerFilters(readerInterceptors, names);
+                for (ProviderInfo<ReaderInterceptor> p : readers) {
                     InjectionUtils.injectContexts(p.getProvider(), p, m);
                     interceptors.add(p.getProvider());
                 }
@@ -349,7 +355,8 @@ public abstract class ProviderFactory {
                                                                           Type parameterType,
                                                                           Annotation[] parameterAnnotations,
                                                                           MediaType mediaType,
-                                                                          Message m) {
+                                                                          Message m,
+                                                                          List<String> names) {
         MessageBodyWriter<T> mw = createMessageBodyWriter(bodyType,
                                                       parameterType,
                                                       parameterAnnotations,
@@ -366,7 +373,9 @@ public abstract class ProviderFactory {
             List<WriterInterceptor> interceptors = null;
             if (size > 0) {
                 interceptors = new ArrayList<WriterInterceptor>(size + 1);
-                for (ProviderInfo<WriterInterceptor> p : writerInterceptors) {
+                List<ProviderInfo<WriterInterceptor>> writers =
+                    getPostMatchContainerFilters(writerInterceptors, names);
+                for (ProviderInfo<WriterInterceptor> p : writers) {
                     InjectionUtils.injectContexts(p.getProvider(), p, m);
                     interceptors.add(p.getProvider());
                 }
@@ -462,28 +471,16 @@ public abstract class ProviderFactory {
         }
     }
     
-    //CHECKSTYLE:OFF       
+    protected abstract void setProviders(Object... providers);
+    
     @SuppressWarnings("unchecked")
-    protected void setProviders(Object... providers) {
-        
-        for (Object o : providers) {
-            if (o == null) {
-                continue;
-            }
-            
-            ProviderInfo<? extends Object> provider = null;
-            Class<?> providerCls = null;
-            Object realObject = null;            
-            if (o instanceof ProviderInfo) {
-                provider = (ProviderInfo<? extends Object>)o;
-                providerCls = provider.getProvider().getClass();
-                realObject = provider;
-            } else {
-                providerCls = ClassHelper.getRealClass(o);
-                provider = new ProviderInfo<Object>(o, getBus());
-                realObject = o;
-            }
-            
+    protected void setCommonProviders(List<ProviderInfo<? extends Object>> theProviders) {
+        List<ProviderInfo<ReaderInterceptor>> readInts = 
+            new LinkedList<ProviderInfo<ReaderInterceptor>>();
+        List<ProviderInfo<WriterInterceptor>> writeInts = 
+            new LinkedList<ProviderInfo<WriterInterceptor>>();
+        for (ProviderInfo<? extends Object> provider : theProviders) {
+            Class<?> providerCls = ClassHelper.getRealClass(provider.getProvider());
             
             if (MessageBodyReader.class.isAssignableFrom(providerCls)) {
                 messageReaders.add((ProviderInfo<MessageBodyReader<?>>)provider); 
@@ -502,16 +499,16 @@ public abstract class ProviderFactory {
             }
             
             if (ReaderInterceptor.class.isAssignableFrom(providerCls)) {
-                readerInterceptors.add((ProviderInfo<ReaderInterceptor>)provider);
+                readInts.add((ProviderInfo<ReaderInterceptor>)provider);
             }
             
             if (WriterInterceptor.class.isAssignableFrom(providerCls)) {
-                writerInterceptors.add((ProviderInfo<WriterInterceptor>)provider);
+                writeInts.add((ProviderInfo<WriterInterceptor>)provider);
             }
             
             if (ParamConverterProvider.class.isAssignableFrom(providerCls)) {
                 //TODO: review the possibility of ParamConverterProvider needing to have Contexts injected
-                Object converter = realObject == provider ? provider.getProvider() : realObject;
+                Object converter = provider.getProvider();
                 newParamConverter = (ParamConverterProvider)converter;
             }
         }
@@ -519,13 +516,12 @@ public abstract class ProviderFactory {
         sortWriters();
         sortContextResolvers();
         
-        Collections.sort(readerInterceptors, new BindingPriorityComparator(true));
-        Collections.sort(writerInterceptors, new BindingPriorityComparator(false));
+        mapContainerFilters(readerInterceptors, readInts, true);
+        mapContainerFilters(writerInterceptors, writeInts, true);
         
         injectContextProxies(messageReaders, messageWriters, contextResolvers, 
-            readerInterceptors, writerInterceptors);
+            readerInterceptors.values(), writerInterceptors.values());
     }
-    //CHECKSTYLE:ON
     
     protected void injectContextValues(ProviderInfo<?> pi, Message m) {
         if (m != null) {
@@ -808,6 +804,8 @@ public abstract class ProviderFactory {
         messageWriters.clear();
         contextResolvers.clear();
         contextProviders.clear();
+        readerInterceptors.clear();
+        writerInterceptors.clear();
     }
     
     public void setBus(Bus bus) {
@@ -846,6 +844,35 @@ public abstract class ProviderFactory {
         }
     }
 
+    protected static <T> List<ProviderInfo<T>> getPostMatchContainerFilters(Map<NameKey, ProviderInfo<T>> boundFilters,
+                                                                          List<String> names) {
+        if (boundFilters.isEmpty()) {
+            return Collections.emptyList();
+        }
+        names = names == null ? Collections.<String>emptyList() : names;
+        
+        MultivaluedMap<ProviderInfo<T>, String> map = 
+            new MetadataMap<ProviderInfo<T>, String>();
+        for (Map.Entry<NameKey, ProviderInfo<T>> entry : boundFilters.entrySet()) {
+            String entryName = entry.getKey().getName();
+            if (entryName.equals(DEFAULT_FILTER_NAME_BINDING)) {
+                ProviderInfo<T> provider = entry.getValue(); 
+                map.put(provider, Collections.<String>emptyList());
+            } else {
+                map.add(entry.getValue(), entryName);
+            }
+        }
+        List<ProviderInfo<T>> list = new LinkedList<ProviderInfo<T>>();
+        for (Map.Entry<ProviderInfo<T>, List<String>> entry : map.entrySet()) {
+            List<String> values = entry.getValue();
+            if (names.containsAll(values)) {
+                ProviderInfo<T> provider = entry.getKey();
+                list.add(provider);
+            }
+        }
+        return list;
+    }
+    
     public void initProviders(List<ClassResourceInfo> cris) {
         Set<Object> set = getReadersWriters();
         for (Object o : set) {
@@ -972,7 +999,7 @@ public abstract class ProviderFactory {
         }
     }
     
-    protected ProviderInfo<Object> createProviderFromConstructor(Constructor<?> c, 
+    protected ProviderInfo<? extends Object> createProviderFromConstructor(Constructor<?> c, 
                                                                  Map<Class<?>, Object> values) {
         Object[] cArgs = ResourceUtils.createConstructorArguments(c, null, false, values);
         Object instance = null;
@@ -994,4 +1021,80 @@ public abstract class ProviderFactory {
         }
         return new ProviderInfo<Object>(instance, proxies, getBus()); 
     }
+    
+    protected static class NameKey { 
+        private String name;
+        private int bindingPriority;
+        public NameKey(String name, int priority) {
+            this.name = name;
+            this.bindingPriority = priority;
+        }
+        
+        public String getName() {
+            return name;
+        }
+        
+        public int getPriority() {
+            return bindingPriority;
+        }
+    }
+    
+    protected static <T> void mapContainerFilters(Map<NameKey, ProviderInfo<T>> map,
+                                                List<ProviderInfo<T>> postMatchFilters,
+                                                boolean ascending) {
+        
+        Collections.sort(postMatchFilters, new PostMatchFilterComparator(ascending));
+        for (ProviderInfo<T> p : postMatchFilters) { 
+            List<String> names = AnnotationUtils.getNameBindings(
+                p.getProvider().getClass().getAnnotations());
+            names = names.isEmpty() ? Collections.singletonList(DEFAULT_FILTER_NAME_BINDING) : names;
+            for (String name : names) {
+                map.put(new NameKey(name, AnnotationUtils.getBindingPriority(p.getProvider().getClass())), 
+                        p);
+            }
+        }
+        
+    }
+    
+    protected static class PostMatchFilterComparator extends BindingPriorityComparator {
+        public PostMatchFilterComparator(boolean ascending) {
+            super(ascending);
+        }
+        
+        @Override
+        public int compare(ProviderInfo<?> p1, ProviderInfo<?> p2) {
+            int result = super.compare(p1, p2);
+            if (result == 0) {
+                Integer namesSize1 = 
+                    AnnotationUtils.getNameBindings(p1.getProvider().getClass().getAnnotations()).size();
+                Integer namesSize2 = 
+                    AnnotationUtils.getNameBindings(p2.getProvider().getClass().getAnnotations()).size();
+                
+                // if we have two filters with the same binding priority, 
+                // then put a filter with more name bindings upfront 
+                // (this effectively puts name bound filters before global ones)
+                result = namesSize1.compareTo(namesSize2) * -1;
+            }
+            return result; 
+        }
+    }
+    
+    protected List<ProviderInfo<? extends Object>> prepareProviders(Object[] providers,
+        ProviderInfo<Application> application) {
+        List<ProviderInfo<? extends Object>> theProviders = 
+            new ArrayList<ProviderInfo<? extends Object>>(providers.length);
+        for (Object o : providers) {
+            if (o == null) {
+                continue;
+            }
+            if (o instanceof Constructor) {
+                Map<Class<?>, Object> values = CastUtils.cast(application == null ? null 
+                    : Collections.singletonMap(Application.class, application.getProvider()));
+                theProviders.add(createProviderFromConstructor((Constructor<?>)o, values));
+            } else {
+                theProviders.add(new ProviderInfo<Object>(o, getBus()));
+            }
+        }
+        return theProviders;
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ServerProviderFactory.java Fri May  3 20:30:47 2013
@@ -18,7 +18,6 @@
  */
 package org.apache.cxf.jaxrs.provider;
 
-import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -41,7 +40,6 @@ import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Configuration;
 import javax.ws.rs.core.Feature;
 import javax.ws.rs.core.FeatureContext;
-import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.ReaderInterceptor;
 import javax.ws.rs.ext.WriterInterceptor;
@@ -50,8 +48,6 @@ import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.common.util.ClassHelper;
 import org.apache.cxf.endpoint.Endpoint;
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.jaxrs.impl.MetadataMap;
 import org.apache.cxf.jaxrs.impl.RequestPreprocessor;
 import org.apache.cxf.jaxrs.impl.ResourceInfoImpl;
 import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper;
@@ -159,35 +155,6 @@ public final class ServerProviderFactory
                                             names);
     }
     
-    private static <T> List<ProviderInfo<T>> getPostMatchContainerFilters(Map<NameKey, ProviderInfo<T>> boundFilters,
-                                                                          List<String> names) {
-        if (boundFilters.isEmpty()) {
-            return Collections.emptyList();
-        }
-        names = names == null ? Collections.<String>emptyList() : names;
-        
-        MultivaluedMap<ProviderInfo<T>, String> map = 
-            new MetadataMap<ProviderInfo<T>, String>();
-        for (Map.Entry<NameKey, ProviderInfo<T>> entry : boundFilters.entrySet()) {
-            String entryName = entry.getKey().getName();
-            if (entryName.equals(DEFAULT_FILTER_NAME_BINDING)) {
-                ProviderInfo<T> provider = entry.getValue(); 
-                map.put(provider, Collections.<String>emptyList());
-            } else {
-                map.add(entry.getValue(), entryName);
-            }
-        }
-        List<ProviderInfo<T>> list = new LinkedList<ProviderInfo<T>>();
-        for (Map.Entry<ProviderInfo<T>, List<String>> entry : map.entrySet()) {
-            List<String> values = entry.getValue();
-            if (names.containsAll(values)) {
-                ProviderInfo<T> provider = entry.getKey();
-                list.add(provider);
-            }
-        }
-        return list;
-    }
-    
     public void addBeanParamInfo(BeanParamInfo bpi) {
         beanParams.put(bpi.getResourceClass(), bpi);
     }
@@ -221,7 +188,6 @@ public final class ServerProviderFactory
         return (ExceptionMapper<T>) candidates.get(0);
     }
     
-  //CHECKSTYLE:OFF 
     @SuppressWarnings("unchecked")
     @Override
     protected void setProviders(Object... providers) {
@@ -230,25 +196,11 @@ public final class ServerProviderFactory
         List<ProviderInfo<ContainerResponseFilter>> postMatchResponseFilters = 
             new LinkedList<ProviderInfo<ContainerResponseFilter>>();
         
-        for (Object o : providers) {
-            if (o == null) {
-                continue;
-            }
-            ProviderInfo<? extends Object> provider = null;
-            Class<?> providerCls = null;
-            Object realObject = null;
-            if (o instanceof Constructor) {
-                Map<Class<?>, Object> values = CastUtils.cast(application == null ? null 
-                    : Collections.singletonMap(Application.class, application.getProvider()));
-                provider = createProviderFromConstructor((Constructor<?>)o, values);
-                providerCls = provider.getProvider().getClass();
-                realObject = provider;
-            } else {
-                providerCls = ClassHelper.getRealClass(o);
-                provider = new ProviderInfo<Object>(o, getBus());
-                realObject = o;
-            }
-            super.setProviders(realObject);
+        List<ProviderInfo<? extends Object>> theProviders = 
+            prepareProviders((Object[])providers, application);
+        super.setCommonProviders(theProviders);
+        for (ProviderInfo<? extends Object> provider : theProviders) {
+            Class<?> providerCls = ClassHelper.getRealClass(provider.getProvider());
                         
             if (ContainerRequestFilter.class.isAssignableFrom(providerCls)) {
                 addContainerRequestFilter(postMatchRequestFilters, 
@@ -261,7 +213,7 @@ public final class ServerProviderFactory
             
             if (DynamicFeature.class.isAssignableFrom(providerCls)) {
                 //TODO: review the possibility of DynamicFeatures needing to have Contexts injected
-                Object feature = realObject == provider ? provider.getProvider() : realObject;
+                Object feature = provider.getProvider();
                 dynamicFeatures.add((DynamicFeature)feature);
             }
             
@@ -276,13 +228,10 @@ public final class ServerProviderFactory
         mapContainerFilters(postMatchContainerRequestFilters, postMatchRequestFilters, true);
         mapContainerFilters(postMatchContainerResponseFilters, postMatchResponseFilters, false);
         
-        injectContextProxies( 
-            exceptionMappers,
+        injectContextProxies(exceptionMappers,
             postMatchContainerRequestFilters.values(), preMatchContainerRequestFilters,
-            postMatchContainerResponseFilters.values(),
-            readerInterceptors, writerInterceptors);
+            postMatchContainerResponseFilters.values());
     }
-//CHECKSTYLE:ON
     
     @Override
     protected void injectContextProxiesIntoProvider(ProviderInfo<?> pi) {
@@ -380,62 +329,7 @@ public final class ServerProviderFactory
         return AnnotationUtils.getClassAnnotation(filterCls, PreMatching.class) != null;
     }
     
-    private static <T> void mapContainerFilters(Map<NameKey, ProviderInfo<T>> map,
-                                                List<ProviderInfo<T>> postMatchFilters,
-                                                boolean ascending) {
-        
-        Collections.sort(postMatchFilters, new PostMatchFilterComparator(ascending));
-        for (ProviderInfo<T> p : postMatchFilters) { 
-            List<String> names = AnnotationUtils.getNameBindings(
-                p.getProvider().getClass().getAnnotations());
-            names = names.isEmpty() ? Collections.singletonList(DEFAULT_FILTER_NAME_BINDING) : names;
-            for (String name : names) {
-                map.put(new NameKey(name, AnnotationUtils.getBindingPriority(p.getProvider().getClass())), 
-                        p);
-            }
-        }
-        
-    }
-    
-    private static class PostMatchFilterComparator extends BindingPriorityComparator {
-        public PostMatchFilterComparator(boolean ascending) {
-            super(ascending);
-        }
-        
-        @Override
-        public int compare(ProviderInfo<?> p1, ProviderInfo<?> p2) {
-            int result = super.compare(p1, p2);
-            if (result == 0) {
-                Integer namesSize1 = 
-                    AnnotationUtils.getNameBindings(p1.getProvider().getClass().getAnnotations()).size();
-                Integer namesSize2 = 
-                    AnnotationUtils.getNameBindings(p2.getProvider().getClass().getAnnotations()).size();
-                
-                // if we have two filters with the same binding priority, 
-                // then put a filter with more name bindings upfront 
-                // (this effectively puts name bound filters before global ones)
-                result = namesSize1.compareTo(namesSize2) * -1;
-            }
-            return result; 
-        }
-    }
     
-    private static class NameKey { 
-        private String name;
-        private int bindingPriority;
-        public NameKey(String name, int priority) {
-            this.name = name;
-            this.bindingPriority = priority;
-        }
-        
-        public String getName() {
-            return name;
-        }
-        
-        public int getPriority() {
-            return bindingPriority;
-        }
-    }
     
     private class MethodConfigurable implements FeatureContext, Configuration {
         
@@ -530,10 +424,14 @@ public final class ServerProviderFactory
                     setIsNeeded = true;    
                 }
                 if (contract == ReaderInterceptor.class && provider instanceof ReaderInterceptor) {
-                    addToInterceptors(readerInterceptors, provider, bindingPriority, true);
+                    readerInterceptors = 
+                        addToPostMatching(readerInterceptors, provider, bindingPriority, true);
+                    setIsNeeded = true;
                 }
                 if (contract == WriterInterceptor.class && provider instanceof WriterInterceptor) {
-                    addToInterceptors(writerInterceptors, provider, bindingPriority, false);
+                    writerInterceptors = 
+                        addToPostMatching(writerInterceptors, provider, bindingPriority, false);
+                    setIsNeeded = true;
                 }
             }
             

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=1478963&r1=1478962&r2=1478963&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 Fri May  3 20:30:47 2013
@@ -831,7 +831,7 @@ public final class JAXRSUtils {
                                        parameterAnns,
                                        is, 
                                        toMediaType(contentType),
-                                       ori.getConsumeTypes(),
+                                       ori,
                                        message);
         } else if (parameter.getType() == ParameterType.CONTEXT) {
             return createContextValue(message, parameterType, parameterClass);
@@ -1260,10 +1260,10 @@ public final class JAXRSUtils {
                                                   Annotation[] parameterAnnotations,
                                                   InputStream is, 
                                                   MediaType contentType, 
-                                                  List<MediaType> consumeTypes,
+                                                  OperationResourceInfo ori,
                                                   Message m) throws IOException, WebApplicationException {
         
-        List<MediaType> types = JAXRSUtils.intersectMimeTypes(consumeTypes, contentType);
+        List<MediaType> types = JAXRSUtils.intersectMimeTypes(ori.getConsumeTypes(), contentType);
         
         final ProviderFactory pf = ServerProviderFactory.getInstance(m);
         for (MediaType type : types) { 
@@ -1272,7 +1272,8 @@ public final class JAXRSUtils {
                                          parameterType,
                                          parameterAnnotations,
                                          type,
-                                         m);
+                                         m,
+                                         ori.getNameBindings());
             if (readers != null) {
                 try {
                     return readFromMessageBodyReader(readers, 

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/utils/JAXRSUtilsTest.java Fri May  3 20:30:47 2013
@@ -1488,7 +1488,8 @@ public class JAXRSUtilsTest extends Asse
                 }
             });
         
-        List<Object> params = JAXRSUtils.processParameters(new OperationResourceInfo(m, null), 
+        List<Object> params = JAXRSUtils.processParameters(new OperationResourceInfo(m, 
+                                                               new ClassResourceInfo(Customer.class)), 
                                                            new MetadataMap<String, String>(), messageImpl);
         assertEquals("3 params should've been identified", 3, params.size());
         

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java Fri May  3 20:30:47 2013
@@ -424,7 +424,7 @@ public abstract class AbstractClient imp
         MediaType contentType = JAXRSUtils.toMediaType(headers.getFirst("Content-Type").toString()); 
         
         List<WriterInterceptor> writers = ClientProviderFactory.getInstance(outMessage)
-            .createMessageBodyWriterInterceptor(theClass, type, anns, contentType, outMessage);
+            .createMessageBodyWriterInterceptor(theClass, type, anns, contentType, outMessage, null);
         if (writers != null) {
             try {
                 JAXRSUtils.writeMessageBody(writers, 
@@ -495,7 +495,7 @@ public abstract class AbstractClient imp
         
         List<ReaderInterceptor> readers 
             = ClientProviderFactory.getInstance(outMessage).createMessageBodyReaderInterceptor(
-                cls, type, anns, contentType, outMessage);
+                cls, type, anns, contentType, outMessage, null);
         if (readers != null) {
             try {
                 responseMessage.put(Message.PROTOCOL_HEADERS, r.getMetadata());

Modified: cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProviderFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProviderFactory.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProviderFactory.java (original)
+++ cxf/trunk/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/ClientProviderFactory.java Fri May  3 20:30:47 2013
@@ -80,38 +80,31 @@ public final class ClientProviderFactory
     }
     
     
-    //CHECKSTYLE:OFF 
+    @SuppressWarnings("unchecked")
     @Override
     protected void setProviders(Object... providers) {
-        super.setProviders(providers);
-        for (Object o : providers) {
-            if (o == null) {
-                continue;
-            }
-            Class<?> oClass = ClassHelper.getRealClass(o);
-            if (ClientRequestFilter.class.isAssignableFrom(oClass)) {
-                clientRequestFilters.add(
-                   new ProviderInfo<ClientRequestFilter>((ClientRequestFilter)o, getBus()));
+        List<ProviderInfo<? extends Object>> theProviders = 
+            prepareProviders((Object[])providers, null);
+        super.setCommonProviders(theProviders);
+        for (ProviderInfo<? extends Object> provider : theProviders) {
+            Class<?> providerCls = ClassHelper.getRealClass(provider.getProvider());
+            if (ClientRequestFilter.class.isAssignableFrom(providerCls)) {
+                clientRequestFilters.add((ProviderInfo<ClientRequestFilter>)provider);
             }
             
-            if (ClientResponseFilter.class.isAssignableFrom(oClass)) {
-                clientResponseFilters.add(
-                   new ProviderInfo<ClientResponseFilter>((ClientResponseFilter)o, getBus()));
+            if (ClientResponseFilter.class.isAssignableFrom(providerCls)) {
+                clientResponseFilters.add((ProviderInfo<ClientResponseFilter>)provider);
             }
             
-            if (ResponseExceptionMapper.class.isAssignableFrom(oClass)) {
-                responseExceptionMappers.add(
-                    new ProviderInfo<ResponseExceptionMapper<?>>((ResponseExceptionMapper<?>)o, getBus())); 
+            if (ResponseExceptionMapper.class.isAssignableFrom(providerCls)) {
+                responseExceptionMappers.add((ProviderInfo<ResponseExceptionMapper<?>>)provider); 
             }
-        
-            
         }
         Collections.sort(clientRequestFilters, new BindingPriorityComparator(true));
         Collections.sort(clientResponseFilters, new BindingPriorityComparator(false));
         
         injectContextProxies(responseExceptionMappers, clientRequestFilters, clientResponseFilters);
     }
-//CHECKSTYLE:ON
     
     @SuppressWarnings("unchecked")
     public <T extends Throwable> ResponseExceptionMapper<T> createResponseExceptionMapper(

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java Fri May  3 20:30:47 2013
@@ -79,6 +79,7 @@ public class BookServer20 extends Abstra
         providers.add(new PostMatchContainerResponseFilter());
         providers.add(new PostMatchContainerResponseFilter3());
         providers.add(new PostMatchContainerResponseFilter2());
+        providers.add(new CustomReaderBoundInterceptor());
         providers.add(new CustomReaderInterceptor());
         providers.add(new CustomWriterInterceptor());
         providers.add(new CustomDynamicFeature());
@@ -325,6 +326,13 @@ public class BookServer20 extends Abstra
     @Target({ ElementType.TYPE, ElementType.METHOD })
     @Retention(value = RetentionPolicy.RUNTIME)
     @NameBinding
+    public @interface CustomHeaderAddedAsync { 
+        
+    }
+    
+    @Target({ ElementType.TYPE, ElementType.METHOD })
+    @Retention(value = RetentionPolicy.RUNTIME)
+    @NameBinding
     public @interface PostMatchMode { 
         
     }
@@ -336,6 +344,7 @@ public class BookServer20 extends Abstra
         
     }
     
+    @Priority(1)
     public static class CustomReaderInterceptor implements ReaderInterceptor {
         @Context
         private ResourceInfo ri;
@@ -351,6 +360,31 @@ public class BookServer20 extends Abstra
         
     }
     
+    @Priority(2)
+    @CustomHeaderAddedAsync
+    public static class CustomReaderBoundInterceptor implements ReaderInterceptor {
+        @Context
+        private ResourceInfo ri;
+        @Context
+        private UriInfo ui;
+        @Override
+        public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException,
+            WebApplicationException {
+            if (ri.getResourceClass() == BookStore.class) {
+                String serverRead = context.getHeaders().getFirst("ServerReaderInterceptor");
+                if (serverRead == null || !serverRead.equals("serverRead")) {
+                    throw new RuntimeException();
+                }
+                if (ui.getPath().endsWith("/async")) {
+                    context.getHeaders().putSingle("ServerReaderInterceptor", "serverReadAsync");
+                }
+            }
+            return context.proceed();
+            
+        }
+        
+    }
+    
     public static class CustomWriterInterceptor implements WriterInterceptor {
 
         @Override

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookStore.java Fri May  3 20:30:47 2013
@@ -89,6 +89,7 @@ import org.apache.cxf.jaxrs.ext.xml.XSIS
 import org.apache.cxf.jaxrs.impl.ResourceContextImpl;
 import org.apache.cxf.phase.PhaseInterceptorChain;
 import org.apache.cxf.systest.jaxrs.BookServer20.CustomHeaderAdded;
+import org.apache.cxf.systest.jaxrs.BookServer20.CustomHeaderAddedAsync;
 import org.apache.cxf.systest.jaxrs.BookServer20.PostMatchMode;
 
 @Path("/bookstore")
@@ -556,6 +557,21 @@ public class BookStore {
         return builder.build();
     }
     
+    @POST
+    @Path("/bookheaders/simple/async")
+    @PostMatchMode
+    @CustomHeaderAdded
+    @CustomHeaderAddedAsync
+    public Response echoBookByHeaderSimpleAsync(Book book,
+                                       @HeaderParam("BOOK") String headerBook,
+                                       @HeaderParam("Simple") String headerSimple,
+                                       @HeaderParam("ServerReaderInterceptor") String serverInterceptorHeader,
+                                       @HeaderParam("ClientWriterInterceptor") String clientInterceptorHeader) 
+        throws Exception {
+        
+        return echoBookByHeaderSimple(book, headerBook, headerSimple, serverInterceptorHeader, clientInterceptorHeader);
+    }
+    
     private ResponseBuilder getBookByHeaderSimpleBuilder(@HeaderParam("BOOK") String headerBook,
         @HeaderParam("Simple") String headerSimple) throws Exception {
         

Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java?rev=1478963&r1=1478962&r2=1478963&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRS20ClientServerBookTest.java Fri May  3 20:30:47 2013
@@ -377,7 +377,7 @@ public class JAXRS20ClientServerBookTest
         Book book = future.get();
         assertSame(book, holder.value);
         assertEquals(124L, book.getId());
-        validatePostResponse(wc);   
+        validatePostResponse(wc, true);   
     }
     
     private void doTestGetBookAsyncResponse(String address, boolean asyncInvoker) 
@@ -413,10 +413,11 @@ public class JAXRS20ClientServerBookTest
         assertEquals("http://localhost/redirect", response.getHeaderString(HttpHeaders.LOCATION));
     }
     
-    private void validatePostResponse(WebClient wc) {
+    private void validatePostResponse(WebClient wc, boolean async) {
         validateResponse(wc);
         Response response = wc.getResponse();
-        assertEquals("serverRead", response.getHeaderString("ServerReaderInterceptor"));
+        assertEquals(!async ? "serverRead" : "serverReadAsync", 
+            response.getHeaderString("ServerReaderInterceptor"));
         assertEquals("clientWrite", response.getHeaderString("ClientWriterInterceptor"));
         assertEquals("clientRead", response.getHeaderString("ClientReaderInterceptor"));
     }
@@ -442,7 +443,7 @@ public class JAXRS20ClientServerBookTest
         WebClient wc = createWebClientPost(address);
         Book book = wc.post(new Book("Book", 126L), Book.class);
         assertEquals(124L, book.getId());
-        validatePostResponse(wc);
+        validatePostResponse(wc, false);
     }
     
     @Test
@@ -463,16 +464,16 @@ public class JAXRS20ClientServerBookTest
     
     @Test
     public void testPostBookAsync() throws Exception {
-        String address = "http://localhost:" + PORT + "/bookstore/bookheaders/simple";
+        String address = "http://localhost:" + PORT + "/bookstore/bookheaders/simple/async";
         WebClient wc = createWebClientPost(address);
         Future<Book> future = wc.async().post(Entity.xml(new Book("Book", 126L)), Book.class);
         assertEquals(124L, future.get().getId());
-        validatePostResponse(wc);
+        validatePostResponse(wc, true);
     }
     
     @Test
     public void testPostBookAsyncHandler() throws Exception {
-        String address = "http://localhost:" + PORT + "/bookstore/bookheaders/simple";
+        String address = "http://localhost:" + PORT + "/bookstore/bookheaders/simple/async";
         doTestPostBookAsyncHandler(address);
     }