Skip to content

Commit

Permalink
SPI Config API for Jersey (#4116)
Browse files Browse the repository at this point in the history
Config SPI API for Jersey

Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
  • Loading branch information
senivam authored Jun 4, 2019
1 parent c9260df commit 5dec448
Show file tree
Hide file tree
Showing 31 changed files with 1,472 additions and 2 deletions.
5 changes: 5 additions & 0 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@
<artifactId>jersey-metainf-services</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mp-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,17 @@ public final class CommonProperties {
*/
public static final String OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER = "jersey.config.server.contentLength.buffer";

/**
* Property which allows (if true) default System properties configuration provider.
*
* Effective if there are no any external properties providers
*
* Shall be set (if used) in system properties.
* @since 2.29
*/

public static final String ALLOW_SYSTEM_PROPERTIES_PROVIDER = "jersey.config.allowSystemPropertiesProvider";

/**
* Prevent instantiation.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 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.internal.config;

import org.glassfish.jersey.internal.spi.AutoDiscoverable;

import javax.annotation.Priority;
import javax.ws.rs.ConstrainedTo;
import javax.ws.rs.RuntimeType;
import javax.ws.rs.core.FeatureContext;

@ConstrainedTo(RuntimeType.CLIENT) //server is configured directly in ResourceConfig
@Priority(AutoDiscoverable.DEFAULT_PRIORITY)
public class ExternalPropertiesAutoDiscoverable implements AutoDiscoverable {
@Override
public void configure(FeatureContext context) {
if (!context.getConfiguration().isRegistered(ExternalPropertiesConfigurationFeature.class)) {
context.register(ExternalPropertiesConfigurationFeature.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright (c) 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.internal.config;

import org.glassfish.jersey.internal.ServiceFinder;
import org.glassfish.jersey.spi.ExternalConfigurationModel;
import org.glassfish.jersey.spi.ExternalConfigurationProvider;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.core.Configurable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
* Factory for external properties providers
* Offers methods to work with properties loaded from providers or
* just configure Jersey's Configurables with loaded properties from providers
*/
public class ExternalPropertiesConfigurationFactory {

private static final List<ExternalConfigurationProvider> EXTERNAL_CONFIGURATION_PROVIDERS =
getExternalConfigurations();


/**
* Map of merged properties from all found providers
*
* @return map of merged properties from all found/plugged providers
*/
static Map<String, Object> readExternalPropertiesMap() {

final ExternalConfigurationProvider provider = mergeConfigs(EXTERNAL_CONFIGURATION_PROVIDERS);
return provider == null ? Collections.emptyMap() : provider.getProperties();
}


/**
* Input Configurable object shall be provided in order to be filled with all found properties
*
* @param config Input Configurable initialised object to be filled with properties
* @return true if configured false otherwise
*/

public static boolean configure(Configurable config) {

if (config instanceof ExternalConfigurationModel) {
return false; //shall not configure itself
}

final Map<String, Object> properties = readExternalPropertiesMap();

properties.forEach((k, v) -> config.property(k, v));

return true;
}

/**
* Merged config model from all found configuration models
*
* @return merged Model object with all properties
*/
static ExternalConfigurationModel getConfig() {
final ExternalConfigurationProvider provider = mergeConfigs(getExternalConfigurations());
return provider == null ? null : provider.getConfiguration();
}

/**
* List of all found models as they are found by Jersey
*
* @return list of models (or empty list)
*/
private static List<ExternalConfigurationProvider> getExternalConfigurations() {
final List<ExternalConfigurationProvider> providers = new ArrayList<>();
final ServiceFinder<ExternalConfigurationProvider> finder =
ServiceFinder.find(ExternalConfigurationProvider.class);
if (finder.iterator().hasNext()) {
finder.forEach(providers::add);
} else {
providers.add(new SystemPropertiesConfigurationProvider());
}
return providers;
}

private static ExternalConfigurationProvider mergeConfigs(List<ExternalConfigurationProvider> configurations) {
final Set<ExternalConfigurationProvider> orderedConfigurations = orderConfigs(configurations);
final Iterator<ExternalConfigurationProvider> configurationIterator = orderedConfigurations.iterator();
if (!configurationIterator.hasNext()) {
return null;
}
final ExternalConfigurationProvider firstConfig = configurationIterator.next();
while (configurationIterator.hasNext()) {
final ExternalConfigurationProvider nextConfig = configurationIterator.next();
firstConfig.merge(nextConfig.getConfiguration());
}

return firstConfig;
}

private static Set<ExternalConfigurationProvider> orderConfigs(List<ExternalConfigurationProvider> configurations) {

final SortedSet<ExternalConfigurationProvider> sortedSet = new TreeSet<>(new ConfigComparator());
sortedSet.addAll(configurations);
return Collections.unmodifiableSortedSet(sortedSet);
}

private static class ConfigComparator implements Comparator<ExternalConfigurationProvider> {

@Override
public int compare(ExternalConfigurationProvider config1, ExternalConfigurationProvider config2) {

boolean config1PriorityPresent = config1.getClass().isAnnotationPresent(Priority.class);
boolean config2PriorityPresent = config2.getClass().isAnnotationPresent(Priority.class);

int priority1 = Priorities.USER;
int priority2 = Priorities.USER;

if (config1PriorityPresent) {
priority1 = config1.getClass().getAnnotation(Priority.class).value();
}
if (config2PriorityPresent) {
priority2 = config2.getClass().getAnnotation(Priority.class).value();
}

if (priority1 == priority2) {
return config1.getClass().getName().compareTo(config2.getClass().getName());
}
return Integer.compare(priority1, priority2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 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.internal.config;

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;

public class ExternalPropertiesConfigurationFeature implements Feature {

@Override
public boolean configure(FeatureContext configurableContext) {
return ExternalPropertiesConfigurationFactory.configure(configurableContext);
}

}
Loading

0 comments on commit 5dec448

Please sign in to comment.