
org.glassfish.jersey.model.internal.CommonConfig Maven / Gradle / Ivy
/*
* Copyright (c) 2012, 2019 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.model.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.ConstrainedTo;
import javax.ws.rs.Priorities;
import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.annotation.Priority;
import org.glassfish.jersey.ExtendedConfig;
import org.glassfish.jersey.inject.spi.BinderConfigurationFactory;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.internal.inject.JerseyBinderConfigurationFactory;
import org.glassfish.jersey.internal.inject.ProviderBinder;
import org.glassfish.jersey.internal.spi.AutoDiscoverable;
import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
import org.glassfish.jersey.internal.util.PropertiesHelper;
import org.glassfish.jersey.model.ContractProvider;
import org.glassfish.jersey.process.Inflector;
/**
* Common immutable {@link javax.ws.rs.core.Configuration} implementation for
* server and client.
*
* @author Michal Gajdos
* @author Marek Potociar
*/
public class CommonConfig implements FeatureContext, ExtendedConfig {
private static final Logger LOGGER = Logger.getLogger(CommonConfig.class.getName());
/**
* Configuration runtime type.
*/
private final RuntimeType type;
/**
* Configuration properties collection and it's immutable views.
*/
private final Map properties;
private final Map immutablePropertiesView;
private final Collection immutablePropertyNames;
/**
* Configured providers, does not include features and binders.
*/
private final ComponentBag componentBag;
/**
* Collection of unprocessed feature registrations.
*/
private final List newFeatureRegistrations;
/**
* Collection of enabled feature classes.
*/
private final Set> enabledFeatureClasses;
/**
* Collection of enabled feature instances.
*/
private final Set enabledFeatures;
/**
* Flag determining whether the configuration of meta-providers (excl. binders) should be disabled.
*/
private boolean disableMetaProviderConfiguration;
/**
* A utility class that binds binders on all {@link BinderConfigurationFactory.BinderConfiguration BinderConfiguration}
* created upon creation of this BinderConfigurations from all {@link BinderConfigurationFactory BinderConfigurationFactories}
*/
private static final class BinderConfigurations {
private static final List BINDER_CONFIGURATION_FACTORIES;
static {
final ServiceFinder factoriesFinder =
ServiceFinder.find(BinderConfigurationFactory.class);
final List configurationFactories = new LinkedList<>();
configurationFactories.add(new JerseyBinderConfigurationFactory());
for (BinderConfigurationFactory configurationFactory : factoriesFinder) {
configurationFactories.add(configurationFactory);
}
BINDER_CONFIGURATION_FACTORIES = Collections.unmodifiableList(configurationFactories);
}
private final List binderConfigurations;
private BinderConfigurations(ComponentBag componentBag) {
binderConfigurations = new LinkedList<>();
for (BinderConfigurationFactory factory : BINDER_CONFIGURATION_FACTORIES) {
BinderConfigurationFactory.BinderConfiguration configuration =
factory.createBinderConfiguration(componentBag::getInstances);
binderConfigurations.add(configuration);
}
}
private void configureBinders(InjectionManager injectionManager) {
for (BinderConfigurationFactory.BinderConfiguration configuration : binderConfigurations) {
configuration.configureBinders(injectionManager);
}
}
}
/**
* A single feature registration record.
*/
private static final class FeatureRegistration {
private final Class extends Feature> featureClass;
private final Feature feature;
private final RuntimeType runtimeType;
private FeatureRegistration(final Class extends Feature> featureClass) {
this.featureClass = featureClass;
this.feature = null;
final ConstrainedTo runtimeTypeConstraint = featureClass.getAnnotation(ConstrainedTo.class);
this.runtimeType = runtimeTypeConstraint == null ? null : runtimeTypeConstraint.value();
}
private FeatureRegistration(final Feature feature) {
this.featureClass = feature.getClass();
this.feature = feature;
final ConstrainedTo runtimeTypeConstraint = featureClass.getAnnotation(ConstrainedTo.class);
this.runtimeType = runtimeTypeConstraint == null ? null : runtimeTypeConstraint.value();
}
/**
* Get the registered feature class.
*
* @return registered feature class.
*/
private Class extends Feature> getFeatureClass() {
return featureClass;
}
/**
* Get the registered feature instance or {@code null} if this is a
* class based feature registration.
*
* @return the registered feature instance or {@code null} if this is a
* class based feature registration.
*/
private Feature getFeature() {
return feature;
}
/**
* Get the {@code RuntimeType} constraint given by {@code ConstrainedTo} annotated
* the Feature or {@code null} if not annotated.
*
* @return the {@code RuntimeType} constraint given by {@code ConstrainedTo} annotated
* the Feature or {@code null} if not annotated.
*/
private RuntimeType getFeatureRuntimeType() {
return runtimeType;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof FeatureRegistration)) {
return false;
}
final FeatureRegistration other = (FeatureRegistration) obj;
return (featureClass == other.featureClass)
|| (feature != null && (feature == other.feature || feature.equals(other.feature)));
}
@Override
public int hashCode() {
int hash = 47;
hash = 13 * hash + (feature != null ? feature.hashCode() : 0);
hash = 13 * hash + (featureClass != null ? featureClass.hashCode() : 0);
return hash;
}
}
/**
* Create a new {@code RuntimeConfig} instance.
*
* The constructor provides a way for defining a {@link ContractProvider contract
* provider model} registration strategy. Once a registration model is built
* for a newly registered contract, the provided registration strategy filter is
* consulted whether the model should be registered or not.
*
*
* Clients can use the method to cancel any contract provider model registration
* that does not meet the criteria of a given configuration context, such as a model
* that does not have any recognized contracts associated with it.
*
*
* @param type configuration runtime type.
* @param registrationStrategy function driving the decision (based on the introspected
* {@link ContractProvider contract provider model}) whether
* or not should the component class registration continue
* towards a successful completion.
*/
public CommonConfig(final RuntimeType type, final Predicate registrationStrategy) {
this.type = type;
this.properties = new HashMap<>();
this.immutablePropertiesView = Collections.unmodifiableMap(properties);
this.immutablePropertyNames = Collections.unmodifiableCollection(properties.keySet());
this.componentBag = ComponentBag.newInstance(registrationStrategy);
this.newFeatureRegistrations = new LinkedList<>();
this.enabledFeatureClasses = Collections.newSetFromMap(new IdentityHashMap<>());
this.enabledFeatures = new HashSet<>();
this.disableMetaProviderConfiguration = false;
}
/**
* Copy constructor.
*
* @param config configurable to copy class properties from.
*/
public CommonConfig(final CommonConfig config) {
this.type = config.type;
this.properties = new HashMap<>(config.properties.size());
this.immutablePropertiesView = Collections.unmodifiableMap(this.properties);
this.immutablePropertyNames = Collections.unmodifiableCollection(this.properties.keySet());
this.componentBag = config.componentBag.copy();
this.newFeatureRegistrations = new LinkedList<>();
this.enabledFeatureClasses = Collections.newSetFromMap(new IdentityHashMap<>());
this.enabledFeatures = new HashSet<>();
copy(config, false);
}
/**
* Copy config properties, providers from given {@code config} to this instance.
*
* @param config configurable to copy class properties from.
* @param loadComponentBag {@code true} if the component bag from config should be copied as well, {@code false} otherwise.
*/
private void copy(final CommonConfig config, final boolean loadComponentBag) {
this.properties.clear();
this.properties.putAll(config.properties);
this.newFeatureRegistrations.clear();
this.newFeatureRegistrations.addAll(config.newFeatureRegistrations);
this.enabledFeatureClasses.clear();
this.enabledFeatureClasses.addAll(config.enabledFeatureClasses);
this.enabledFeatures.clear();
this.enabledFeatures.addAll(config.enabledFeatures);
this.disableMetaProviderConfiguration = config.disableMetaProviderConfiguration;
if (loadComponentBag) {
this.componentBag.loadFrom(config.componentBag);
}
}
@Override
public ExtendedConfig getConfiguration() {
return this;
}
@Override
public RuntimeType getRuntimeType() {
return type;
}
@Override
public Map getProperties() {
return immutablePropertiesView;
}
@Override
public Object getProperty(final String name) {
return properties.get(name);
}
@Override
public boolean isProperty(final String name) {
return PropertiesHelper.isProperty(getProperty(name));
}
@Override
public Collection getPropertyNames() {
return immutablePropertyNames;
}
@Override
public boolean isEnabled(final Class extends Feature> featureClass) {
return enabledFeatureClasses.contains(featureClass);
}
@Override
public boolean isEnabled(final Feature feature) {
return enabledFeatures.contains(feature);
}
@Override
public boolean isRegistered(final Object component) {
return componentBag.getInstances().contains(component);
}
@Override
public boolean isRegistered(final Class> componentClass) {
return componentBag.getRegistrations().contains(componentClass);
}
@Override
public Map, Integer> getContracts(final Class> componentClass) {
final ContractProvider model = componentBag.getModel(componentClass);
return (model == null) ? Collections.emptyMap() : model.getContractMap();
}
@Override
public Set> getClasses() {
return componentBag.getClasses();
}
@Override
public Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy