Skip to content

Commit bffec01

Browse files
committedOct 13, 2018
New Module: Java SE Bootstrap Microprofile Config
Signed-off-by: Markus KARG <markus@headcrashing.eu>
1 parent 523dd03 commit bffec01

File tree

11 files changed

+462
-0
lines changed

11 files changed

+462
-0
lines changed
 

‎core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.glassfish.jersey.server.ContainerFactory;
3939
import org.glassfish.jersey.server.ServerFactory;
4040
import org.glassfish.jersey.server.ServerProperties;
41+
import org.glassfish.jersey.server.spi.ConfiguratorFactory;
4142
import org.glassfish.jersey.server.spi.Server;
4243

4344
/**
@@ -116,6 +117,12 @@ public final <T> Builder from(final BiFunction<String, Class<T>, Optional<T>> co
116117
return this;
117118
}
118119

120+
@Override
121+
public final Builder from(final Object externalConfig) {
122+
ConfiguratorFactory.configure(this, externalConfig);
123+
return this;
124+
}
125+
119126
@Override
120127
public final JAXRS.Configuration build() {
121128
return this.properties::get;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2018 Markus KARG. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.server.spi;
18+
19+
import javax.ws.rs.ConstrainedTo;
20+
import javax.ws.rs.JAXRS;
21+
import javax.ws.rs.JAXRS.Configuration;
22+
import javax.ws.rs.ProcessingException;
23+
import javax.ws.rs.RuntimeType;
24+
25+
import org.glassfish.jersey.spi.Contract;
26+
27+
/**
28+
* Service-provider interface for configuring {@link Configuration.Builder} instances.
29+
* <p>
30+
* If the type of supported configuration is supported by the provider, the builder instance will get configured
31+
* accordingly.
32+
* </p>
33+
* <p>
34+
* An implementation can identify itself by placing a Java service provider configuration file (if not already present)
35+
* - {@code org.glassfish.jersey.server.spi.Configurator} - in the resource directory {@code META-INF/services}, and
36+
* adding the fully qualified service-provider-class of the implementation in the file.
37+
* </p>
38+
*
39+
* @author Markus KARG (markus@headcrashing.eu)
40+
* @since 2.28
41+
*/
42+
@Contract
43+
@ConstrainedTo(RuntimeType.SERVER)
44+
public interface Configurator {
45+
46+
/**
47+
* Configures the configuration builder according to the provided configuration if its type is supported, or just does
48+
* nothing otherwise.
49+
*
50+
* @param configurationBuilder The configuration builder to configure.
51+
* @param configuration The configuration to use for configuring the configuration builder.
52+
* @throws ProcessingException in case the type of configuration is supported but there was any other problem when
53+
* applying the configuration.
54+
*/
55+
public void configure(JAXRS.Configuration.Builder configurationBuilder, Object configuration) throws ProcessingException;
56+
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2018 Markus KARG. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.server.spi;
18+
19+
import javax.ws.rs.JAXRS;
20+
import javax.ws.rs.ProcessingException;
21+
22+
import org.glassfish.jersey.internal.ServiceFinder;
23+
24+
/**
25+
* Factory for configuring configuration builders using provided configuration instances.
26+
*
27+
* @author Markus KARG (markus@headcrashing.eu)
28+
* @since 2.28
29+
*/
30+
public final class ConfiguratorFactory {
31+
32+
/**
33+
* Prevents instantiation.
34+
*/
35+
private ConfiguratorFactory() {
36+
}
37+
38+
/**
39+
* Configures the configuration builder according to the provided configuration if its type is supported, or just does
40+
* nothing otherwise.
41+
* <p>
42+
* The list of service-providers supporting the {@link Configurator} service-provider will be iterated over, so
43+
* effectively <em>all</em> compatible configurators will apply the configuration, but in <em>arbitrary</em> order.
44+
* <p>
45+
*
46+
* @param configurationBuilder The configuration builder to configure.
47+
* @param configuration The configuration to use for configuring the configuration builder.
48+
* @throws ProcessingException in case the type of configuration is supported but there was any other problem when
49+
* applying the configuration.
50+
*/
51+
public static void configure(final JAXRS.Configuration.Builder configurationBuilder, final Object configuration) {
52+
for (final Configurator configurator : ServiceFinder.find(Configurator.class)) {
53+
configurator.configure(configurationBuilder, configuration);
54+
}
55+
}
56+
57+
}

‎core-server/src/test/java/org/glassfish/jersey/server/internal/RuntimeDelegateImplTest.java

+59
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727

2828
import java.security.NoSuchAlgorithmException;
2929
import java.util.Collections;
30+
import java.util.HashMap;
3031
import java.util.Iterator;
32+
import java.util.Map;
3133
import java.util.Optional;
3234
import java.util.concurrent.CompletableFuture;
3335
import java.util.concurrent.CompletionStage;
@@ -43,9 +45,11 @@
4345

4446
import org.glassfish.jersey.internal.ServiceFinder;
4547
import org.glassfish.jersey.internal.ServiceFinder.ServiceIteratorProvider;
48+
import org.glassfish.jersey.internal.guava.Iterators;
4649
import org.glassfish.jersey.server.ApplicationHandler;
4750
import org.glassfish.jersey.server.ResourceConfig;
4851
import org.glassfish.jersey.server.ServerProperties;
52+
import org.glassfish.jersey.server.spi.Configurator;
4953
import org.glassfish.jersey.server.spi.Container;
5054
import org.glassfish.jersey.server.spi.Server;
5155
import org.glassfish.jersey.server.spi.ServerProvider;
@@ -228,6 +232,61 @@ public final void shouldBuildCustomConfigurationFromPropertiesProvider() {
228232
assertThat(configuration.property(ServerProperties.AUTO_START), is(FALSE));
229233
}
230234

235+
@Test
236+
public final void shouldBuildCustomConfigurationFromExternalConfiguration() {
237+
// given
238+
final JAXRS.Configuration.Builder configurationBuilder = new RuntimeDelegateImpl().createConfigurationBuilder();
239+
final SSLContext mockSslContext = new SSLContext(null, null, null) {
240+
};
241+
final Class<Server> mockServerClass = Server.class;
242+
final Map<String, Object> externalConfiguration = new HashMap<>();
243+
externalConfiguration.put(JAXRS.Configuration.PROTOCOL, "HTTPS");
244+
externalConfiguration.put(JAXRS.Configuration.HOST, "hostname");
245+
externalConfiguration.put(JAXRS.Configuration.PORT, 8080);
246+
externalConfiguration.put(JAXRS.Configuration.ROOT_PATH, "path");
247+
externalConfiguration.put(JAXRS.Configuration.SSL_CLIENT_AUTHENTICATION, JAXRS.Configuration.SSLClientAuthentication.OPTIONAL);
248+
externalConfiguration.put(JAXRS.Configuration.SSL_CONTEXT, mockSslContext);
249+
externalConfiguration.put(ServerProperties.HTTP_SERVER_CLASS, mockServerClass);
250+
externalConfiguration.put(ServerProperties.AUTO_START, FALSE);
251+
final Configurator mockConfigurator = new Configurator() {
252+
@SuppressWarnings("unchecked")
253+
@Override
254+
public final void configure(final JAXRS.Configuration.Builder configurationBuilder, final Object configuration) {
255+
if (configuration instanceof Map) {
256+
final Map<String, Object> valueNamePairs = (Map<String, Object>) configuration;
257+
valueNamePairs.forEach(configurationBuilder::property);
258+
}
259+
}
260+
};
261+
ServiceFinder.setIteratorProvider(new ServiceIteratorProvider() {
262+
@Override
263+
public final <T> Iterator<T> createIterator(final Class<T> service, final String serviceName, final ClassLoader loader,
264+
final boolean ignoreOnClassNotFound) {
265+
return Iterators.singletonIterator(service.cast(mockConfigurator));
266+
}
267+
268+
@Override
269+
public final <T> Iterator<Class<T>> createClassIterator(final Class<T> service, final String serviceName, final ClassLoader loader,
270+
final boolean ignoreOnClassNotFound) {
271+
throw new UnsupportedOperationException();
272+
}
273+
});
274+
275+
// when
276+
final JAXRS.Configuration configuration = configurationBuilder.from(externalConfiguration).build();
277+
278+
// then
279+
assertThat(configuration, is(notNullValue()));
280+
assertThat(configuration.protocol(), is("HTTPS"));
281+
assertThat(configuration.host(), is("hostname"));
282+
assertThat(configuration.port(), is(8080));
283+
assertThat(configuration.rootPath(), is("path"));
284+
assertThat(configuration.sslClientAuthentication(), is(JAXRS.Configuration.SSLClientAuthentication.OPTIONAL));
285+
assertThat(configuration.sslContext(), is(theInstance(mockSslContext)));
286+
assertThat(configuration.property(ServerProperties.HTTP_SERVER_CLASS), is(theInstance(mockServerClass)));
287+
assertThat(configuration.property(ServerProperties.AUTO_START), is(FALSE));
288+
}
289+
231290
@Test
232291
public final void shouldBootstrapApplication() throws InterruptedException, ExecutionException, TimeoutException {
233292
// given
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2018 Markus KARG. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.server.spi;
18+
19+
import static org.hamcrest.Matchers.both;
20+
import static org.hamcrest.Matchers.hasEntry;
21+
import static org.junit.Assert.assertThat;
22+
23+
import java.util.HashMap;
24+
import java.util.Iterator;
25+
import java.util.Map;
26+
import java.util.Optional;
27+
import java.util.function.BiFunction;
28+
import java.util.function.Function;
29+
30+
import javax.ws.rs.JAXRS;
31+
import javax.ws.rs.JAXRS.Configuration;
32+
import javax.ws.rs.JAXRS.Configuration.Builder;
33+
34+
import org.glassfish.jersey.internal.ServiceFinder;
35+
import org.glassfish.jersey.internal.ServiceFinder.ServiceIteratorProvider;
36+
import org.glassfish.jersey.internal.guava.Iterators;
37+
import org.junit.Test;
38+
39+
/**
40+
* Unit tests for {@link ConfiguratorFactory}.
41+
*
42+
* @author Markus KARG (markus@headcrashing.eu)
43+
*/
44+
public final class ConfiguratorFactoryTest {
45+
46+
@Test
47+
public final void shouldConfigureUsingAllProviders() {
48+
// given
49+
final Function<String, String> configuration = name -> name + "Value";
50+
final Map<String, String> properties = new HashMap<>(2);
51+
final JAXRS.Configuration.Builder configurationBuilder = new JAXRS.Configuration.Builder() {
52+
@Override
53+
public final JAXRS.Configuration.Builder property(final String name, final Object value) {
54+
properties.put(name, value.toString());
55+
return this;
56+
}
57+
58+
@Override
59+
public final <T> Builder from(final BiFunction<String, Class<T>, Optional<T>> propertiesProvider) {
60+
return null;
61+
}
62+
63+
@Override
64+
public final Configuration build() {
65+
return null;
66+
}
67+
};
68+
final Configurator firstConfigurator = new Configurator() {
69+
@SuppressWarnings("unchecked")
70+
@Override
71+
public final void configure(final JAXRS.Configuration.Builder configurationBuilder, final Object configuration) {
72+
configurationBuilder.property("firstProperty", ((Function<String, String>) configuration).apply("first"));
73+
}
74+
};
75+
final Configurator secondConfigurator = new Configurator() {
76+
@SuppressWarnings("unchecked")
77+
@Override
78+
public final void configure(final JAXRS.Configuration.Builder configurationBuilder, final Object configuration) {
79+
configurationBuilder.property("secondProperty", ((Function<String, String>) configuration).apply("second"));
80+
}
81+
};
82+
ServiceFinder.setIteratorProvider(new ServiceIteratorProvider() {
83+
@SuppressWarnings("unchecked")
84+
@Override
85+
public final <T> Iterator<T> createIterator(final Class<T> service, final String serviceName, final ClassLoader loader,
86+
final boolean ignoreOnClassNotFound) {
87+
return Iterators.forArray(service.cast(firstConfigurator), service.cast(secondConfigurator));
88+
}
89+
90+
@Override
91+
public final <T> Iterator<Class<T>> createClassIterator(final Class<T> service, final String serviceName, final ClassLoader loader,
92+
final boolean ignoreOnClassNotFound) {
93+
throw new UnsupportedOperationException();
94+
}
95+
});
96+
97+
// when
98+
ConfiguratorFactory.configure(configurationBuilder, configuration);
99+
100+
// then
101+
assertThat(properties, both(hasEntry("firstProperty", "firstValue")).and(hasEntry("secondProperty", "secondValue")));
102+
}
103+
104+
}
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- Copyright (c) 2018 Markus KARG This program and the accompanying materials
3+
are made available under the terms of the Eclipse Public License 2.0 which
4+
is available at http://www.eclipse.org/legal/epl-2.0. This Source Code may
5+
also be made available under the following Secondary Licenses when the conditions
6+
for such availability set forth in the Eclipse Public License v. 2.0 are
7+
satisfied: GNU General Public License, version 2 with the GNU Classpath Exception,
8+
which is available at https://www.gnu.org/software/classpath/license.html.
9+
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 -->
10+
11+
<project xmlns="http://maven.apache.org/POM/4.0.0"
12+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
13+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
14+
<modelVersion>4.0.0</modelVersion>
15+
16+
<parent>
17+
<groupId>org.glassfish.jersey.ext</groupId>
18+
<artifactId>project</artifactId>
19+
<version>2.28-SNAPSHOT</version>
20+
</parent>
21+
22+
<artifactId>jersey-microprofile-config-javase</artifactId>
23+
<name>jersey-microprofile-config-javase</name>
24+
25+
<description>
26+
Jersey extension module providing support for Microprofile Config integration on Java SE platforms.
27+
</description>
28+
29+
<dependencies>
30+
<dependency>
31+
<groupId>javax.ws.rs</groupId>
32+
<artifactId>javax.ws.rs-api</artifactId>
33+
</dependency>
34+
35+
<dependency>
36+
<groupId>org.glassfish.jersey.core</groupId>
37+
<artifactId>jersey-server</artifactId>
38+
<version>${project.version}</version>
39+
</dependency>
40+
41+
<dependency>
42+
<groupId>org.eclipse.microprofile.config</groupId>
43+
<artifactId>microprofile-config-api</artifactId>
44+
<version>${microprofile.config.version}</version>
45+
<scope>provided</scope>
46+
</dependency>
47+
48+
<dependency>
49+
<groupId>junit</groupId>
50+
<artifactId>junit</artifactId>
51+
</dependency>
52+
53+
<dependency>
54+
<groupId>org.mockito</groupId>
55+
<artifactId>mockito-all</artifactId>
56+
</dependency>
57+
58+
<dependency>
59+
<groupId>org.hamcrest</groupId>
60+
<artifactId>hamcrest-library</artifactId>
61+
<scope>test</scope>
62+
</dependency>
63+
</dependencies>
64+
</project>
65+

0 commit comments

Comments
 (0)