public <T> T getResource(Class<T> c) {
return c.cast(getResourceComponentProvider(c).getInstance(context));
}
};
final ProviderServices providerServices = new ProviderServices(
ServerSide.class,
this.cpFactory,
resourceConfig.getProviderClasses(),
resourceConfig.getProviderSingletons());
injectableFactory.add(new ContextInjectableProvider<ProviderServices>(
ProviderServices.class, providerServices));
injectableFactory.add(new ContextInjectableProvider<ResourceMethodCustomInvokerDispatchFactory>(
ResourceMethodCustomInvokerDispatchFactory.class, new ResourceMethodCustomInvokerDispatchFactory(providerServices)));
// Add injectable provider for @ParentRef
injectableFactory.add(
new InjectableProvider<ParentRef, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, ParentRef a, Type t) {
if (!(t instanceof Class))
return null;
final Class target = ReflectionHelper.getDeclaringClass(cc.getAccesibleObject());
final Class inject = (Class)t;
return new Injectable<Object>() {
@Override
public Object getValue() {
final UriInfo ui = context.getUriInfo();
final List l = ui.getMatchedResources();
final Object parent = getParent(l, target);
if (parent == null) return null;
try {
return inject.cast(parent);
} catch (ClassCastException ex) {
throw new ContainerException(
"The parent resource is expected to be of class " + inject.getName() +
" but is of class " + parent.getClass().getName(),
ex);
}
}
private Object getParent(List l, Class target) {
if (l.isEmpty()) {
return null;
} else if (l.size() == 1) {
return (l.get(0).getClass() == target) ? null : l.get(0);
} else {
return (l.get(0).getClass() == target) ? l.get(1) : l.get(0);
}
}
};
}
});
// Add injectable provider for @Inject
injectableFactory.add(
new InjectableProvider<Inject, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, Inject a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
injectableFactory.add(
new InjectableProvider<Inject, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.Undefined;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, Inject a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
if (rcp.getScope() == ComponentScope.PerRequest)
return null;
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
injectableFactory.add(
new InjectableProvider<Inject, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, Inject a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
if (rcp.getScope() != ComponentScope.Singleton)
return null;
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
// Add injectable provider for @ResourceRef
injectableFactory.add(
new InjectableProvider<InjectParam, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, InjectParam a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
injectableFactory.add(
new InjectableProvider<InjectParam, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.Undefined;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, InjectParam a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
if (rcp.getScope() == ComponentScope.PerRequest)
return null;
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
injectableFactory.add(
new InjectableProvider<InjectParam, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
@Override
public Injectable<Object> getInjectable(ComponentContext cc, InjectParam a, Type t) {
if (!(t instanceof Class))
return null;
final ResourceComponentProvider rcp = getResourceComponentProvider(cc, (Class)t);
if (rcp.getScope() != ComponentScope.Singleton)
return null;
return new Injectable<Object>() {
@Override
public Object getValue() {
return rcp.getInstance(context);
}
};
}
});
// Allow injection of features and properties
injectableFactory.add(new ContextInjectableProvider<FeaturesAndProperties>(
FeaturesAndProperties.class, resourceConfig));
// Allow injection of resource config
// Since the resourceConfig reference can change refer to the
// reference directly.
injectableFactory.add(
new InjectableProvider<Context, Type>() {
@Override
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
@Override
public Injectable<ResourceConfig> getInjectable(ComponentContext cc, Context a, Type t) {
if (t != ResourceConfig.class)
return null;
return new Injectable<ResourceConfig>() {
@Override
public ResourceConfig getValue() {
return resourceConfig;
}
};
}
});
// Allow injection of resource context
injectableFactory.add(new ContextInjectableProvider<ResourceContext>(
ResourceContext.class, resourceContext));
// Configure the injectable factory with declared providers
injectableFactory.configure(providerServices);
boolean updateRequired = false;
// Create application-declared Application instance as a component
if (rc instanceof DeferredResourceConfig) {
final DeferredResourceConfig drc = (DeferredResourceConfig)rc;
// Check if resource config has already been cloned
if (resourceConfig == drc)
resourceConfig = drc.clone();
final DeferredResourceConfig.ApplicationHolder da = drc.getApplication(cpFactory);
resourceConfig.add(da.getApplication());
updateRequired = true;
injectableFactory.add(new ContextInjectableProvider<Application>(
Application.class, da.getOriginalApplication()));
} else {
injectableFactory.add(new ContextInjectableProvider<FeaturesAndProperties>(
Application.class, resourceConfig));
}
// Pipelined, decentralized configuration
for(ResourceConfigurator configurator : providerServices.getProviders(ResourceConfigurator.class)) {
configurator.configure(this.resourceConfig);
updateRequired = true;
}
// Validate the resource config
this.resourceConfig.validate();
if (updateRequired) {
// Check if application modified provider classes or singletons
providerServices.update(resourceConfig.getProviderClasses(),
resourceConfig.getProviderSingletons(), injectableFactory);
}
// Obtain all the templates
this.templateContext = new TemplateFactory(providerServices);
// Allow injection of template context
injectableFactory.add(new ContextInjectableProvider<TemplateContext>(
TemplateContext.class, templateContext));
// Obtain all context resolvers
final ContextResolverFactory crf = new ContextResolverFactory();
// Obtain all the exception mappers
this.exceptionFactory = new ExceptionMapperFactory();
// Obtain all message body readers/writers
this.bodyFactory = new MessageBodyFactory(providerServices,
getFeaturesAndProperties().getFeature(FeaturesAndProperties.FEATURE_PRE_1_4_PROVIDER_PRECEDENCE));
injectableFactory.add(
new ContextInjectableProvider<MessageBodyWorkers>(
MessageBodyWorkers.class, bodyFactory));
// Injection of Providers
this.providers = new Providers() {
@Override
public <T> MessageBodyReader<T> getMessageBodyReader(Class<T> c, Type t,
Annotation[] as, MediaType m) {
return bodyFactory.getMessageBodyReader(c, t, as, m);
}
@Override
public <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> c, Type t,
Annotation[] as, MediaType m) {
return bodyFactory.getMessageBodyWriter(c, t, as, m);
}
@Override
public <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> c) {
if (Throwable.class.isAssignableFrom(c))
return exceptionFactory.find(c);
else
return null;
}
@Override
public <T> ContextResolver<T> getContextResolver(Class<T> ct, MediaType m) {
return crf.resolve(ct, m);
}
};
injectableFactory.add(
new ContextInjectableProvider<Providers>(
Providers.class, providers));
// Obtain all String readers
this.stringReaderFactory = new StringReaderFactory();
injectableFactory.add(
new ContextInjectableProvider<StringReaderWorkers>(
StringReaderWorkers.class, stringReaderFactory));
MultivaluedParameterExtractorProvider mpep =
new MultivaluedParameterExtractorFactory(stringReaderFactory);
// Add the multi-valued parameter extractor provider
injectableFactory.add(
new ContextInjectableProvider<MultivaluedParameterExtractorProvider>(
MultivaluedParameterExtractorProvider.class, mpep));
// Add per-request-based injectable providers
injectableFactory.add(new CookieParamInjectableProvider(mpep));
injectableFactory.add(new HeaderParamInjectableProvider(mpep));
injectableFactory.add(new HttpContextInjectableProvider());
injectableFactory.add(new MatrixParamInjectableProvider(mpep));
injectableFactory.add(new PathParamInjectableProvider(mpep));
injectableFactory.add(new QueryParamInjectableProvider(mpep));
injectableFactory.add(new FormParamInjectableProvider(mpep));
// Create filter factory
filterFactory = new FilterFactory(providerServices);
// Initiate resource method dispatchers
dispatcherFactory = ResourceMethodDispatcherFactory.create(providerServices);
dispatchingListener = new DispatchingListenerProxy();
// Initiate the WADL factory
this.wadlFactory = new WadlFactory(resourceConfig);
WadlApplicationContextInjectionProxy wadlApplicationContextInjectionProxy = null;
if(!resourceConfig.getFeature(ResourceConfig.FEATURE_DISABLE_WADL)) {
wadlApplicationContextInjectionProxy = new WadlApplicationContextInjectionProxy();
injectableFactory.add(new SingletonTypeInjectableProvider<Context, WadlApplicationContext>(
WadlApplicationContext.class, wadlApplicationContextInjectionProxy) {});
// In order for the application to properly marshall the Application
// object we need to make sure that we provide a JAXBContext that
// will work
final WadlApplicationContext wac = wadlApplicationContextInjectionProxy;
@Provider @Produces({MediaTypes.WADL_STRING,MediaTypes.WADL_JSON_STRING, MediaType.APPLICATION_XML})
class WadlContextResolver implements ContextResolver<JAXBContext>
{
@Override
public JAXBContext getContext(Class<?> type) {
if (com.sun.research.ws.wadl.Application.class.isAssignableFrom(type)) {
return wac.getJAXBContext();
}
else {
return null;
}
}
}
resourceConfig.getSingletons().add(new WadlContextResolver());
// Update the provider services, so this is used
providerServices.update(resourceConfig.getProviderClasses(),
resourceConfig.getProviderSingletons(), injectableFactory);
}
// Initiate filter
filterFactory.init(resourceConfig);