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/07/31 23:42:45 UTC

svn commit: r1509043 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/ rt/frontend/jaxrs/src/main/java/org/a...

Author: sergeyb
Date: Wed Jul 31 21:42:45 2013
New Revision: 1509043

URL: http://svn.apache.org/r1509043
Log:
[CXF-5135] Related refactoring to get various provider registration options supported

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java   (with props)
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.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/AnnotationUtils.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/model/ClassResourceInfoTest.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookServer20.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java?rev=1509043&r1=1509042&r2=1509043&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/JAXRSServerFactoryBean.java Wed Jul 31 21:42:45 2013
@@ -22,7 +22,7 @@ import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -101,9 +101,9 @@ public class JAXRSServerFactoryBean exte
      */
     public void setApplication(Application app) {
         appProvider = new ProviderInfo<Application>(app, getBus());
-        List<String> appNameBindings = AnnotationUtils.getNameBindings(app.getClass().getAnnotations());
+        Set<String> appNameBindings = AnnotationUtils.getNameBindings(app.getClass().getAnnotations());
         for (ClassResourceInfo cri : getServiceFactory().getClassResourceInfo()) {
-            List<String> clsNameBindings = new LinkedList<String>(appNameBindings);
+            Set<String> clsNameBindings = new LinkedHashSet<String>(appNameBindings);
             clsNameBindings.addAll(AnnotationUtils.getNameBindings(cri.getServiceClass().getAnnotations()));
             cri.setNameBindings(clsNameBindings);
         }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java?rev=1509043&r1=1509042&r2=1509043&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ClassResourceInfo.java Wed Jul 31 21:42:45 2013
@@ -53,7 +53,7 @@ public class ClassResourceInfo extends B
     private boolean createdFromModel; 
     private String consumesTypes;
     private String producesTypes;
-    private List<String> nameBindings = Collections.emptyList();
+    private Set<String> nameBindings = Collections.emptySet();
     private ClassResourceInfo parent;
     private Set<String> injectedSubInstances = new HashSet<String>();
     public ClassResourceInfo(ClassResourceInfo cri) {
@@ -188,7 +188,7 @@ public class ClassResourceInfo extends B
         return Collections.unmodifiableCollection(subResources.values());
     }
     
-    public List<String> getNameBindings() {
+    public Set<String> getNameBindings() {
         if (parent == null) {
             return nameBindings;
         } else {
@@ -196,7 +196,7 @@ public class ClassResourceInfo extends B
         }
     }
     
-    public void setNameBindings(List<String> names) {
+    public void setNameBindings(Set<String> names) {
         nameBindings = names;
     }
     

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java?rev=1509043&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java Wed Jul 31 21:42:45 2013
@@ -0,0 +1,57 @@
+/**
+ * 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.cxf.jaxrs.model;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.cxf.Bus;
+
+public class FilterProviderInfo<T> extends ProviderInfo<T> {
+
+    private Set<String> nameBinding;
+    private int priority;
+    private List<Class<?>> supportedContracts;
+    
+    public FilterProviderInfo(T provider,
+                              Bus bus,
+                              String nameBinding,
+                              int priority,
+                              List<Class<?>> supportedContracts) {
+        super(provider, bus);
+        this.nameBinding = Collections.singleton(nameBinding);
+        this.priority = priority;
+        this.supportedContracts = supportedContracts;        
+    }
+
+    public Set<String> getNameBinding() {
+        return nameBinding;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+
+    public List<Class<?>> getSupportedContracts() {
+        return supportedContracts;
+    }
+
+}

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/FilterProviderInfo.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java?rev=1509043&r1=1509042&r2=1509043&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/OperationResourceInfo.java Wed Jul 31 21:42:45 2013
@@ -20,9 +20,9 @@
 package org.apache.cxf.jaxrs.model;
 
 import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.LinkedList;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DefaultValue;
@@ -47,7 +47,7 @@ public class OperationResourceInfo {
     private String defaultParamValue;
     private List<Parameter> parameters;
     private boolean oneway; 
-    private List<String> nameBindings = new LinkedList<String>();
+    private Set<String> nameBindings = new LinkedHashSet<String>();
 
     public OperationResourceInfo(Method mInvoke, ClassResourceInfo cri) {
         this(mInvoke, mInvoke, cri);
@@ -106,13 +106,12 @@ public class OperationResourceInfo {
         nameBindings.addAll(names);
     }
     
-    public List<String> getNameBindings() {
-        List<String> criNames = classResourceInfo.getNameBindings();
+    public Set<String> getNameBindings() {
+        Set<String> criNames = classResourceInfo.getNameBindings();
         if (criNames.isEmpty()) {
             return nameBindings;
         } else {
-            List<String> all = new ArrayList<String>(criNames.size() + nameBindings.size());
-            all.addAll(criNames);
+            Set<String> all = new LinkedHashSet<String>(criNames);
             all.addAll(nameBindings);
             return all;
         }

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=1509043&r1=1509042&r2=1509043&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 Wed Jul 31 21:42:45 2013
@@ -31,11 +31,11 @@ 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;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.logging.Logger;
 
 import javax.ws.rs.Produces;
@@ -65,6 +65,7 @@ import org.apache.cxf.jaxrs.impl.ReaderI
 import org.apache.cxf.jaxrs.impl.WriterInterceptorMBW;
 import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.FilterProviderInfo;
 import org.apache.cxf.jaxrs.model.ProviderInfo;
 import org.apache.cxf.jaxrs.utils.AnnotationUtils;
 import org.apache.cxf.jaxrs.utils.InjectionUtils;
@@ -87,9 +88,9 @@ public abstract class ProviderFactory {
     private static final String BUS_PROVIDERS_ALL = "org.apache.cxf.jaxrs.bus.providers";
     
     protected Map<NameKey, ProviderInfo<ReaderInterceptor>> readerInterceptors = 
-        new LinkedHashMap<NameKey, ProviderInfo<ReaderInterceptor>>();
+        new NameKeyMap<ProviderInfo<ReaderInterceptor>>(true);
     protected Map<NameKey, ProviderInfo<WriterInterceptor>> writerInterceptors = 
-        new LinkedHashMap<NameKey, ProviderInfo<WriterInterceptor>>();
+        new NameKeyMap<ProviderInfo<WriterInterceptor>>(true);
     
     private List<ProviderInfo<MessageBodyReader<?>>> messageReaders = 
         new ArrayList<ProviderInfo<MessageBodyReader<?>>>();
@@ -333,7 +334,7 @@ public abstract class ProviderFactory {
                                                             Annotation[] parameterAnnotations,
                                                             MediaType mediaType,
                                                             Message m,
-                                                            List<String> names) {
+                                                            Set<String> names) {
         MessageBodyReader<T> mr = createMessageBodyReader(bodyType,
                                                       parameterType,
                                                       parameterAnnotations,
@@ -368,7 +369,7 @@ public abstract class ProviderFactory {
                                                                           Annotation[] parameterAnnotations,
                                                                           MediaType mediaType,
                                                                           Message m,
-                                                                          List<String> names) {
+                                                                          Set<String> names) {
         MessageBodyWriter<T> mw = createMessageBodyWriter(bodyType,
                                                       parameterType,
                                                       parameterAnnotations,
@@ -510,11 +511,11 @@ public abstract class ProviderFactory {
                 contextProviders.add((ProviderInfo<ContextProvider<?>>)provider); 
             }
             
-            if (ReaderInterceptor.class.isAssignableFrom(providerCls)) {
+            if (filterContractSupported(provider, providerCls, ReaderInterceptor.class)) {
                 readInts.add((ProviderInfo<ReaderInterceptor>)provider);
             }
             
-            if (WriterInterceptor.class.isAssignableFrom(providerCls)) {
+            if (filterContractSupported(provider, providerCls, WriterInterceptor.class)) {
                 writeInts.add((ProviderInfo<WriterInterceptor>)provider);
             }
             
@@ -531,8 +532,8 @@ public abstract class ProviderFactory {
         sortWriters();
         sortContextResolvers();
         
-        mapContainerFilters(readerInterceptors, readInts, true);
-        mapContainerFilters(writerInterceptors, writeInts, true);
+        mapInterceptorFilters(readerInterceptors, readInts, true);
+        mapInterceptorFilters(writerInterceptors, writeInts, true);
         
         injectContextProxies(messageReaders, messageWriters, contextResolvers, 
             readerInterceptors.values(), writerInterceptors.values());
@@ -860,11 +861,11 @@ public abstract class ProviderFactory {
     }
 
     protected static <T> List<ProviderInfo<T>> getPostMatchContainerFilters(Map<NameKey, ProviderInfo<T>> boundFilters,
-                                                                          List<String> names) {
+                                                                          Set<String> names) {
         if (boundFilters.isEmpty()) {
             return Collections.emptyList();
         }
-        names = names == null ? Collections.<String>emptyList() : names;
+        names = names == null ? Collections.<String>emptySet() : names;
         
         MultivaluedMap<ProviderInfo<T>, String> map = 
             new MetadataMap<ProviderInfo<T>, String>();
@@ -977,32 +978,32 @@ public abstract class ProviderFactory {
         return getGenericInterfaces(cls.getSuperclass(), expectedClass);
     }
     
-    protected static class BindingPriorityComparator extends AbstactBindingPriorityComparator {
-        public BindingPriorityComparator(boolean ascending) {
-            super(ascending);
-        }
-    }
-    
-    private abstract static class AbstactBindingPriorityComparator implements 
-        Comparator<ProviderInfo<?>> {
+    protected static class AbstractPriorityComparator {
     
         private boolean ascending; 
         
-        protected AbstactBindingPriorityComparator(boolean ascending) {
+        protected AbstractPriorityComparator(boolean ascending) {
             this.ascending = ascending; 
         }
         
-        public int compare(ProviderInfo<?> p1, ProviderInfo<?> p2) {
-            Integer b1Value = getBindingPriorityValue(p1);
-            Integer b2Value = getBindingPriorityValue(p2);
-            
+        protected int compare(Integer b1Value, Integer b2Value) {
             int result = b1Value.compareTo(b2Value);
             return ascending ? result : result * -1;      
         }
         
-        private int getBindingPriorityValue(ProviderInfo<?> p) {
-            return AnnotationUtils.getBindingPriority(p.getProvider().getClass());
+    }
+    
+    protected static class BindingPriorityComparator extends AbstractPriorityComparator
+        implements Comparator<ProviderInfo<?>> {
+    
+        public BindingPriorityComparator(boolean ascending) {
+            super(ascending); 
+        }
+        
+        public int compare(ProviderInfo<?> p1, ProviderInfo<?> p2) {
+            return compare(getFilterPriority(p1), getFilterPriority(p2));
         }
+        
     }
     
     static class ContextResolverProxy<T> implements ContextResolver<T> {
@@ -1050,7 +1051,7 @@ public abstract class ProviderFactory {
     
     protected static class NameKey { 
         private String name;
-        private int bindingPriority;
+        private Integer bindingPriority;
         public NameKey(String name, int priority) {
             this.name = name;
             this.bindingPriority = priority;
@@ -1060,49 +1061,92 @@ public abstract class ProviderFactory {
             return name;
         }
         
-        public int getPriority() {
+        public Integer getPriority() {
             return bindingPriority;
         }
+                
+        public String toString() {
+            return name + ":" + 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;
+    protected static <T> void mapInterceptorFilters(Map<NameKey, ProviderInfo<T>> map,
+                                                    List<ProviderInfo<T>> filters,
+                                                    boolean ascending) {
+        
+        for (ProviderInfo<T> p : filters) { 
+            Set<String> names = getFilterNameBindings(p);
+            
+            int priority = getFilterPriority(p);
+            
             for (String name : names) {
-                map.put(new NameKey(name, AnnotationUtils.getBindingPriority(p.getProvider().getClass())), 
-                        p);
+                map.put(new NameKey(name, priority), p);
             }
         }
         
     }
     
-    protected static class PostMatchFilterComparator extends BindingPriorityComparator {
-        public PostMatchFilterComparator(boolean ascending) {
+    protected static Set<String> getFilterNameBindings(ProviderInfo<?> p) {
+        Set<String> names = null;
+        if (p instanceof FilterProviderInfo) {
+            names = ((FilterProviderInfo<?>)p).getNameBinding();
+        }
+        if (names == null) {
+            names = AnnotationUtils.getNameBindings(p.getProvider().getClass().getAnnotations());
+        }
+        if (names.isEmpty()) {
+            names = Collections.singleton(DEFAULT_FILTER_NAME_BINDING);
+        }
+        return names;
+    }
+    
+    protected static int getFilterPriority(ProviderInfo<?> p) {
+        return p instanceof FilterProviderInfo ? ((FilterProviderInfo<?>)p).getPriority()
+            : AnnotationUtils.getBindingPriority(p.getProvider().getClass());
+    }
+    
+    protected static class NameKeyComparator extends AbstractPriorityComparator
+        implements Comparator<NameKey> {
+
+        public NameKeyComparator(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;
+        public int compare(NameKey key1, NameKey key2) {
+            int result = compare(key1.getPriority(), key2.getPriority());
+            if (result != 0) {
+                return result;
+            }
+            return compare(key1.hashCode(), key2.hashCode());
+        }
+        
+    }
+    
+    protected static class NameKeyMap<T> extends TreeMap<NameKey, T> {
+        private static final long serialVersionUID = -4352258671270502204L;
+
+        public NameKeyMap(boolean ascending) {
+            super(new NameKeyComparator(ascending));
+        }
+    }
+    
+    protected static boolean filterContractSupported(ProviderInfo<?> provider, 
+                                                     Class<?> providerCls, 
+                                                     Class<?> contract) {
+        boolean result = false;
+        if (contract.isAssignableFrom(providerCls)) {
+            List<Class<?>> actualContracts = null;
+            if (provider instanceof FilterProviderInfo) {    
+                actualContracts = ((FilterProviderInfo<?>)provider).getSupportedContracts();
+            }
+            if (actualContracts != null) {
+                result = actualContracts.contains(contract); 
+            } else {
+                result = true;
             }
-            return result; 
         }
+        return result;
     }
     
     protected List<ProviderInfo<? extends Object>> prepareProviders(Object[] providers,
@@ -1117,7 +1161,9 @@ public abstract class ProviderFactory {
                 Map<Class<?>, Object> values = CastUtils.cast(application == null ? null 
                     : Collections.singletonMap(Application.class, application.getProvider()));
                 theProviders.add(createProviderFromConstructor((Constructor<?>)o, values));
-            } else {
+            } else if (o instanceof ProviderInfo) {
+                theProviders.add((ProviderInfo<?>)o);
+            } else {    
                 theProviders.add(new ProviderInfo<Object>(o, getBus()));
             }
         }

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=1509043&r1=1509042&r2=1509043&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 Wed Jul 31 21:42:45 2013
@@ -19,11 +19,11 @@
 package org.apache.cxf.jaxrs.provider;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -53,6 +53,7 @@ import org.apache.cxf.jaxrs.impl.Resourc
 import org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper;
 import org.apache.cxf.jaxrs.model.BeanParamInfo;
 import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+import org.apache.cxf.jaxrs.model.FilterProviderInfo;
 import org.apache.cxf.jaxrs.model.OperationResourceInfo;
 import org.apache.cxf.jaxrs.model.ProviderInfo;
 import org.apache.cxf.jaxrs.utils.AnnotationUtils;
@@ -61,11 +62,12 @@ import org.apache.cxf.message.Message;
 
 public final class ServerProviderFactory extends ProviderFactory {
     private static final String SHARED_SERVER_FACTORY = "jaxrs.shared.server.factory";
-    private static final Class<?>[] SERVER_FILTER_INTERCEPTOR_CLASSES = 
-        new Class<?>[] {ContainerRequestFilter.class,
-                        ContainerResponseFilter.class,
-                        ReaderInterceptor.class,
-                        WriterInterceptor.class};
+    private static final Set<Class<?>> SERVER_FILTER_INTERCEPTOR_CLASSES = 
+        new HashSet<Class<?>>(Arrays.<Class<?>>asList(ContainerRequestFilter.class,
+                                                      ContainerResponseFilter.class,
+                                                      ReaderInterceptor.class,
+                                                      WriterInterceptor.class));
+    
     private static final String WADL_PROVIDER_NAME = "org.apache.cxf.jaxrs.model.wadl.WadlGenerator";
     private List<ProviderInfo<ExceptionMapper<?>>> exceptionMappers = 
         new ArrayList<ProviderInfo<ExceptionMapper<?>>>(1);
@@ -73,9 +75,9 @@ public final class ServerProviderFactory
     private List<ProviderInfo<ContainerRequestFilter>> preMatchContainerRequestFilters = 
         new ArrayList<ProviderInfo<ContainerRequestFilter>>(1);
     private Map<NameKey, ProviderInfo<ContainerRequestFilter>> postMatchContainerRequestFilters = 
-        new LinkedHashMap<NameKey, ProviderInfo<ContainerRequestFilter>>();
+        new NameKeyMap<ProviderInfo<ContainerRequestFilter>>(true);
     private Map<NameKey, ProviderInfo<ContainerResponseFilter>> postMatchContainerResponseFilters = 
-        new LinkedHashMap<NameKey, ProviderInfo<ContainerResponseFilter>>();
+        new NameKeyMap<ProviderInfo<ContainerResponseFilter>>(false);
     private RequestPreprocessor requestPreprocessor;
     private ProviderInfo<Application> application;
     private List<DynamicFeature> dynamicFeatures = new LinkedList<DynamicFeature>();
@@ -135,7 +137,7 @@ public final class ServerProviderFactory
         return getContainerRequestFilters(preMatchContainerRequestFilters, true);
     }
     
-    public List<ProviderInfo<ContainerRequestFilter>> getPostMatchContainerRequestFilters(List<String> names) {
+    public List<ProviderInfo<ContainerRequestFilter>> getPostMatchContainerRequestFilters(Set<String> names) {
         return getPostMatchContainerFilters(postMatchContainerRequestFilters, names);
         
     }
@@ -162,7 +164,7 @@ public final class ServerProviderFactory
         }
     }
     
-    public List<ProviderInfo<ContainerResponseFilter>> getContainerResponseFilters(List<String> names) {
+    public List<ProviderInfo<ContainerResponseFilter>> getContainerResponseFilters(Set<String> names) {
         return getPostMatchContainerFilters(postMatchContainerResponseFilters, 
                                             names);
     }
@@ -200,6 +202,7 @@ public final class ServerProviderFactory
         return (ExceptionMapper<T>) candidates.get(0);
     }
     
+    
     @SuppressWarnings("unchecked")
     @Override
     protected void setProviders(Object... providers) {
@@ -213,13 +216,13 @@ public final class ServerProviderFactory
         super.setCommonProviders(theProviders);
         for (ProviderInfo<? extends Object> provider : theProviders) {
             Class<?> providerCls = ClassHelper.getRealClass(provider.getProvider());
-                        
-            if (ContainerRequestFilter.class.isAssignableFrom(providerCls)) {
+            
+            if (filterContractSupported(provider, providerCls, ContainerRequestFilter.class)) {
                 addContainerRequestFilter(postMatchRequestFilters, 
                                           (ProviderInfo<ContainerRequestFilter>)provider);
             }
             
-            if (ContainerResponseFilter.class.isAssignableFrom(providerCls)) {
+            if (filterContractSupported(provider, providerCls, ContainerResponseFilter.class)) {
                 postMatchResponseFilters.add((ProviderInfo<ContainerResponseFilter>)provider); 
             }
             
@@ -237,8 +240,8 @@ public final class ServerProviderFactory
         }
         
         Collections.sort(preMatchContainerRequestFilters, new BindingPriorityComparator(true));
-        mapContainerFilters(postMatchContainerRequestFilters, postMatchRequestFilters, true);
-        mapContainerFilters(postMatchContainerResponseFilters, postMatchResponseFilters, false);
+        mapInterceptorFilters(postMatchContainerRequestFilters, postMatchRequestFilters, true);
+        mapInterceptorFilters(postMatchContainerResponseFilters, postMatchResponseFilters, false);
         
         injectContextProxies(exceptionMappers,
             postMatchContainerRequestFilters.values(), preMatchContainerRequestFilters,
@@ -358,7 +361,6 @@ public final class ServerProviderFactory
         private Configurable<FeatureContext> configImpl;    
         private OperationResourceInfo ori;
         private String nameBinding;
-        private boolean bindingSet;
         
         public MethodFeatureContextImpl(OperationResourceInfo ori) {
             this.ori = ori;
@@ -420,130 +422,37 @@ public final class ServerProviderFactory
             return configImpl.register(object, map);
         }
         
-        FeatureContext doRegister(Object provider, int bindingPriority, Class<?>... contracts) {
+        FeatureContext doRegister(Object provider, int priority, Class<?>... contracts) {
         
             if (provider instanceof Feature) {
                 ((Feature)provider).configure(this);
                 return this;
             }
             
-            boolean setIsNeeded = false;
+            List<Class<?>> actualContracts = new LinkedList<Class<?>>();
+            
             for (Class<?> contract : contracts) {
-                if (contract == ContainerRequestFilter.class && provider instanceof ContainerRequestFilter) {
-                    if (isPrematching(provider.getClass())) {
-                        addToInterceptors(preMatchContainerRequestFilters, provider, bindingPriority, true);
-                    } else {
-                        postMatchContainerRequestFilters = 
-                            addToPostMatching(postMatchContainerRequestFilters, provider, bindingPriority, true);
-                        setIsNeeded = true;
-                    }
-                }
-                if (contract == ContainerResponseFilter.class && provider instanceof ContainerResponseFilter) {
-                    postMatchContainerResponseFilters = 
-                        addToPostMatching(postMatchContainerResponseFilters, provider, bindingPriority, false);
-                    setIsNeeded = true;    
-                }
-                if (contract == ReaderInterceptor.class && provider instanceof ReaderInterceptor) {
-                    readerInterceptors = 
-                        addToPostMatching(readerInterceptors, provider, bindingPriority, true);
-                    setIsNeeded = true;
-                }
-                if (contract == WriterInterceptor.class && provider instanceof WriterInterceptor) {
-                    writerInterceptors = 
-                        addToPostMatching(writerInterceptors, provider, bindingPriority, false);
-                    setIsNeeded = true;
+                if (SERVER_FILTER_INTERCEPTOR_CLASSES.contains(contract)
+                    && contract.isAssignableFrom(provider.getClass())) {
+                    actualContracts.add(contract);
                 }
             }
-            
-            if (setIsNeeded && !bindingSet) {
+            if (!actualContracts.isEmpty()) {
+                registerUserProvider(new FilterProviderInfo<Object>(provider, 
+                    getBus(),
+                    nameBinding,
+                    priority,
+                    actualContracts));
                 ori.addNameBindings(Collections.singletonList(nameBinding));
-                bindingSet = true;
             }
-
             return this;
         }
         
-        @SuppressWarnings("unchecked")
-        private <T> void addToInterceptors(List<ProviderInfo<T>> providers, Object provider, 
-                                           int priority, boolean asc) {
-            int size = providers.size();
-            if (size > 0) {
-                for (int i = 0; i < size; i++) {
-                    int providerPriority = AnnotationUtils.getBindingPriority(
-                        providers.get(i).getProvider().getClass());
-                    if (asc) {
-                        if (priority < providerPriority || i + 1 == size) {
-                            int index = priority < providerPriority ? i : i + 1;
-                            providers.add(index, (ProviderInfo<T>)newProvider(provider));
-                            break;
-                        }
-                    } else if (priority > providerPriority || i + 1 == size) {
-                        int index = priority > providerPriority ? i : i + 1; 
-                        providers.add(index, (ProviderInfo<T>)newProvider(provider));
-                        break;
-                    }
-                }
-            } else {
-                providers.add((ProviderInfo<T>)newProvider(provider));
-            }
-        }
-        
-        private <T> ProviderInfo<T> newProvider(T provider) {
-            ProviderInfo<T> newProvider = new ProviderInfo<T>(provider, getBus());
-            injectContextProxiesIntoProvider(newProvider);
-            return newProvider;
-        }
-        
-        @SuppressWarnings("unchecked")
-        private <T> Map<NameKey, ProviderInfo<T>> addToPostMatching(
-            Map<NameKey, ProviderInfo<T>> map, Object provider, int priority, boolean asc) {
-            Map<NameKey, ProviderInfo<T>> newMap = new LinkedHashMap<NameKey, ProviderInfo<T>>();
-            
-            Iterator<Map.Entry<NameKey, ProviderInfo<T>>> it = map.entrySet().iterator();
-            if (it.hasNext()) {
-                boolean added = false;
-                while (it.hasNext()) {
-                    Map.Entry<NameKey, ProviderInfo<T>> entry = it.next();
-                    int providerPriority = entry.getKey().getPriority();
-                    // this surely can be collapsed further
-                    if (!added && asc && (priority < providerPriority || !it.hasNext())) {
-                        addNewProvider(newMap, entry, provider, priority, providerPriority >= priority);
-                        added = true;
-                    } else if (!added && !asc && (priority > providerPriority || !it.hasNext())) {
-                        addNewProvider(newMap, entry, provider, priority, priority > providerPriority);
-                        added = true;
-                    } else {
-                        newMap.put(entry.getKey(), entry.getValue());
-                    }   
-                }
-            } else {
-                newMap.put(new NameKey(nameBinding, priority), (ProviderInfo<T>)newProvider(provider));
-            }
-            return newMap;
-            
-                
-        }
-        
-        @SuppressWarnings("unchecked")
-        private <T> void addNewProvider(Map<NameKey, ProviderInfo<T>> newMap, 
-                                        Map.Entry<NameKey, ProviderInfo<T>> entry,
-                                        Object provider, 
-                                        int priority,
-                                        boolean first) {
-            if (first) {
-                newMap.put(new NameKey(nameBinding, priority), (ProviderInfo<T>)newProvider(provider));
-                newMap.put(entry.getKey(), entry.getValue());
-            } else {
-                newMap.put(entry.getKey(), entry.getValue());
-                newMap.put(new NameKey(nameBinding, priority), (ProviderInfo<T>)newProvider(provider));
-            }
-        }
-        
-        
     }
+    
     private static class MethodFeatureContextConfigurable extends ConfigurableImpl<FeatureContext> {
         protected MethodFeatureContextConfigurable(MethodFeatureContextImpl mc) {
-            super(mc, RuntimeType.SERVER, SERVER_FILTER_INTERCEPTOR_CLASSES);
+            super(mc, RuntimeType.SERVER, SERVER_FILTER_INTERCEPTOR_CLASSES.toArray(new Class<?>[]{}));
         }
         @Override
         protected FeatureContext doRegister(Object provider, int bindingPriority, Class<?>... contracts) {

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AnnotationUtils.java?rev=1509043&r1=1509042&r2=1509043&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AnnotationUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/AnnotationUtils.java Wed Jul 31 21:42:45 2013
@@ -23,8 +23,7 @@ import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.LinkedHashSet;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.logging.Logger;
@@ -134,11 +133,11 @@ public final class AnnotationUtils {
         Priority b = getClassAnnotation(providerCls, Priority.class);
         return b == null ? Priorities.USER : b.value();
     }
-    public static List<String> getNameBindings(Annotation[] targetAnns) {
+    public static Set<String> getNameBindings(Annotation[] targetAnns) {
         if (targetAnns.length == 0) {
-            return Collections.emptyList();
+            return Collections.emptySet();
         }
-        List<String> names = new LinkedList<String>();
+        Set<String> names = new LinkedHashSet<String>();
         for (Annotation a : targetAnns) {
             NameBinding nb = a.annotationType().getAnnotation(NameBinding.class);
             if (nb != 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=1509043&r1=1509042&r2=1509043&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 Wed Jul 31 21:42:45 2013
@@ -1693,7 +1693,7 @@ public final class JAXRSUtils {
     public static boolean runContainerRequestFilters(ServerProviderFactory pf, 
                                                      Message m, 
                                                      boolean preMatch, 
-                                                     List<String> names,
+                                                     Set<String> names,
                                                      boolean sub) {
         List<ProviderInfo<ContainerRequestFilter>> containerFilters = preMatch 
             ? pf.getPreMatchContainerRequestFilters() : pf.getPostMatchContainerRequestFilters(names);

Modified: cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/ClassResourceInfoTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/ClassResourceInfoTest.java?rev=1509043&r1=1509042&r2=1509043&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/ClassResourceInfoTest.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/model/ClassResourceInfoTest.java Wed Jul 31 21:42:45 2013
@@ -224,8 +224,8 @@ public class ClassResourceInfoTest exten
         Application app = new TestApplication();
         JAXRSServerFactoryBean bean = ResourceUtils.createApplication(app, true, true);
         ClassResourceInfo cri = bean.getServiceFactory().getClassResourceInfo().get(0);
-        List<String> names = cri.getNameBindings();
-        assertEquals(Collections.singletonList(CustomNameBinding.class.getName()), names);
+        Set<String> names = cri.getNameBindings();
+        assertEquals(Collections.singleton(CustomNameBinding.class.getName()), names);
     }
     
     @Target({ ElementType.TYPE, ElementType.METHOD })

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=1509043&r1=1509042&r2=1509043&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 Wed Jul 31 21:42:45 2013
@@ -30,7 +30,9 @@ import java.lang.annotation.Target;
 import java.lang.reflect.Type;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Priority;
 import javax.servlet.http.HttpServletRequest;
@@ -302,8 +304,8 @@ public class BookServer20 extends Abstra
         
     }
     
-    @Priority(2)
-    public static class PostMatchDynamicContainerResponseFilter implements ContainerResponseFilter {
+    public static class PostMatchDynamicContainerResponseFilter 
+        implements ContainerRequestFilter, ContainerResponseFilter {
 
         @Override
         public void filter(ContainerRequestContext requestContext,
@@ -314,6 +316,12 @@ public class BookServer20 extends Abstra
             responseContext.getHeaders().add("DynamicResponse", "Dynamic");
             
         }
+
+        @Override
+        public void filter(ContainerRequestContext requestContext) throws IOException {
+            throw new RuntimeException();
+            
+        }
         
     }
     
@@ -407,7 +415,10 @@ public class BookServer20 extends Abstra
         public void configure(ResourceInfo resourceInfo, FeatureContext configurable) {
             
             configurable.register(new PreMatchDynamicContainerRequestFilter());
-            configurable.register(new PostMatchDynamicContainerResponseFilter());
+            Map<Class<?>, Integer> contracts = new HashMap<Class<?>, Integer>();
+            contracts.put(ContainerResponseFilter.class, 2);
+            configurable.register(new PostMatchDynamicContainerResponseFilter(), 
+                                  contracts);
         }
         
     }