001package co.codewizards.cloudstore.rest.client; 002 003import java.security.KeyStore; 004import java.util.Map; 005 006import javax.net.ssl.HostnameVerifier; 007import javax.net.ssl.SSLContext; 008import javax.ws.rs.client.Client; 009import javax.ws.rs.client.ClientBuilder; 010import javax.ws.rs.core.Configuration; 011 012import org.glassfish.jersey.client.ClientConfig; 013import org.glassfish.jersey.client.ClientProperties; 014 015import co.codewizards.cloudstore.core.config.Config; 016import co.codewizards.cloudstore.core.config.ConfigImpl; 017import co.codewizards.cloudstore.rest.client.ssl.HostnameVerifierAllowingAll; 018import co.codewizards.cloudstore.rest.shared.filter.GZIPClientRequestFilter; 019import co.codewizards.cloudstore.rest.shared.interceptor.GZIPReaderInterceptor; 020import co.codewizards.cloudstore.rest.shared.interceptor.GZIPWriterInterceptor; 021 022public class ClientBuilderDefaultValuesDecorator extends ClientBuilder{ 023 private static final int DEFAULT_SOCKET_CONNECT_TIMEOUT = 1 * 60 * 1000; 024 private static final int DEFAULT_SOCKET_READ_TIMEOUT = 5 * 60 * 1000; 025 026 /** 027 * The {@code key} for the connection timeout used with {@link Config#getPropertyAsInt(String, int)}. 028 * <p> 029 * The configuration can be overridden by a system property - see {@link Config#SYSTEM_PROPERTY_PREFIX}. 030 */ 031 public static final String CONFIG_KEY_SOCKET_CONNECT_TIMEOUT = "socket.connectTimeout"; //$NON-NLS-1$ 032 033 /** 034 * The {@code key} for the read timeout used with {@link Config#getPropertyAsInt(String, int)}. 035 * <p> 036 * The configuration can be overridden by a system property - see {@link Config#SYSTEM_PROPERTY_PREFIX}. 037 */ 038 public static final String CONFIG_KEY_SOCKET_READ_TIMEOUT = "socket.readTimeout"; //$NON-NLS-1$ 039 040 private final ClientBuilder builder; 041 042 public ClientBuilderDefaultValuesDecorator(){ 043 this(ClientBuilder.newBuilder()); 044 } 045 046 public ClientBuilderDefaultValuesDecorator(ClientBuilder builder){ 047 this.builder = builder; 048 049 final ClientConfig clientConfig = new ClientConfig(CloudStoreJaxbContextResolver.class); 050 final Integer socketReadTimeout = ConfigImpl.getInstance().getPropertyAsPositiveOrZeroInt( 051 CONFIG_KEY_SOCKET_READ_TIMEOUT, 052 DEFAULT_SOCKET_READ_TIMEOUT); 053 054 final Integer socketConnectTimeout = ConfigImpl.getInstance().getPropertyAsPositiveOrZeroInt( 055 CONFIG_KEY_SOCKET_CONNECT_TIMEOUT, 056 DEFAULT_SOCKET_CONNECT_TIMEOUT); 057 058 clientConfig.property(ClientProperties.CONNECT_TIMEOUT, socketConnectTimeout); // must be a java.lang.Integer 059 clientConfig.property(ClientProperties.READ_TIMEOUT, socketReadTimeout); // must be a java.lang.Integer 060 // The following line allows for PUT without entity. We decide whether to use PUT or POST dependent on whether 061 // it is idempotent (=> PUT) or not (=> POST). Jersey allows to use POST with null as entity, but throws an exception 062 // when trying to PUT the same way. 063 clientConfig.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); 064 065 066 this.builder.withConfig(clientConfig) 067 .register(GZIPReaderInterceptor.class) 068 .register(GZIPClientRequestFilter.class) 069 .register(GZIPWriterInterceptor.class) 070 .hostnameVerifier(new HostnameVerifierAllowingAll()); 071 } 072 073 @Override 074 public Client build(){ 075 return builder.build(); 076 } 077 078 @Override 079 public ClientBuilderDefaultValuesDecorator sslContext(final SSLContext sslContext){ 080 builder.sslContext(sslContext); 081 return this; 082 } 083 084 @Override 085 public ClientBuilderDefaultValuesDecorator hostnameVerifier(final HostnameVerifier hostnameVerifier){ 086 builder.hostnameVerifier(hostnameVerifier); 087 return this; 088 } 089 090 @Override 091 public Configuration getConfiguration() { 092 return builder.getConfiguration(); 093 } 094 095 @Override 096 public ClientBuilder property(String name, Object value) { 097 builder.property(name, value); 098 return this; 099 } 100 101 @Override 102 public ClientBuilder register(Class<?> componentClass) { 103 builder.register(componentClass); 104 return this; 105 } 106 107 @Override 108 public ClientBuilder register(Class<?> componentClass, int priority) { 109 builder.register(componentClass, priority); 110 return this; 111 } 112 113 @Override 114 public ClientBuilder register(Class<?> componentClass, Class<?>... contracts) { 115 builder.register(componentClass, contracts); 116 return this; 117 } 118 119 @Override 120 public ClientBuilder register(Class<?> componentClass, Map<Class<?>, Integer> contracts) { 121 builder.register(componentClass, contracts); 122 return this; 123 } 124 125 @Override 126 public ClientBuilder register(Object component) { 127 builder.register(component); 128 return this; 129 } 130 131 @Override 132 public ClientBuilder register(Object component, int priority) { 133 builder.register(component, priority); 134 return this; 135 } 136 137 @Override 138 public ClientBuilder register(Object component, Class<?>... contracts) { 139 builder.register(component, contracts); 140 return this; 141 } 142 143 @Override 144 public ClientBuilder register(Object component, Map<Class<?>, Integer> contracts) { 145 builder.register(component, contracts); 146 return this; 147 } 148 149 @Override 150 public ClientBuilder withConfig(Configuration config) { 151 builder.withConfig(config); 152 return this; 153 } 154 155 @Override 156 public ClientBuilder keyStore(KeyStore keyStore, char[] password) { 157 builder.keyStore(keyStore, password); 158 return this; 159 } 160 161 @Override 162 public ClientBuilder trustStore(KeyStore trustStore) { 163 builder.trustStore(trustStore); 164 return this; 165 } 166 167}