package org.etk.core.rest.impl; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.MessageBodyReader; import javax.ws.rs.ext.MessageBodyWriter; import javax.ws.rs.ext.Providers; import org.etk.common.logging.Logger; import org.etk.core.rest.ComponentLifecycleScope; import org.etk.core.rest.ContainerObjectFactory; import org.etk.core.rest.FilterDescriptor; import org.etk.core.rest.PerRequestObjectFactory; import org.etk.core.rest.RequestFilter; import org.etk.core.rest.ResponseFilter; import org.etk.core.rest.SingletonObjectFactory; import org.etk.core.rest.impl.header.MediaTypeHelper; import org.etk.core.rest.impl.provider.ByteEntityProvider; import org.etk.core.rest.impl.provider.DOMSourceEntityProvider; import org.etk.core.rest.impl.provider.DataSourceEntityProvider; import org.etk.core.rest.impl.provider.FileEntityProvider; import org.etk.core.rest.impl.provider.InputStreamEntityProvider; import org.etk.core.rest.impl.provider.JAXBContextResolver; import org.etk.core.rest.impl.provider.JAXBElementEntityProvider; import org.etk.core.rest.impl.provider.JAXBObjectEntityProvider; import org.etk.core.rest.impl.provider.JsonEntityProvider; import org.etk.core.rest.impl.provider.MultipartFormDataEntityProvider; import org.etk.core.rest.impl.provider.MultivaluedMapEntityProvider; import org.etk.core.rest.impl.provider.ProviderDescriptorImpl; import org.etk.core.rest.impl.provider.ReaderEntityProvider; import org.etk.core.rest.impl.provider.SAXSourceEntityProvider; import org.etk.core.rest.impl.provider.StreamOutputEntityProvider; import org.etk.core.rest.impl.provider.StreamSourceEntityProvider; import org.etk.core.rest.impl.provider.StringEntityProvider; import org.etk.core.rest.impl.resource.ResourceDescriptorValidator; import org.etk.core.rest.impl.uri.UriPattern; import org.etk.core.rest.method.MethodInvokerFilter; import org.etk.core.rest.provider.ProviderDescriptor; import org.etk.core.rest.resource.ResourceDescriptorVisitor; import org.etk.core.rest.util.MediaTypeMap; import org.etk.core.rest.util.MediaTypeMultivaluedMap; import org.etk.core.rest.util.UriPatternMap; public class ProviderBinder implements Providers { /** * Logger. */ private static final Logger LOG = Logger.getLogger(ProviderBinder.class); /** * Providers instance. * * @see Providers */ private static AtomicReference<ProviderBinder> ainst = new AtomicReference<ProviderBinder>(); /** * @return instance of {@link ProviderBinder} */ public static ProviderBinder getInstance() { ProviderBinder t = ainst.get(); if (t == null) { ainst.compareAndSet(null, new ProviderBinder()); t = ainst.get(); } return t; } public static void setInstance(ProviderBinder inst) { ainst.set(inst); } public ProviderBinder() { init(); } /** * Add prepared providers. */ void init() { // TODO remove this hard code ByteEntityProvider baep = new ByteEntityProvider(); addMessageBodyReader(baep); addMessageBodyWriter(baep); DataSourceEntityProvider dsep = new DataSourceEntityProvider(); addMessageBodyReader(dsep); addMessageBodyWriter(dsep); DOMSourceEntityProvider domsep = new DOMSourceEntityProvider(); addMessageBodyReader(domsep); addMessageBodyWriter(domsep); FileEntityProvider fep = new FileEntityProvider(); addMessageBodyReader(fep); addMessageBodyWriter(fep); MultivaluedMapEntityProvider mvep = new MultivaluedMapEntityProvider(); addMessageBodyReader(mvep); addMessageBodyWriter(mvep); InputStreamEntityProvider isep = new InputStreamEntityProvider(); addMessageBodyReader(isep); addMessageBodyWriter(isep); ReaderEntityProvider rep = new ReaderEntityProvider(); addMessageBodyReader(rep); addMessageBodyWriter(rep); SAXSourceEntityProvider saxep = new SAXSourceEntityProvider(); addMessageBodyReader(saxep); addMessageBodyWriter(saxep); StreamSourceEntityProvider ssep = new StreamSourceEntityProvider(); addMessageBodyReader(ssep); addMessageBodyWriter(ssep); StringEntityProvider sep = new StringEntityProvider(); addMessageBodyReader(sep); addMessageBodyWriter(sep); StreamOutputEntityProvider soep = new StreamOutputEntityProvider(); addMessageBodyReader(soep); addMessageBodyWriter(soep); JsonEntityProvider jsep = new JsonEntityProvider(); addMessageBodyReader(jsep); addMessageBodyWriter(jsep); // per-request mode , Providers should be injected addMessageBodyReader(JAXBElementEntityProvider.class); addMessageBodyWriter(JAXBElementEntityProvider.class); addMessageBodyReader(JAXBObjectEntityProvider.class); addMessageBodyWriter(JAXBObjectEntityProvider.class); // per-request mode , HttpServletRequest should be injected in provider addMessageBodyReader(MultipartFormDataEntityProvider.class); // JAXB context addContextResolver(JAXBContextResolver.class, null, ComponentLifecycleScope.CONTAINER); } /** * Read message body providers. Also see {@link MediaTypeMultivaluedMap}. */ private final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> writeProviders = new MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>>(); /** * Read message body providers. Also see {@link MediaTypeMultivaluedMap}. */ private final MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>> readProviders = new MediaTypeMultivaluedMap<ObjectFactory<ProviderDescriptor>>(); /** * Exception mappers, see {@link ExceptionMapper}. */ private final Map<Class<? extends Throwable>, ObjectFactory<ProviderDescriptor>> exceptionMappers = new HashMap<Class<? extends Throwable>, ObjectFactory<ProviderDescriptor>>(); /** * Context resolvers. */ private final Map<Class<?>, MediaTypeMap<ObjectFactory<ProviderDescriptor>>> contextResolvers = new HashMap<Class<?>, MediaTypeMap<ObjectFactory<ProviderDescriptor>>>(); /** * Request filters, see {@link RequestFilter}. */ private final UriPatternMap<ObjectFactory<FilterDescriptor>> requestFilters = new UriPatternMap<ObjectFactory<FilterDescriptor>>(); /** * Response filters, see {@link ResponseFilter}. */ private final UriPatternMap<ObjectFactory<FilterDescriptor>> responseFilters = new UriPatternMap<ObjectFactory<FilterDescriptor>>(); /** * Method invoking filters. */ private final UriPatternMap<ObjectFactory<FilterDescriptor>> invokerFilters = new UriPatternMap<ObjectFactory<FilterDescriptor>>(); /** * Validator. */ private final ResourceDescriptorVisitor rdv = ResourceDescriptorValidator.getInstance(); // /** * Add per-request ContextResolver. * * @param clazz class of implementation ContextResolver */ @SuppressWarnings("unchecked") public void addContextResolver(Class<? extends ContextResolver> clazz) { try { addContextResolver(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add ContextResolver " + clazz.getName(), e); } } /** * Add singleton ContextResolver. * * @param instance ContextResolver instance */ @SuppressWarnings("unchecked") public void addContextResolver(ContextResolver instance) { Class<? extends ContextResolver> clazz = instance.getClass(); try { addContextResolver(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add ContextResolver " + clazz.getName(), e); } } /** * Add per-request ExceptionMapper. * * @param clazz class of implementation ExceptionMapper */ @SuppressWarnings("unchecked") public void addExceptionMapper(Class<? extends ExceptionMapper> clazz) { try { addExceptionMapper(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add ExceptionMapper " + clazz.getName(), e); } } /** * Add singleton ExceptionMapper. * * @param instance ExceptionMapper instance */ @SuppressWarnings("unchecked") public void addExceptionMapper(ExceptionMapper instance) { Class<? extends ExceptionMapper> clazz = instance.getClass(); try { addExceptionMapper(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add ExceptionMapper " + clazz.getName(), e); } } /** * Add per-request MessageBodyReader. * * @param clazz class of implementation MessageBodyReader */ @SuppressWarnings("unchecked") public void addMessageBodyReader(Class<? extends MessageBodyReader> clazz) { try { addMessageBodyReader(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add MessageBodyReader " + clazz.getName(), e); } } /** * Add singleton MessageBodyReader. * * @param instance MessageBodyReader instance */ @SuppressWarnings("unchecked") public void addMessageBodyReader(MessageBodyReader instance) { Class<? extends MessageBodyReader> clazz = instance.getClass(); try { addMessageBodyReader(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add MessageBodyReader " + clazz.getName(), e); } } /** * Add per-request MessageBodyWriter. * * @param clazz class of implementation MessageBodyWriter */ @SuppressWarnings("unchecked") public void addMessageBodyWriter(Class<? extends MessageBodyWriter> clazz) { try { addMessageBodyWriter(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add MessageBodyWriter " + clazz.getName(), e); } } /** * Add singleton MessageBodyWriter. * * @param instance MessageBodyWriter instance */ @SuppressWarnings("unchecked") public void addMessageBodyWriter(MessageBodyWriter instance) { Class<? extends MessageBodyWriter> clazz = instance.getClass(); try { addMessageBodyWriter(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add MessageBodyWriter ", e); } } /** * Get list of most acceptable writer's media type for specified type. * * @param type type * @param genericType generic type * @param annotations annotations * @return sorted acceptable media type collection * @see MediaTypeHelper#MEDIA_TYPE_COMPARATOR */ @SuppressWarnings("unchecked") public List<MediaType> getAcceptableWriterMediaTypes(Class<?> type, Type genericType, Annotation[] annotations) { List<MediaType> l = new ArrayList<MediaType>(); for (Map.Entry<MediaType, List<ObjectFactory<ProviderDescriptor>>> e : writeProviders.entrySet()) { MediaType mime = e.getKey(); for (ObjectFactory pf : e.getValue()) { MessageBodyWriter writer = (MessageBodyWriter) pf.getInstance(ApplicationContextImpl.getCurrent()); if (writer.isWriteable(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE)) l.add(mime); } } Collections.sort(l, MediaTypeHelper.MEDIA_TYPE_COMPARATOR); return l; } /** * {@inheritDoc} */ public <T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType) { MediaTypeMap<ObjectFactory<ProviderDescriptor>> pm = contextResolvers.get(contextType); ContextResolver<T> resolver = null; if (pm != null) { if (mediaType == null) return _getContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE); resolver = _getContextResolver(pm, contextType, mediaType); if (resolver == null) resolver = _getContextResolver(pm, contextType, new MediaType(mediaType.getType(), MediaType.MEDIA_TYPE_WILDCARD)); if (resolver == null) resolver = _getContextResolver(pm, contextType, MediaTypeHelper.DEFAULT_TYPE); } return resolver; } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type) { ObjectFactory pf = exceptionMappers.get(type); if (pf != null) return (ExceptionMapper<T>) pf.getInstance(ApplicationContextImpl.getCurrent()); return null; } /** * {@inheritDoc} */ public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (mediaType == null) return _getMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE); MessageBodyReader<T> reader = _getMessageBodyReader(type, genericType, annotations, mediaType); if (reader == null) reader = _getMessageBodyReader(type, genericType, annotations, new MediaType(mediaType.getType(), MediaType.MEDIA_TYPE_WILDCARD)); if (reader == null) reader = _getMessageBodyReader(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE); return reader; } /** * {@inheritDoc} */ public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { if (mediaType == null) return _getMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE); MessageBodyWriter<T> writer = _getMessageBodyWriter(type, genericType, annotations, mediaType); if (writer == null) writer = _getMessageBodyWriter(type, genericType, annotations, new MediaType(mediaType.getType(), MediaType.MEDIA_TYPE_WILDCARD)); if (writer == null) writer = _getMessageBodyWriter(type, genericType, annotations, MediaTypeHelper.DEFAULT_TYPE); return writer; } /** * Add per-request MethodInvokerFilter. * * @param clazz class of implementation MethodInvokerFilter */ public void addMethodInvokerFilter(Class<? extends MethodInvokerFilter> clazz) { try { addMethodInvokerFilter(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add MethodInvokerFilter " + clazz.getName(), e); } } /** * Add singleton MethodInvokerFilter. * * @param instance MethodInvokerFilter instance */ public void addMethodInvokerFilter(MethodInvokerFilter instance) { Class<? extends MethodInvokerFilter> clazz = instance.getClass(); try { addMethodInvokerFilter(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add RequestFilter " + clazz.getName(), e); } } /** * Add per-request RequestFilter. * * @param clazz class of implementation RequestFilter */ public void addRequestFilter(Class<? extends RequestFilter> clazz) { try { addRequestFilter(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add MethodInvokerFilter " + clazz.getName(), e); } } /** * Add singleton RequestFilter. * * @param instance RequestFilter instance */ public void addRequestFilter(RequestFilter instance) { Class<? extends RequestFilter> clazz = instance.getClass(); try { addRequestFilter(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add RequestFilter " + clazz.getName(), e); } } /** * Add per-request ResponseFilter. * * @param clazz class of implementation ResponseFilter */ public void addResponseFilter(Class<? extends ResponseFilter> clazz) { try { addResponseFilter(clazz, null, ComponentLifecycleScope.PER_REQUEST); } catch (Exception e) { LOG.error("Failed add ResponseFilter " + clazz.getName(), e); } } /** * Add singleton ResponseFilter. * * @param instance ResponseFilter instance */ public void addResponseFilter(ResponseFilter instance) { Class<? extends ResponseFilter> clazz = instance.getClass(); try { addResponseFilter(clazz, instance, ComponentLifecycleScope.SINGLETON); } catch (Exception e) { LOG.error("Failed add ResponseFilter " + clazz.getName(), e); } } /** * @param path request path * @return acceptable method invocation filters */ public List<ObjectFactory<FilterDescriptor>> getMethodInvokerFilters(String path) { return getMatchedFilters(path, invokerFilters); } /** * @param path request path * @return acceptable request filters */ public List<ObjectFactory<FilterDescriptor>> getRequestFilters(String path) { return getMatchedFilters(path, requestFilters); } /** * @param path request path * @return acceptable response filters */ public List<ObjectFactory<FilterDescriptor>> getResponseFilters(String path) { return getMatchedFilters(path, responseFilters); } /** * @param path request path * @param m filter map * @return acceptable filter * @see #getMethodInvokerFilters(String) * @see #getRequestFilters(String) * @see #getResponseFilters(String) */ private List<ObjectFactory<FilterDescriptor>> getMatchedFilters(String path, UriPatternMap<ObjectFactory<FilterDescriptor>> m) { List<ObjectFactory<FilterDescriptor>> l = new ArrayList<ObjectFactory<FilterDescriptor>>(); List<String> capturingValues = new ArrayList<String>(); for (Map.Entry<UriPattern, List<ObjectFactory<FilterDescriptor>>> e : m.entrySet()) { UriPattern uriPattern = e.getKey(); if (uriPattern != null) { if (e.getKey().match(path, capturingValues)) { int len = capturingValues.size(); if (capturingValues.get(len - 1) != null && !"/".equals(capturingValues.get(len - 1))) continue; // not matched } else { continue; // not matched } } // if matched or UriPattern is null l.addAll(e.getValue()); } return l; } /** * @param <T> context resolver actual type argument * @param pm MediaTypeMap that contains ProviderFactories that may produce * objects that are instance of T * @param contextType context type * @param mediaType media type that can be used to restrict context resolver * choose * @return ContextResolver or null if nothing was found */ @SuppressWarnings("unchecked") private <T> ContextResolver<T> _getContextResolver(MediaTypeMap<ObjectFactory<ProviderDescriptor>> pm, Class<T> contextType, MediaType mediaType) { for (Map.Entry<MediaType, ObjectFactory<ProviderDescriptor>> e : pm.entrySet()) { if (mediaType.isCompatible(e.getKey())) { return (ContextResolver<T>) e.getValue().getInstance(ApplicationContextImpl.getCurrent()); } } return null; } /** * Looking for message body reader according to supplied entity class, entity * generic type, annotations and content type. * * @param <T> message body reader actual type argument * @param type entity type * @param genericType entity generic type * @param annotations annotations * @param mediaType entity content type * @return message body reader or null if no one was found. */ @SuppressWarnings("unchecked") private <T> MessageBodyReader<T> _getMessageBodyReader(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { for (ObjectFactory pf : readProviders.getList(mediaType)) { MessageBodyReader reader = (MessageBodyReader) pf.getInstance(ApplicationContextImpl.getCurrent()); if (reader.isReadable(type, genericType, annotations, mediaType)) return reader; } return null; } /** * Looking for message body writer according to supplied entity class, entity * generic type, annotations and content type. * * @param <T> message body writer actual type argument * @param type entity type * @param genericType entity generic type * @param annotations annotations * @param mediaType content type in which entity should be represented * @return message body writer or null if no one was found. */ @SuppressWarnings("unchecked") private <T> MessageBodyWriter<T> _getMessageBodyWriter(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType) { for (ObjectFactory pf : writeProviders.getList(mediaType)) { MessageBodyWriter writer = (MessageBodyWriter) pf.getInstance(ApplicationContextImpl.getCurrent()); if (writer.isWriteable(type, genericType, annotations, mediaType)) return writer; } return null; } /** * @param clazz ContextResolver class * @param instance ContextResolver instance, may be null if not singleton * instance * @param scope ComponentLifecycleScope */ @SuppressWarnings("unchecked") public void addContextResolver(Class<? extends ContextResolver> clazz, ContextResolver instance, ComponentLifecycleScope scope) { for (Type type : clazz.getGenericInterfaces()) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; if (ContextResolver.class == pt.getRawType()) { Type[] atypes = pt.getActualTypeArguments(); if (atypes.length > 1) throw new RuntimeException("Unable strong determine actual type argument, more then one type found."); Class<?> aclazz = (Class<?>) atypes[0]; MediaTypeMap<ObjectFactory<ProviderDescriptor>> pm = contextResolvers.get(aclazz); if (pm == null) { pm = new MediaTypeMap<ObjectFactory<ProviderDescriptor>>(); contextResolvers.put(aclazz, pm); } ProviderDescriptor descriptor = new ProviderDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<ProviderDescriptor> factory = null; switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<ProviderDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("ContextResolver instance is null."); factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor); break; } for (MediaType mime : factory.getObjectModel().produces()) { if (pm.get(mime) != null) { String msg = "ContextResolver for " + aclazz.getName() + " and media type " + mime + " already registered."; throw new RuntimeException(msg); } else { pm.put(mime, factory); } } } } } } /** * @param clazz MessageBodyreader class * @param instance MessageBodyReader, may be null if not singleton instance * @param scope ComponentLifecycleScope */ @SuppressWarnings("unchecked") public void addMessageBodyReader(Class<? extends MessageBodyReader> clazz, MessageBodyReader instance, ComponentLifecycleScope scope) { ProviderDescriptor descriptor = new ProviderDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<ProviderDescriptor> factory = null; switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<ProviderDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("MessageBodyReader instance is null."); factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor); break; } // MessageBodyReader is smart component and can determine which type it // supports, see method MessageBodyReader.isReadable. So here does not // check is reader for the same Java and media type already exists. // Let it be under developer's control. for (MediaType mime : factory.getObjectModel().consumes()) readProviders.getList(mime).add(factory); } /** * @param clazz MessageBodyWriter class * @param instance MessageBodyWriter, may be null if not singleton instance * @param scope ComponentLifecycleScope */ @SuppressWarnings("unchecked") public void addMessageBodyWriter(Class<? extends MessageBodyWriter> clazz, MessageBodyWriter instance, ComponentLifecycleScope scope) { ProviderDescriptor descriptor = new ProviderDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<ProviderDescriptor> factory = null; switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<ProviderDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("MessageBodyWriter instance is null."); factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor); break; } // MessageBodyWriter is smart component and can determine which type it // supports, see method MessageBodyWriter.isWriteable. So here does not // check is writer for the same Java and media type already exists. // Let it be under developer's control. for (MediaType mime : factory.getObjectModel().produces()) writeProviders.getList(mime).add(factory); } /** * @param clazz ExceptionMapper class * @param instance ExceptionMapper instance, may be null if not singleton * instance * @param scope ComponentLifecycleScope */ @SuppressWarnings("unchecked") public void addExceptionMapper(Class<? extends ExceptionMapper> clazz, ExceptionMapper instance, ComponentLifecycleScope scope) { for (Type type : clazz.getGenericInterfaces()) { if (type instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) type; if (ExceptionMapper.class == pt.getRawType()) { Type[] atypes = pt.getActualTypeArguments(); if (atypes.length > 1) throw new RuntimeException("Unable strong determine actual type argument, more then one type found."); Class<? extends Throwable> exc = (Class<? extends Throwable>) atypes[0]; if (exceptionMappers.get(exc) != null) { String msg = "ExceptionMapper for exception " + exc + " already registered."; throw new RuntimeException(msg); } ProviderDescriptor descriptor = new ProviderDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<ProviderDescriptor> factory = null; switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<ProviderDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("ExceptionMapper instance is null."); factory = new SingletonObjectFactory<ProviderDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<ProviderDescriptor>(descriptor); break; } exceptionMappers.put(exc, factory); } } } } /** * @param clazz RequestFilter class * @param instance RequestFilter instance, may be null if not singleton * instance * @param scope ComponentLifecycleScope */ public void addRequestFilter(Class<? extends RequestFilter> clazz, RequestFilter instance, ComponentLifecycleScope scope) { FilterDescriptor descriptor = new FilterDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<FilterDescriptor> factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("RequestFilter instance is null."); factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<FilterDescriptor>(descriptor); break; } requestFilters.getList(descriptor.getUriPattern()).add(factory); } /** * @param clazz ResponseFilter class * @param instance ResponseFilter instance, may be null if not singleton * instance * @param scope ComponentLifecycleScope */ public void addResponseFilter(Class<? extends ResponseFilter> clazz, ResponseFilter instance, ComponentLifecycleScope scope) { FilterDescriptor descriptor = new FilterDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<FilterDescriptor> factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("ResponseFilter instance is null."); factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<FilterDescriptor>(descriptor); break; } responseFilters.getList(descriptor.getUriPattern()).add(factory); } /** * @param clazz MethodInvokerFilter class * @param instance MethodInvokerFilter instance, may be null if not singleton * instance * @param scope ComponentLifecycleScope */ public void addMethodInvokerFilter(Class<? extends MethodInvokerFilter> clazz, MethodInvokerFilter instance, ComponentLifecycleScope scope) { FilterDescriptor descriptor = new FilterDescriptorImpl(clazz); descriptor.accept(rdv); ObjectFactory<FilterDescriptor> factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); switch (scope) { case PER_REQUEST: factory = new PerRequestObjectFactory<FilterDescriptor>(descriptor); break; case SINGLETON: if (instance == null) throw new NullPointerException("MethodInvokerFilter instance is null."); factory = new SingletonObjectFactory<FilterDescriptor>(descriptor, instance); break; case CONTAINER: factory = new ContainerObjectFactory<FilterDescriptor>(descriptor); break; } invokerFilters.getList(descriptor.getUriPattern()).add(factory); } }