All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.jersey.server.ProcessingProvidersConfigurator Maven / Gradle / Ivy

There is a newer version: 4.0.0-M1
Show newest version
/*
 * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.server;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

import javax.ws.rs.NameBinding;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.WriterInterceptor;

import org.glassfish.jersey.internal.BootstrapBag;
import org.glassfish.jersey.internal.BootstrapConfigurator;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.Providers;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.model.ContractProvider;
import org.glassfish.jersey.model.internal.ComponentBag;
import org.glassfish.jersey.model.internal.RankedProvider;
import org.glassfish.jersey.server.internal.LocalizationMessages;
import org.glassfish.jersey.server.internal.ProcessingProviders;

/**
 * Configurator which initializes and register {@link ProcessingProviders} instance into {@link BootstrapBag}.
 * Instances of these interfaces are processed, configured and provided using this configurator:
 * 
    *
  • {@link ContainerRequestFilter}
  • *
  • {@link ContainerResponseFilter}
  • *
  • {@link ReaderInterceptor}
  • *
  • {@link WriterInterceptor}
  • *
  • {@link DynamicFeature}
  • *
* * @author Petr Bouda */ class ProcessingProvidersConfigurator implements BootstrapConfigurator { private static final Logger LOGGER = Logger.getLogger(ProcessingProvidersConfigurator.class.getName()); @Override public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { } @Override public void postInit(InjectionManager injectionManager, BootstrapBag bootstrapBag) { ServerBootstrapBag serverBag = (ServerBootstrapBag) bootstrapBag; ComponentBag componentBag = serverBag.getRuntimeConfig().getComponentBag(); // scan for NameBinding annotations attached to the application class Collection> applicationNameBindings = ReflectionHelper.getAnnotationTypes( ResourceConfig.unwrapApplication(serverBag.getRuntimeConfig()).getClass(), NameBinding.class); MultivaluedMap, Class> nameBoundRespFiltersInverse = new MultivaluedHashMap<>(); MultivaluedMap, Class> nameBoundReqFiltersInverse = new MultivaluedHashMap<>(); MultivaluedMap, Class> nameBoundReaderInterceptorsInverse = new MultivaluedHashMap<>(); MultivaluedMap, Class> nameBoundWriterInterceptorsInverse = new MultivaluedHashMap<>(); Iterable> responseFilters = Providers.getAllRankedProviders(injectionManager, ContainerResponseFilter.class); MultivaluedMap, RankedProvider> nameBoundResponseFilters = filterNameBound(responseFilters, null, componentBag, applicationNameBindings, nameBoundRespFiltersInverse); Iterable> requestFilters = Providers.getAllRankedProviders(injectionManager, ContainerRequestFilter.class); List> preMatchFilters = new ArrayList<>(); MultivaluedMap, RankedProvider> nameBoundReqFilters = filterNameBound(requestFilters, preMatchFilters, componentBag, applicationNameBindings, nameBoundReqFiltersInverse); Iterable> readerInterceptors = Providers.getAllRankedProviders(injectionManager, ReaderInterceptor.class); MultivaluedMap, RankedProvider> nameBoundReaderInterceptors = filterNameBound(readerInterceptors, null, componentBag, applicationNameBindings, nameBoundReaderInterceptorsInverse); Iterable> writerInterceptors = Providers.getAllRankedProviders(injectionManager, WriterInterceptor.class); MultivaluedMap, RankedProvider> nameBoundWriterInterceptors = filterNameBound(writerInterceptors, null, componentBag, applicationNameBindings, nameBoundWriterInterceptorsInverse); Iterable dynamicFeatures = Providers.getAllProviders(injectionManager, DynamicFeature.class); ProcessingProviders processingProviders = new ProcessingProviders(nameBoundReqFilters, nameBoundReqFiltersInverse, nameBoundResponseFilters, nameBoundRespFiltersInverse, nameBoundReaderInterceptors, nameBoundReaderInterceptorsInverse, nameBoundWriterInterceptors, nameBoundWriterInterceptorsInverse, requestFilters, preMatchFilters, responseFilters, readerInterceptors, writerInterceptors, dynamicFeatures); serverBag.setProcessingProviders(processingProviders); } /** * Takes collection of all filters/interceptors (either request/reader or response/writer) * and separates out all name-bound filters/interceptors, returns them as a separate MultivaluedMap, * mapping the name-bound annotation to the list of name-bound filters/interceptors. The same key values * are also added into the inverse map passed in {@code inverseNameBoundMap}. *

* Note, the name-bound filters/interceptors are removed from the original filters/interceptors collection. * If non-null collection is passed in the postMatching parameter (applicable for filters only), * this method also removes all the global * postMatching filters from the original collection and adds them to the collection passed in the postMatching * parameter. * * @param all Collection of all filters to be processed. * @param preMatchingFilters Collection into which pre-matching filters should be added. * @param componentBag Component bag * @param applicationNameBindings Collection of name binding annotations attached to the JAX-RS application. * @param inverseNameBoundMap Inverse name bound map into which the name bound providers should be inserted. The keys * are providers (filters, interceptor) * @return {@link MultivaluedMap} of all name-bound filters. */ private static MultivaluedMap, RankedProvider> filterNameBound( final Iterable> all, final Collection> preMatchingFilters, final ComponentBag componentBag, final Collection> applicationNameBindings, final MultivaluedMap, Class> inverseNameBoundMap) { final MultivaluedMap, RankedProvider> result = new MultivaluedHashMap<>(); for (final Iterator> it = all.iterator(); it.hasNext(); ) { final RankedProvider provider = it.next(); Class providerClass = provider.getProvider().getClass(); final Set contractTypes = provider.getContractTypes(); if (contractTypes != null && !contractTypes.contains(providerClass)) { providerClass = ReflectionHelper.theMostSpecificTypeOf(contractTypes); } ContractProvider model = componentBag.getModel(providerClass); if (model == null) { // the provider was (most likely) bound in HK2 externally model = ComponentBag.modelFor(providerClass); } final boolean preMatching = providerClass.getAnnotation(PreMatching.class) != null; if (preMatching && preMatchingFilters != null) { it.remove(); preMatchingFilters.add(new RankedProvider<>((ContainerRequestFilter) provider.getProvider(), model.getPriority(ContainerRequestFilter.class))); } boolean nameBound = model.isNameBound(); if (nameBound && !applicationNameBindings.isEmpty() && applicationNameBindings.containsAll(model.getNameBindings())) { // override the name-bound flag nameBound = false; } if (nameBound) { // not application-bound if (!preMatching) { it.remove(); for (final Class binding : model.getNameBindings()) { result.add(binding, provider); inverseNameBoundMap.add(provider, binding); } } else { LOGGER.warning(LocalizationMessages.PREMATCHING_ALSO_NAME_BOUND(providerClass)); } } } return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy