private Application createApplication(Class<? extends Application> applicationClass) { // need to handle ResourceConfig and Application separately as invoking forContract() on these // will trigger the factories which we don't want at this point if (applicationClass == ResourceConfig.class) { return new ResourceConfig(); } else if (applicationClass == Application.class) { return new Application(); } else { Application app = locator.createAndInitialize(applicationClass); if (app instanceof ResourceConfig) { final ResourceConfig _rc = (ResourceConfig) app; final Class<? extends Application> innerAppClass = _rc.getApplicationClass(); if (innerAppClass != null) { final Application innerApp = createApplication(innerAppClass); _rc.setApplication(innerApp); } } return app; } }
/** Assumes the configuration field is initialized with a valid ResourceConfig. */ private void initialize() { LOGGER.info(LocalizationMessages.INIT_MSG(Version.getBuildId())); // Lock original ResourceConfig. if (application instanceof ResourceConfig) { ((ResourceConfig) application).lock(); } // add WADL support runtimeConfig.register(WadlModelProcessorFeature.class); // Configure binders and features. runtimeConfig.configureMetaProviders(locator); // Introspecting classes & instances final ResourceBag.Builder resourceBagBuilder = new ResourceBag.Builder(); for (Class<?> c : runtimeConfig.getClasses()) { try { Resource resource = Resource.from(c); if (resource != null) { resourceBagBuilder.registerResource(c, resource); } } catch (IllegalArgumentException ex) { LOGGER.warning(ex.getMessage()); } } for (Object o : runtimeConfig.getSingletons()) { try { Resource resource = Resource.from(o.getClass()); if (resource != null) { resourceBagBuilder.registerResource(o, resource); } } catch (IllegalArgumentException ex) { LOGGER.warning(ex.getMessage()); } } // Adding programmatic resource models for (Resource programmaticResource : runtimeConfig.getResources()) { resourceBagBuilder.registerProgrammaticResource(programmaticResource); } final ResourceBag resourceBag = resourceBagBuilder.build(); runtimeConfig.lock(); // Registering Injection Bindings final Set<ComponentProvider> componentProviders = new HashSet<ComponentProvider>(); for (ComponentProvider provider : ServiceFinder.find(ComponentProvider.class)) { provider.initialize(locator); componentProviders.add(provider); } final ComponentBag componentBag = runtimeConfig.getComponentBag(); bindProvidersAndResources( componentProviders, componentBag, resourceBag.classes, resourceBag.instances); for (ComponentProvider componentProvider : componentProviders) { componentProvider.done(); } // scan for NameBinding annotations attached to the application class Collection<Class<? extends Annotation>> applicationNameBindings = ReflectionHelper.getAnnotationTypes(application.getClass(), NameBinding.class); // find all filters, interceptors and dynamic features final Iterable<RankedProvider<ContainerResponseFilter>> responseFilters = Providers.getAllRankedProviders(locator, ContainerResponseFilter.class); final MultivaluedMap<Class<? extends Annotation>, RankedProvider<ContainerResponseFilter>> nameBoundResponseFilters = filterNameBound(responseFilters, null, componentBag, applicationNameBindings); final Iterable<RankedProvider<ContainerRequestFilter>> requestFilters = Providers.getAllRankedProviders(locator, ContainerRequestFilter.class); final List<RankedProvider<ContainerRequestFilter>> preMatchFilters = Lists.newArrayList(); final MultivaluedMap<Class<? extends Annotation>, RankedProvider<ContainerRequestFilter>> nameBoundRequestFilters = filterNameBound(requestFilters, preMatchFilters, componentBag, applicationNameBindings); final Iterable<RankedProvider<ReaderInterceptor>> readerInterceptors = Providers.getAllRankedProviders(locator, ReaderInterceptor.class); final MultivaluedMap<Class<? extends Annotation>, RankedProvider<ReaderInterceptor>> nameBoundReaderInterceptors = filterNameBound(readerInterceptors, null, componentBag, applicationNameBindings); final Iterable<RankedProvider<WriterInterceptor>> writerInterceptors = Providers.getAllRankedProviders(locator, WriterInterceptor.class); final MultivaluedMap<Class<? extends Annotation>, RankedProvider<WriterInterceptor>> nameBoundWriterInterceptors = filterNameBound(writerInterceptors, null, componentBag, applicationNameBindings); final Iterable<DynamicFeature> dynamicFeatures = Providers.getAllProviders(locator, DynamicFeature.class); ResourceModel resourceModel = new ResourceModel.Builder(resourceBag.getRootResources(), false).build(); resourceModel = processResourceModel(resourceModel); // validate the models validate(resourceModel); bindEnhancingResourceClasses(resourceModel, resourceBag, componentProviders); final RuntimeModelBuilder runtimeModelBuilder = locator.getService(RuntimeModelBuilder.class); runtimeModelBuilder.setGlobalInterceptors(readerInterceptors, writerInterceptors); runtimeModelBuilder.setBoundProviders( nameBoundRequestFilters, nameBoundResponseFilters, nameBoundReaderInterceptors, nameBoundWriterInterceptors, dynamicFeatures); // assembly request processing chain /** * Root hierarchical request matching acceptor. Invoked in a single linear stage as part of the * main linear accepting chain. */ final Router resourceRoutingRoot = runtimeModelBuilder.buildModel(resourceModel.getRuntimeResourceModel(), false); final ContainerFilteringStage preMatchRequestFilteringStage = locator .createAndInitialize(ContainerFilteringStage.Builder.class) .build(preMatchFilters, responseFilters); final RoutingStage routingStage = locator.createAndInitialize(RoutingStage.Builder.class).build(resourceRoutingRoot); final ContainerFilteringStage resourceFilteringStage = locator .createAndInitialize(ContainerFilteringStage.Builder.class) .build(requestFilters, null); final RoutedInflectorExtractorStage routedInflectorExtractorStage = locator.createAndInitialize(RoutedInflectorExtractorStage.class); /** * Root linear request acceptor. This is the main entry point for the whole request processing. */ final Stage<ContainerRequest> rootStage = Stages.chain(locator.createAndInitialize(ReferencesInitializer.class)) .to(locator.createAndInitialize(ContainerMessageBodyWorkersInitializer.class)) .to(preMatchRequestFilteringStage) .to(routingStage) .to(resourceFilteringStage) .build(routedInflectorExtractorStage); // Inject instances. for (Object instance : componentBag.getInstances(ComponentBag.EXCLUDE_META_PROVIDERS)) { locator.inject(instance); } for (Object instance : resourceBag.instances) { locator.inject(instance); } // initiate resource model into JerseyResourceContext JerseyResourceContext jerseyResourceContext = locator.getService(JerseyResourceContext.class); jerseyResourceContext.setResourceModel(resourceModel); this.runtime = locator.createAndInitialize(ServerRuntime.Builder.class).build(rootStage); // inject self locator.inject(this); }
/** * Build a runtime model. * * @param subResourceMode if {@code true}, all resources will be processed as sub-resources. * @return runtime request routing root. */ public Router buildModel(boolean subResourceMode) { final PushMatchedUriRouter uriPushingRouter = locator.createAndInitialize(PushMatchedUriRouter.class); RouteToPathBuilder<PathPattern> lastRoutedBuilder = null; // route resource method acceptors if (!rootAcceptors.isEmpty()) { for (Map.Entry<PathPattern, List<MethodAcceptorPair>> entry : rootAcceptors.entrySet()) { final PathPattern closedResourcePathPattern = entry.getKey(); List<MethodAcceptorPair> methodAcceptorPairs = entry.getValue(); lastRoutedBuilder = routeMethodAcceptor( lastRoutedBuilder, closedResourcePathPattern, uriPushingRouter, methodSelectingAcceptorBuilder.build(workers, methodAcceptorPairs), subResourceMode); } rootAcceptors.clear(); } // route sub-resource method and locator acceptors if (!subResourceAcceptors.isEmpty()) { for (Map.Entry<PathPattern, TreeMap<PathPattern, List<MethodAcceptorPair>>> singleResourcePathEntry : subResourceAcceptors.entrySet()) { RouteToPathBuilder<PathPattern> srRoutedBuilder = null; for (Map.Entry<PathPattern, List<MethodAcceptorPair>> singlePathEntry : singleResourcePathEntry.getValue().entrySet()) { // there can be multiple sub-resource methods on the same path // but only a single sub-resource locator. List<MethodAcceptorPair> resourceMethods = Lists.newLinkedList(); MethodAcceptorPair resourceLocator = null; for (MethodAcceptorPair methodAcceptorPair : singlePathEntry.getValue()) { if (methodAcceptorPair.model.getType() == ResourceMethod.JaxrsType.RESOURCE_METHOD) { resourceMethods.add(methodAcceptorPair); } else { resourceLocator = methodAcceptorPair; } } if (!resourceMethods.isEmpty()) { final PathPattern subResourceMethodPath = PathPattern.asClosed(singlePathEntry.getKey()); srRoutedBuilder = routedBuilder(srRoutedBuilder) .route(subResourceMethodPath) .to(uriPushingRouter) .to(methodSelectingAcceptorBuilder.build(workers, resourceMethods)); } if (resourceLocator != null) { srRoutedBuilder = routedBuilder(srRoutedBuilder) .route(singlePathEntry.getKey()) .to(uriPushingRouter) .to(resourceLocator.router); } } assert srRoutedBuilder != null; lastRoutedBuilder = routeMethodAcceptor( lastRoutedBuilder, singleResourcePathEntry.getKey(), uriPushingRouter, srRoutedBuilder.build(), subResourceMode); } subResourceAcceptors.clear(); } return createRootTreeAcceptor(lastRoutedBuilder, subResourceMode); }
/** * Get the class by contract or create and inject a new instance. * * @param <T> instance type. * @param serviceLocator HK2 service locator. * @param clazz class of the instance to be provider. * @return instance of the class either provided as a service or created and injected by HK2. */ public static <T> T getOrCreate(ServiceLocator serviceLocator, Class<T> clazz) { T component = serviceLocator.getService(clazz); return component == null ? serviceLocator.createAndInitialize(clazz) : component; }