/* * COMSAT * Copyright (c) 2013-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.fibers.ws.rs.client; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.security.KeyStore; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.core.Configuration; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; import org.glassfish.jersey.spi.ExecutorServiceProvider; /** * Main entry point to the client API used to bootstrap Client instances that integrate with Quasar fibers. */ public class AsyncClientBuilder extends ClientBuilder { private final ClientBuilder clientBuilder; protected AsyncClientBuilder(ClientBuilder clientBuilder) { this.clientBuilder = clientBuilder; } /** * Create a new {@code ClientBuilder} instance using the default client builder * implementation class provided by the JAX-RS implementation provider. * * @return new client builder instance. */ public static ClientBuilder newBuilder() { return new AsyncClientBuilder(ClientBuilder.newBuilder().withConfig(addDefaultConfigurations(null))); } /** * Create a new {@link Client} instance using the default client builder implementation * class provided by the JAX-RS implementation provider. * * @return new client instance. */ public static Client newClient() { return newClient(null); } /** * Create a new custom-configured {@link Client} instance using the default client builder * implementation class provided by the JAX-RS implementation provider. * * @param configuration data used to provide initial configuration for the new client instance. * @return a new, configured, client instance. */ public static Client newClient(Configuration configuration) { return new FiberClient(ClientBuilder.newClient(addDefaultConfigurations(configuration))); } private static ClientConfig addDefaultConfigurations(Configuration configuration) { // currently there is no usage with the singleThreadPool variable due to jersey bug. See below. final ExecutorServiceProvider singleThreadPool = new ExecutorServiceProvider() { private ExecutorService tp = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(true).setNameFormat("jersey-puniverse-single-worker-%d").build()); @Override public ExecutorService getExecutorService() { return tp; } @Override public void dispose(ExecutorService es) { } }; final ClientConfig config = new ClientConfig(). // This is commented since, jersey has major problem (since ~2.5) - it blocks the calling thread !!! // When this bug will be fixed we should uncomment this line in order to enable a lot of concurrent open requsets // register(singleThreadPool, RequestExecutorProvider.class). property(ClientProperties.ASYNC_THREADPOOL_SIZE, 20); if (configuration != null) config.loadFrom(configuration); if (config.getConnectorProvider() == null) config.connectorProvider(new JettyConnectorProvider()); return config; } @Override public Client build() { return new FiberClient(clientBuilder.build()); } @Override public ClientBuilder withConfig(Configuration config) { clientBuilder.withConfig(addDefaultConfigurations(config)); return this; } @Override public ClientBuilder sslContext(SSLContext sslContext) { clientBuilder.sslContext(sslContext); return this; } @Override public ClientBuilder keyStore(KeyStore keyStore, char[] password) { clientBuilder.keyStore(keyStore, password); return this; } @Override public ClientBuilder keyStore(KeyStore keyStore, String password) { clientBuilder.keyStore(keyStore, password); return this; } @Override public ClientBuilder trustStore(KeyStore trustStore) { clientBuilder.trustStore(trustStore); return this; } @Override public ClientBuilder hostnameVerifier(HostnameVerifier verifier) { clientBuilder.hostnameVerifier(verifier); return this; } @Override public ClientBuilder property(String name, Object value) { clientBuilder.property(name, value); return this; } @Override public ClientBuilder register(Class<?> componentClass) { clientBuilder.register(componentClass); return this; } @Override public ClientBuilder register(Class<?> componentClass, int priority) { clientBuilder.register(componentClass, priority); return this; } @Override public ClientBuilder register(Class<?> componentClass, Class<?>... contracts) { clientBuilder.register(componentClass, contracts); return this; } @Override public ClientBuilder register(Class<?> componentClass, Map<Class<?>, Integer> contracts) { clientBuilder.register(componentClass, contracts); return this; } @Override public ClientBuilder register(Object component) { clientBuilder.register(component); return this; } @Override public ClientBuilder register(Object component, int priority) { clientBuilder.register(component, priority); return this; } @Override public ClientBuilder register(Object component, Class<?>... contracts) { clientBuilder.register(component, contracts); return this; } @Override public ClientBuilder register(Object component, Map<Class<?>, Integer> contracts) { clientBuilder.register(component, contracts); return this; } @Override public Configuration getConfiguration() { return clientBuilder.getConfiguration(); } @Override public int hashCode() { return clientBuilder.hashCode(); } @Override public boolean equals(Object obj) { return clientBuilder.equals(obj); } @Override public String toString() { return clientBuilder.toString(); } }