incubator-wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r788908 [5/8] - in /incubator/wink/contrib/ibm-jaxrs: src/com/ibm/ws/jaxrs/annotations/ src/com/ibm/ws/jaxrs/context/ src/com/ibm/ws/jaxrs/core/ src/com/ibm/ws/jaxrs/engine/ src/com/ibm/ws/jaxrs/exception/ src/com/ibm/ws/jaxrs/ext/ src/com/...
Date Sat, 27 Jun 2009 00:02:34 GMT
Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/ProviderFactory.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/ProviderFactory.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/ProviderFactory.java
(original)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/ProviderFactory.java
Sat Jun 27 00:02:26 2009
@@ -25,7 +25,11 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
@@ -63,9 +67,7 @@
     private final List<ProviderInfo<ExceptionMapper>> userExceptionMappers =
new ArrayList<ProviderInfo<ExceptionMapper>>();
 
     private ProviderFactory(List<ProviderInfo> userProviders, RESTContext context)
{
-        // TODO : this needs to be done differently,
-        // we need to use cxf-jaxrs-extensions
-        List<Object> providers = new ArrayList<Object>();
+        List<ProviderInfo> providers = new ArrayList<ProviderInfo>();
 
         String[] providerClasses = {
                 "org.apache.cxf.jaxrs.provider.JAXBElementProvider",
@@ -88,10 +90,13 @@
         for (int i = 0; i < providerClasses.length; i++) {
             try {
                 Class clazz = ClassUtils.loadClass(providerClasses[i], cl);
-                providers.add(ClassUtils.newInstance(clazz));
+                providers.add(new ProviderInfoImpl(ClassUtils
+                        .newInstance(clazz)));
             } catch (Throwable t) {
-                System.out.println("Unable to load " + providerClasses[i]
-                        + " - skipping due to " + t.getMessage());
+                if (log.isDebugEnabled()) {
+                    log.debug("Unable to load " + providerClasses[i]
+                            + " - skipping due to " + t.getMessage());
+                }
                 continue;
             }
         }
@@ -159,16 +164,23 @@
             }
             return pf;
         }
-        pf = new ProviderFactory(metadata.getProviderInfoList(), context);
-        if (log.isDebugEnabled()) {
-            log
-                    .debug("Did not find ProviderFactory in cache so created: "
-                            + pf);
-        }
 
-        cache.cacheProviderFactory(context
-                .getProperty(ContextConstants.METADATA_KEY), pf);
-        return pf;
+        synchronized (cache) {
+            pf = cache.getProviderFactory(context
+                    .getProperty(ContextConstants.METADATA_KEY));
+            if (pf != null) {
+                return pf;
+            }
+
+            pf = new ProviderFactory(metadata.getProviderInfoList(), context);
+            if (log.isDebugEnabled()) {
+                log.debug("Did not find ProviderFactory in cache so created: "
+                        + pf);
+            }
+            cache.cacheProviderFactory(context
+                    .getProperty(ContextConstants.METADATA_KEY), pf);
+            return pf;
+        }
     }
 
     public <T> ContextResolver<T> createContextResolver(Type contextType, MediaType
mt, RESTContext context) {
@@ -197,44 +209,13 @@
     }
 
     private <T> ContextResolver<T> chooseContextResolver(List<ProviderInfo<ContextResolver>>
resolvers, Type contextType, final MediaType mediaType, final RESTContext context) {
-        final List<ProviderInfo<ContextResolver>> compatibleContextResolverInfo
= new ArrayList<ProviderInfo<ContextResolver>>();
+        final List<ProviderInfo> compatibleContextResolverInfo = new ArrayList<ProviderInfo>();
         for (ProviderInfo<ContextResolver> cr : resolvers) {
-            boolean isProducesMediaTypeMatch = true;
-            if (cr.getProducesTypes() != null && mediaType != null) {
-                isProducesMediaTypeMatch = false;
-                for (MediaType mt : cr.getProducesTypes()) {
-                    if (mediaType.isCompatible(mt)) {
-                        isProducesMediaTypeMatch = true;
-                        break;
-                    }
-                }
-            }
-            if (isProducesMediaTypeMatch) {
-                Type[] types = cr.getProviderClass().getGenericInterfaces();
-                for (Type t : types) {
-                    if (t instanceof ParameterizedType) {
-                        ParameterizedType pt = (ParameterizedType) t;
-                        Type[] args = pt.getActualTypeArguments();
-                        for (int i = 0; i < args.length; i++) {
-                            if (contextType == args[i]) {
-                                compatibleContextResolverInfo.add(cr);
-                            }
-                            /*
-                             * should check if type widening is acceptable
-                             */
-                            //                            else if (contextType instanceof
Class && args[i] instanceof Class) {
-                            //                                Class contextTypeClass = (Class)
contextType;
-                            //                                Class argClass = (Class) args[i];
-                            //                                if (argClass.isAssignableFrom(contextTypeClass))
{
-                            //                                    InjectionUtils.injectContextFields(cr.getProvider(),
cr,
-                            //                                        context);
-                            //                                    InjectionUtils.injectContextMethods(cr.getProvider(),
cr,
-                            //                                        context);
-                            //                                    compatibleContextResolverInfo.add(cr);
-                            //                                }
-                            //                            }
-                        }
-                    }
+            if (mediaType == null
+                    || cr.isMediaTypeCompatibleWithProduces(mediaType)) {
+                if (cr.isParameterizedTypeCompatible(
+                        ProviderInfo.Type.ContextResolver, contextType)) {
+                    compatibleContextResolverInfo.add(cr);
                 }
             }
         }
@@ -248,8 +229,7 @@
         if (compatibleContextResolverInfo.size() > 1) {
             if (mediaType != null) {
                 Collections.sort(compatibleContextResolverInfo,
-                        new ProviderInfoProducesComparator<ContextResolver>(
-                                mediaType));
+                        ProviderInfoProducesComparator.getInstance(mediaType));
             }
             return new ContextResolver<T>() {
                 final List<ContextResolver<T>> contextResolvers = new ArrayList<ContextResolver<T>>();
@@ -286,7 +266,7 @@
         return chooseExceptionMapper(exceptionType, context, exceptionMappers);
     }
 
-    private int getDistanceFromClass(Class<?> superclass, Class<?> subclass)
{
+    private static int getDistanceFromClass(Class<?> superclass, Class<?> subclass)
{
         Class<?> currentClass = subclass;
         int distance = 0;
         while (!currentClass.equals(superclass)) {
@@ -348,12 +328,13 @@
         // Try user provided providers
         MessageBodyReader<T> mr = chooseMessageReader(userMessageReaders,
                 bodyType, parameterType, parameterAnnotations, mediaType,
-                context);
+                context, false);
 
         //If none found try the default ones
         if (mr == null) {
             mr = chooseMessageReader(defaultMessageReaders, bodyType,
-                    parameterType, parameterAnnotations, mediaType, context);
+                    parameterType, parameterAnnotations, mediaType, context,
+                    true);
         }
 
         return mr;
@@ -371,7 +352,7 @@
         // Try user provided providers
         MessageBodyProviderMatch<MessageBodyWriter> match = chooseMessageWriter(
                 userMessageWriters, bodyType, parameterType,
-                parameterAnnotations, mediaType, context);
+                parameterAnnotations, mediaType, context, false);
         MessageBodyWriter mw = (match == null) ? null : match.getWriter();
         if (log.isDebugEnabled()) {
             if (mw != null)
@@ -384,7 +365,8 @@
         // If none found try the default ones
         if (match == null) {
             match = chooseMessageWriter(defaultMessageWriters, bodyType,
-                    parameterType, parameterAnnotations, mediaType, context);
+                    parameterType, parameterAnnotations, mediaType, context,
+                    true);
         }
 
         mw = (match == null) ? null : match.getWriter();
@@ -408,49 +390,25 @@
         return mw;
     }
 
-    private static void setProviders(List<ProviderInfo<MessageBodyReader>> readers,
List<ProviderInfo<MessageBodyWriter>> writers, List<ProviderInfo<ContextResolver>>
resolvers, List<ProviderInfo<ExceptionMapper>> excMappers, List<?> providers)
{
+    private static void setProviders(List<ProviderInfo<MessageBodyReader>> readers,
List<ProviderInfo<MessageBodyWriter>> writers, List<ProviderInfo<ContextResolver>>
resolvers, List<ProviderInfo<ExceptionMapper>> excMappers, List<ProviderInfo>
providers) {
 
-        for (Object o : providers) {
-            Class<?> classToTest = o.getClass();
-            // TODO: Reusing the same ProviderInfo object may not be the right thing
-            // to do here, but it solves problems created by injection of different
-            // thread local proxies
-            ProviderInfo info = null;
-
-            if (o instanceof ProviderInfo) {
-                info = (ProviderInfo) o;
-                classToTest = info.getProviderClass();
-            }
+        for (ProviderInfo o : providers) {
+            Class<?> classToTest = o.getProviderClass();
+            ProviderInfo info = o;
 
             if (MessageBodyReader.class.isAssignableFrom(classToTest)) {
-                if (info == null) {
-                    info = new ProviderInfoImpl<MessageBodyReader>(
-                            (MessageBodyReader) o);
-                }
                 readers.add(info);
             }
 
             if (MessageBodyWriter.class.isAssignableFrom(classToTest)) {
-                if (info == null) {
-                    info = new ProviderInfoImpl<MessageBodyWriter>(
-                            (MessageBodyWriter) o);
-                }
                 writers.add(info);
             }
 
             if (ContextResolver.class.isAssignableFrom(classToTest)) {
-                if (info == null) {
-                    info = new ProviderInfoImpl<ContextResolver>(
-                            (ContextResolver) o);
-                }
                 resolvers.add(info);
             }
 
             if (ExceptionMapper.class.isAssignableFrom(classToTest)) {
-                if (info == null) {
-                    info = new ProviderInfoImpl<ExceptionMapper>(
-                            (ExceptionMapper) o);
-                }
                 excMappers.add(info);
             }
         }
@@ -467,66 +425,198 @@
      * @return
      */
     @SuppressWarnings("unchecked")
-    private <T> MessageBodyReader<T> chooseMessageReader(List<ProviderInfo<MessageBodyReader>>
readers, Class<T> type, Type genericType, Annotation[] annotations, final MediaType
mediaType, RESTContext context) {
+    private <T> MessageBodyReader<T> chooseMessageReader(List<ProviderInfo<MessageBodyReader>>
readers, Class<T> type, Type genericType, Annotation[] annotations, final MediaType
mediaType, RESTContext context, boolean isDefaultProviders) {
         if (log.isDebugEnabled()) {
             log.debug("chooseMessageReader, type= " + type.getName()
                     + ", genericType= " + genericType + ", mediaType= "
                     + (mediaType != null ? mediaType.toString() : "<null>"));
         }
 
-        List<MessageBodyProviderMatch<MessageBodyReader>> possibleReaders = new
ArrayList<MessageBodyProviderMatch<MessageBodyReader>>();
+        ProviderInfo<MessageBodyReader> bestProviderInfoMatch = null;
+        MessageBodyReader bestProviderInstanceMatch = null;
+        //        MediaType bestIntersectedMediaType = null;
+        MediaType bestCompatibleMediaType = null;
+
         /*
-         * TODO possible performance improvement is not to call the
-         * MessageBodyReader.isReadable method in matchesReaderCriteria
-         * until the mime types are compared and the writers are sorted. The
-         * penalty for the isReadable method could be significant.
+         * see the note about cheating in the chooseMessageWriter method
          */
-        for (ProviderInfo<MessageBodyReader> ep : readers) {
-            List<MediaType> supportedMediaTypes = ep.getConsumesTypes();
-            List<MediaType> availableMimeTypes = JAXRSUtils.intersectMimeTypes(
-                    Collections.singletonList(mediaType), supportedMediaTypes);
 
-            if (availableMimeTypes.size() == 0) {
+        ProviderInfo<MessageBodyReader> cacheHit = null;
+        Map<Type, ProviderInfo<MessageBodyReader>> typeCache = null;
+
+        if (isDefaultProviders) {
+            Map<MediaType, Map<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>>
defaultProviderCache = this.defaultReaderProviderCache
+                    .get();
+            Map<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>
classCache = defaultProviderCache
+                    .get(mediaType);
+            if (classCache == null) {
+                classCache = new ClassToGenericTypeReaderCache();
+                defaultProviderCache.put(mediaType, classCache);
+            }
+
+            typeCache = classCache.get(type);
+            if (typeCache == null) {
+                typeCache = new TypeToMessageBodyProviderMatchReaderCache();
+                classCache.put(type, typeCache);
+            }
+
+            cacheHit = typeCache.get(genericType);
+            if (cacheHit != null) {
+                LifecycleManager mgr = LifecycleManagerFactory
+                        .getLifeCycleManager(cacheHit);
+                return (MessageBodyReader) mgr
+                        .createInstance(cacheHit, context);
+            }
+        }
+
+        for (ProviderInfo<MessageBodyReader> ep : readers) {
+            if (!ep.isMediaTypeCompatibleWithConsumes(mediaType)) {
                 continue;
             }
 
-            Type t = ep
-                    .getParameterizedType()
-                    .get(
-                            org.apache.cxf.jaxrs.model.ProviderInfo.Type.MessageBodyReader);
-            if (!isTypeCompatible(type, t)) {
+            if (!ep
+                    .isParameterizedTypeCompatible(
+                            org.apache.cxf.jaxrs.model.ProviderInfo.Type.MessageBodyReader,
+                            type)) {
                 continue;
             }
 
+            MediaType epMostSpecificCompatible = null;
+            if (bestProviderInfoMatch != null) {
+                epMostSpecificCompatible = ep
+                        .getConsumesTypesMostSpecificCompatibleWithMediaType(mediaType);
+                if (compareMediaTypesWithNullPossible(epMostSpecificCompatible,
+                        bestCompatibleMediaType) != -1) {
+                    continue;
+                }
+            }
+
             LifecycleManager mgr = LifecycleManagerFactory
                     .getLifeCycleManager(ep);
             MessageBodyReader instance = (MessageBodyReader) mgr
                     .createInstance(ep, context);
 
-            if (instance.isReadable(type, genericType, annotations, mediaType)) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Found suitable MessageBodyReader instance: "
-                            + instance.getClass().getName());
+            List<MediaType> availableMimeTypes = ep
+                    .getConsumesTypesIntersectedWithMediaType(mediaType);
+            for (MediaType intersectedMediaType : availableMimeTypes) {
+                if (instance.isReadable(type, genericType, annotations,
+                        intersectedMediaType)) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Found suitable MessageBodyReader instance: "
+                                + instance.getClass().getName());
+                    }
+                    bestProviderInfoMatch = ep;
+                    bestProviderInstanceMatch = instance;
+                    //                    bestIntersectedMediaType = intersectedMediaType;
+                    if (epMostSpecificCompatible == null) {
+                        epMostSpecificCompatible = ep
+                                .getConsumesTypesMostSpecificCompatibleWithMediaType(mediaType);
+                    }
+                    bestCompatibleMediaType = epMostSpecificCompatible;
+                    break;
                 }
-                possibleReaders
-                        .add(new MessageBodyProviderMatch<MessageBodyReader>(
-                                ep, instance, mediaType));
             }
         }
 
-        if (possibleReaders.size() > 0) {
-            Collections.sort(possibleReaders,
-                    new Comparator<MessageBodyProviderMatch>() {
-                        public int compare(MessageBodyProviderMatch object1, MessageBodyProviderMatch
object2) {
-                            return new ProviderInfoConsumesComparator<MessageBodyReader>(
-                                    mediaType).compare(object1
-                                    .getProviderInfo(), object2
-                                    .getProviderInfo());
-                        }
-                    });
-            return possibleReaders.get(0).getWriter();
+        if (isDefaultProviders) {
+            /*
+             * the following null check is redundant
+             */
+            if (typeCache != null) {
+                typeCache.put(genericType, bestProviderInfoMatch);
+            }
+        }
+        return bestProviderInstanceMatch;
+    }
+
+    final private static int CACHE_SIZE = 8;
+
+    private ThreadLocal<Map<MediaType, Map<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>>>
defaultWriterProviderCache = new ThreadLocal<Map<MediaType, Map<Class<?>, Map<Type,
MessageBodyProviderMatch<MessageBodyWriter>>>>>() {
+        @Override
+        public Map<MediaType, Map<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>>
initialValue() {
+            return new LinkedHashMap<MediaType, Map<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>>(
+                    CACHE_SIZE, 0.75f, true) {
+
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                public boolean removeEldestEntry(Map.Entry<MediaType, Map<Class<?>,
Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>> eldestEntry) {
+                    return size() > CACHE_SIZE;
+                }
+            };
+        }
+    };
+
+    private static class ClassToGenericTypeCache extends LinkedHashMap<Class<?>,
Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>> {
+
+        private static final long serialVersionUID = 1L;
+
+        public ClassToGenericTypeCache() {
+            super(CACHE_SIZE, 0.75f, true);
+        }
+
+        @Override
+        public boolean removeEldestEntry(Map.Entry<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>
eldestEntry) {
+            return size() > CACHE_SIZE;
+        }
+    }
+
+    private static class TypeToMessageBodyProviderMatchCache extends LinkedHashMap<Type,
MessageBodyProviderMatch<MessageBodyWriter>> {
+
+        private static final long serialVersionUID = 1L;
+
+        public TypeToMessageBodyProviderMatchCache() {
+            super(CACHE_SIZE, 0.75f, true);
+        }
+
+        @Override
+        public boolean removeEldestEntry(Map.Entry<Type, MessageBodyProviderMatch<MessageBodyWriter>>
eldestEntry) {
+            return size() > CACHE_SIZE;
+        }
+    }
+
+    private ThreadLocal<Map<MediaType, Map<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>>>
defaultReaderProviderCache = new ThreadLocal<Map<MediaType, Map<Class<?>, Map<Type,
ProviderInfo<MessageBodyReader>>>>>() {
+        @Override
+        public Map<MediaType, Map<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>>
initialValue() {
+            return new LinkedHashMap<MediaType, Map<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>>(
+                    CACHE_SIZE, 0.75f, true) {
+
+                private static final long serialVersionUID = 1L;
+
+                @Override
+                public boolean removeEldestEntry(Map.Entry<MediaType, Map<Class<?>,
Map<Type, ProviderInfo<MessageBodyReader>>>> eldestEntry) {
+                    return size() > CACHE_SIZE;
+                }
+            };
+        }
+    };
+
+    private static class ClassToGenericTypeReaderCache extends LinkedHashMap<Class<?>,
Map<Type, ProviderInfo<MessageBodyReader>>> {
+
+        private static final long serialVersionUID = 1L;
+
+        public ClassToGenericTypeReaderCache() {
+            super(CACHE_SIZE, 0.75f, true);
+        }
+
+        @Override
+        public boolean removeEldestEntry(Map.Entry<Class<?>, Map<Type, ProviderInfo<MessageBodyReader>>>
eldestEntry) {
+            return size() > CACHE_SIZE;
+        }
+    }
+
+    private static class TypeToMessageBodyProviderMatchReaderCache extends LinkedHashMap<Type,
ProviderInfo<MessageBodyReader>> {
+
+        private static final long serialVersionUID = 1L;
+
+        public TypeToMessageBodyProviderMatchReaderCache() {
+            super(CACHE_SIZE, 0.75f, true);
+        }
+
+        @Override
+        public boolean removeEldestEntry(Map.Entry<Type, ProviderInfo<MessageBodyReader>>
eldestEntry) {
+            return size() > CACHE_SIZE;
         }
-        return null;
     }
 
     /**
@@ -540,71 +630,127 @@
      * @return
      */
     @SuppressWarnings("unchecked")
-    private <T> MessageBodyProviderMatch<MessageBodyWriter> chooseMessageWriter(List<ProviderInfo<MessageBodyWriter>>
writers, Class<T> type, Type genericType, Annotation[] annotations, final MediaType
mediaType, RESTContext context) {
+    private <T> MessageBodyProviderMatch<MessageBodyWriter> chooseMessageWriter(List<ProviderInfo<MessageBodyWriter>>
writers, Class<T> type, Type genericType, Annotation[] annotations, final MediaType
mediaType, RESTContext context, boolean isDefaultProviders) {
         if (log.isDebugEnabled()) {
             log.debug("chooseMessageWriter, type= " + type.getName()
                     + ", genericType= " + genericType + ", mediaType= "
                     + (mediaType != null ? mediaType.toString() : "<null>"));
         }
 
-        List<MessageBodyProviderMatch> possibleWriters = new ArrayList<MessageBodyProviderMatch>();
+        ProviderInfo<MessageBodyWriter> bestProviderInfoMatch = null;
+        MessageBodyWriter bestProviderInstanceMatch = null;
+        MediaType bestIntersectedMediaType = null;
+        MediaType bestCompatibleMediaType = null;
+
+        MessageBodyProviderMatch<MessageBodyWriter> cacheHit = null;
+        Map<Type, MessageBodyProviderMatch<MessageBodyWriter>> typeCache = null;
+
         /*
-         * TODO possible performance improvement is not to call the
-         * MessageBodyWriter.isWritable method in matchesWriterCriterias
-         * until the mime types are compared and the writers are sorted. The
-         * penalty for the isWritable method could be significant.
+         * we can only cheat here for the default providers because we implemented them.
+         * other providers may do dangerous things that while aren't against the spec, aren't
exactly good.
+         * 
+         * there are a lot of things we know about the default providers that we don't know
about user providers.
+         * namely, they are singletons (because we currently don't support other provider
lifecycles but if we do we can easily make the change), their
+         * isWritable call does not check for annotations, media types, etc. and the most
likely writer will always be the most
+         * likely writer.
          */
+        if (isDefaultProviders) {
+            Map<MediaType, Map<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>>
defaultProviderCache = this.defaultWriterProviderCache
+                    .get();
+            Map<Class<?>, Map<Type, MessageBodyProviderMatch<MessageBodyWriter>>>
classCache = defaultProviderCache
+                    .get(mediaType);
+            if (classCache == null) {
+                classCache = new ClassToGenericTypeCache();
+                defaultProviderCache.put(mediaType, classCache);
+            }
+
+            typeCache = classCache.get(type);
+            if (typeCache == null) {
+                typeCache = new TypeToMessageBodyProviderMatchCache();
+                classCache.put(type, typeCache);
+            }
+
+            cacheHit = typeCache.get(genericType);
+            if (cacheHit != null) {
+                LifecycleManager mgr = LifecycleManagerFactory
+                        .getLifeCycleManager(cacheHit.getProviderInfo());
+                MessageBodyWriter instance = (MessageBodyWriter) mgr
+                        .createInstance(cacheHit.getProviderInfo(), context);
+                cacheHit.setWriter(instance);
+                return cacheHit;
+            }
+        }
+
         for (ProviderInfo<MessageBodyWriter> ep : writers) {
-            List<MediaType> availableMimeTypes = JAXRSUtils
-                    .intersectMimeTypes(Collections.singletonList(mediaType),
-                            ep.getProducesTypes());
-            if (availableMimeTypes.size() == 0) {
+            if (!ep.isMediaTypeCompatibleWithProduces(mediaType)) {
                 continue;
             }
 
-            Type t = ep
-                    .getParameterizedType()
-                    .get(
-                            org.apache.cxf.jaxrs.model.ProviderInfo.Type.MessageBodyWriter);
-            if (!isTypeCompatible(type, t)) {
+            if (!ep
+                    .isParameterizedTypeCompatible(
+                            org.apache.cxf.jaxrs.model.ProviderInfo.Type.MessageBodyWriter,
+                            type)) {
                 continue;
             }
 
+            MediaType epMostSpecificCompatible = null;
+            if (bestProviderInfoMatch != null) {
+                epMostSpecificCompatible = ep
+                        .getProducesTypesMostSpecificCompatibleWithMediaType(mediaType);
+                if (compareMediaTypesWithNullPossible(epMostSpecificCompatible,
+                        bestCompatibleMediaType) != -1) {
+                    continue;
+                }
+            }
+
             LifecycleManager mgr = LifecycleManagerFactory
                     .getLifeCycleManager(ep);
             MessageBodyWriter instance = (MessageBodyWriter) mgr
                     .createInstance(ep, context);
+
+            List<MediaType> availableMimeTypes = ep
+                    .getProducesTypesIntersectedWithMediaType(mediaType);
             for (MediaType intersectedMediaType : availableMimeTypes) {
                 if (instance.isWriteable(type, genericType, annotations,
-                        mediaType)) {
+                        intersectedMediaType)) {
                     if (log.isDebugEnabled()) {
                         log.debug("Found suitable MessageBodyWriter instance: "
                                 + instance.getClass().getName());
                     }
-                    possibleWriters.add(new MessageBodyProviderMatch(ep,
-                            instance, intersectedMediaType));
+
+                    bestProviderInfoMatch = ep;
+                    bestProviderInstanceMatch = instance;
+                    bestIntersectedMediaType = intersectedMediaType;
+                    if (epMostSpecificCompatible == null) {
+                        epMostSpecificCompatible = ep
+                                .getProducesTypesMostSpecificCompatibleWithMediaType(mediaType);
+                    }
+                    bestCompatibleMediaType = epMostSpecificCompatible;
+                    break;
                 }
             }
         }
 
-        if (possibleWriters.size() > 0) {
-            Collections.sort(possibleWriters,
-                    new Comparator<MessageBodyProviderMatch>() {
-                        public int compare(MessageBodyProviderMatch object1, MessageBodyProviderMatch
object2) {
-                            return new ProviderInfoProducesComparator<MessageBodyWriter>(
-                                    mediaType).compare(object1
-                                    .getProviderInfo(), object2
-                                    .getProviderInfo());
-                        }
-                    });
-            return possibleWriters.get(0);
+        if (bestProviderInfoMatch != null) {
+            cacheHit = new MessageBodyProviderMatch<MessageBodyWriter>(
+                    bestProviderInfoMatch, bestProviderInstanceMatch,
+                    bestIntersectedMediaType);
+            if (isDefaultProviders) {
+                /*
+                 * the following null check is redundant
+                 */
+                if (typeCache != null) {
+                    typeCache.put(genericType, cacheHit);
+                }
+            }
+            return cacheHit;
         }
         return null;
     }
 
     private static class MessageBodyProviderMatch<T> {
         final private ProviderInfo<T> provider;
-        final private T instance;
+        private T instance;
         final private MediaType mediaType;
 
         public MessageBodyProviderMatch(ProviderInfo<T> provider, T instance, MediaType
mediaType) {
@@ -621,93 +767,59 @@
             return instance;
         }
 
+        public void setWriter(T instance) {
+            this.instance = instance;
+        }
+
         public MediaType getMediaType() {
             return mediaType;
         }
     }
 
-    private final static boolean isTypeCompatible(Class<?> returnType, Type providerTypeArgument)
{
-        if (returnType == providerTypeArgument) {
-            return true;
-        } else if (providerTypeArgument instanceof Class) {
-            Class<?> argsType = (Class<?>) providerTypeArgument;
-            if (argsType.isAssignableFrom(returnType)) {
-                return true;
-            }
-        } else if (providerTypeArgument instanceof ParameterizedType) {
-            Class<?> argsType = (Class<?>) ((ParameterizedType) providerTypeArgument)
-                    .getRawType();
-            if (argsType.isAssignableFrom(returnType)) {
-                return true;
-            }
-        }
-        return false;
-    }
+    private static class ProviderInfoProducesComparator implements Comparator<ProviderInfo>
{
 
-    private static class ProviderInfoProducesComparator<T> implements Comparator<ProviderInfo<T>>
{
+        final private static ConcurrentMap<String, ProviderInfoProducesComparator>
map = new ConcurrentHashMap<String, ProviderInfoProducesComparator>();
 
-        final private MediaType mediaType;
-
-        public ProviderInfoProducesComparator(MediaType mt) {
-            this.mediaType = mt;
+        public static ProviderInfoProducesComparator getInstance(MediaType mt) {
+            String mtStr = mt.toString();
+            ProviderInfoProducesComparator comparator = map.get(mtStr);
+            if (comparator != null) {
+                return comparator;
+            }
+            comparator = new ProviderInfoProducesComparator(mt);
+            map.putIfAbsent(mtStr, comparator);
+            return comparator;
         }
 
-        public int compare(ProviderInfo<T> object1, ProviderInfo<T> object2)
{
-            List<MediaType> pi1MediaTypes = object1.getProducesTypes();
-            List<MediaType> pi2MediaTypes = object2.getProducesTypes();
-
-            MediaType pi1MostSpecificCompatible = findMostSpecificCompatibleMediaType(
-                    mediaType, pi1MediaTypes);
-            MediaType pi2MostSpecificCompatible = findMostSpecificCompatibleMediaType(
-                    mediaType, pi2MediaTypes);
-
-            return JAXRSUtils.compareMediaTypes(pi1MostSpecificCompatible,
-                    pi2MostSpecificCompatible);
-        }
-    }
-
-    private static class ProviderInfoConsumesComparator<T> implements Comparator<ProviderInfo<T>>
{
-
         final private MediaType mediaType;
 
-        public ProviderInfoConsumesComparator(MediaType mt) {
+        private ProviderInfoProducesComparator(MediaType mt) {
             this.mediaType = mt;
         }
 
-        public int compare(ProviderInfo<T> object1, ProviderInfo<T> object2)
{
-            List<MediaType> pi1MediaTypes = object1.getConsumesTypes();
-            List<MediaType> pi2MediaTypes = object2.getConsumesTypes();
-
-            MediaType pi1MostSpecificCompatible = findMostSpecificCompatibleMediaType(
-                    mediaType, pi1MediaTypes);
-            MediaType pi2MostSpecificCompatible = findMostSpecificCompatibleMediaType(
-                    mediaType, pi2MediaTypes);
-            return JAXRSUtils.compareMediaTypes(pi1MostSpecificCompatible,
+        public int compare(ProviderInfo object1, ProviderInfo object2) {
+            MediaType pi1MostSpecificCompatible = object1
+                    .getProducesTypesMostSpecificCompatibleWithMediaType(mediaType);
+            MediaType pi2MostSpecificCompatible = object2
+                    .getProducesTypesMostSpecificCompatibleWithMediaType(mediaType);
+
+            return compareMediaTypesWithNullPossible(pi1MostSpecificCompatible,
                     pi2MostSpecificCompatible);
         }
     }
 
-    private static MediaType findMostSpecificCompatibleMediaType(MediaType typeGiven, List<MediaType>
availableTypes) {
-        if (typeGiven == null || availableTypes == null) {
-            return null;
-        }
-        MediaType mostSpecificCompatibleType = null;
-        for (MediaType mt : availableTypes) {
-            if (typeGiven.isCompatible(mt)) {
-                if (mostSpecificCompatibleType == null) {
-                    mostSpecificCompatibleType = mt;
-                } else {
-                    if (!mt.isWildcardType()
-                            && mostSpecificCompatibleType.isWildcardType()) {
-                        mostSpecificCompatibleType = mt;
-                    } else if (!mostSpecificCompatibleType.isWildcardType()
-                            && mostSpecificCompatibleType.isWildcardSubtype()
-                            && !mt.isWildcardType() && !mt.isWildcardSubtype())
{
-                        mostSpecificCompatibleType = mt;
-                    }
-                }
-            }
+    private static final int compareMediaTypesWithNullPossible(MediaType pi1MostSpecificCompatible,
MediaType pi2MostSpecificCompatible) {
+        if (pi1MostSpecificCompatible == null
+                && pi2MostSpecificCompatible == null) {
+            return 0;
+        } else if (pi1MostSpecificCompatible == null
+                && pi2MostSpecificCompatible != null) {
+            return 1;
+        } else if (pi1MostSpecificCompatible != null
+                && pi2MostSpecificCompatible == null) {
+            return -1;
         }
-        return mostSpecificCompatibleType;
+        return JAXRSUtils.compareMediaTypes(pi1MostSpecificCompatible,
+                pi2MostSpecificCompatible);
     }
 }

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/ProviderFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/SourceProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/SourceProvider.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/SourceProvider.java
(original)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/SourceProvider.java
Sat Jun 27 00:02:26 2009
@@ -42,6 +42,8 @@
 import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.w3c.dom.Document;
 
 import com.ibm.ws.jaxrs.i18n.Messages;
@@ -51,6 +53,8 @@
 @Consumes(value = { "text/xml", "application/xml", "application/*+xml" })
 public class SourceProvider implements MessageBodyReader<Source>, MessageBodyWriter<Source>
{
 
+    final private static Log log = LogFactory.getLog(SourceProvider.class);
+
     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
         return Source.class.isAssignableFrom(type);
     }
@@ -94,7 +98,7 @@
             Transformer t = tf.newTransformer();
             t.transform(source, result);
         } catch (TransformerException te) {
-            te.printStackTrace();
+            log.debug("Encountered TransformerException", te);
         }
     }
 

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/SourceProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/StringProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/StringProvider.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
    (empty)

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/StringProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeanStreamSerializer.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeanStreamSerializer.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
    (empty)

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeanStreamSerializer.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeansElementProvider.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeansElementProvider.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
    (empty)

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/provider/XMLBeansElementProvider.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/AnnotationUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/AnnotationUtils.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
    (empty)

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/AnnotationUtils.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/ClassResourceInfoComparator.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/ClassResourceInfoComparator.java?rev=788908&view=auto
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/ClassResourceInfoComparator.java
(added)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/ClassResourceInfoComparator.java
Sat Jun 27 00:02:26 2009
@@ -0,0 +1,51 @@
+/*
+ * 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.utils;
+
+import java.util.Comparator;
+
+import org.apache.cxf.jaxrs.model.ClassResourceInfo;
+
+/**
+ *  Compares two ClassResourceInfo by literal charcter names.
+ */
+public class ClassResourceInfoComparator implements Comparator<ClassResourceInfo> {
+
+    private static final ClassResourceInfoComparator comparator = new ClassResourceInfoComparator();
+
+    public static ClassResourceInfoComparator getInstance() {
+        return comparator;
+    }
+
+    public int compare(ClassResourceInfo cr1, ClassResourceInfo cr2) {
+
+        String l1 = cr1.getURITemplate().getLiteralChars();
+        String l2 = cr2.getURITemplate().getLiteralChars();
+        if (!l1.equals(l2)) {
+            // descending order
+            return l1.length() < l2.length() ? 1 : -1;
+        }
+
+        int g1 = cr1.getURITemplate().getNumberOfGroups();
+        int g2 = cr2.getURITemplate().getNumberOfGroups();
+        // descending order
+        return g1 < g2 ? 1 : g1 > g2 ? -1 : 0;
+    }
+}

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/ClassResourceInfoComparator.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/HttpUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/HttpUtils.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/HttpUtils.java (original)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/HttpUtils.java Sat Jun
27 00:02:26 2009
@@ -19,43 +19,18 @@
 
 package org.apache.cxf.jaxrs.utils;
 
-import java.net.URI;
 import java.util.List;
 import java.util.Map;
 
-import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.PathSegment;
 
 import org.apache.cxf.jaxrs.impl.PathSegmentImpl;
 
-import com.ibm.ws.jaxrs.context.ContextConstants;
-import com.ibm.ws.jaxrs.context.RESTContext;
-
 public final class HttpUtils {
-    private static final String LOCAL_IP_ADDRESS = "127.0.0.1";
-    private static final String LOCAL_HOST = "localhost";
 
     private HttpUtils() {
     }
 
-    public static URI toAbsoluteUri(URI u, RESTContext context) {
-        if (!u.isAbsolute()) {
-            HttpServletRequest httpRequest = (HttpServletRequest) context
-                    .getProperty(ContextConstants.SERVLET_REQUEST);
-            if (httpRequest != null) {
-                String scheme = httpRequest.isSecure() ? "https" : "http";
-                String host = httpRequest.getLocalName();
-                if (LOCAL_IP_ADDRESS.equals(host)) {
-                    host = LOCAL_HOST;
-                }
-                int port = httpRequest.getLocalPort();
-                return URI.create(scheme + "://" + host + ':' + port
-                        + u.toString());
-            }
-        }
-        return u;
-    }
-
     public static String fromPathSegment(PathSegment ps) {
         if (PathSegmentImpl.class.isAssignableFrom(ps.getClass())) {
             return ((PathSegmentImpl) ps).getOriginalPath();

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/HttpUtils.java
------------------------------------------------------------------------------
    svn:executable = *

Modified: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=788908&r1=788907&r2=788908&view=diff
==============================================================================
--- incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original)
+++ incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/InjectionUtils.java Sat
Jun 27 00:02:26 2009
@@ -201,7 +201,6 @@
                 String headerId = ((HeaderParam) annotation).value();
                 MultivaluedMap<String, String> headerValues = (MultivaluedMap<String,
String>) context
                         .getProperty(ContextConstants.HTTP_HEADER_VALUES);
-                headerId = headerId.toLowerCase();
                 values = headerValues != null ? headerValues.get(headerId)
                         : null;
                 isHeaderOrCookieParam = true;
@@ -232,9 +231,8 @@
                                 formValues);
                     }
                 } else {
-                    formValues = new MetadataMap<String, String>(
-                            (Map<String, List<String>>) context
-                                    .getProperty(ContextConstants.FORM_VALUES));
+                    formValues = (MultivaluedMap<String, String>) context
+                            .getProperty(ContextConstants.FORM_VALUES);
                 }
 
                 values = formValues != null ? formValues.get(formParamId)
@@ -468,6 +466,12 @@
             c = pClass.getConstructor(new Class<?>[] { String.class });
         } catch (Exception ex) {
             // try valueOf
+            if (log.isDebugEnabled()) {
+                log
+                        .debug(
+                                "Could not find a String constructor to handle the parameter",
+                                ex);
+            }
         }
 
         if (c != null) {
@@ -504,8 +508,12 @@
         try {
             m = pClass.getMethod("valueOf", new Class<?>[] { String.class });
         } catch (Exception ex) {
-            // no luck
-            ex.printStackTrace();
+            if (log.isDebugEnabled()) {
+                log
+                        .debug(
+                                "Could not find a String constructor or valueOf method to
handle the parameter",
+                                ex);
+            }
         }
         if (m != null && Modifier.isStatic(m.getModifiers())) {
             if (log.isDebugEnabled()) {

Propchange: incubator/wink/contrib/ibm-jaxrs/src/org/apache/cxf/jaxrs/utils/InjectionUtils.java
------------------------------------------------------------------------------
    svn:executable = *



Mime
View raw message