diff --git a/pom.xml b/pom.xml index f6e8d66..0224ae4 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,11 @@ + + javax.annotation + javax.annotation-api + 1.3.2 + org.springframework spring-context diff --git a/src/main/java/com/inteligr8/rs/Client.java b/src/main/java/com/inteligr8/rs/Client.java index 1700d99..2da7a6e 100644 --- a/src/main/java/com/inteligr8/rs/Client.java +++ b/src/main/java/com/inteligr8/rs/Client.java @@ -72,9 +72,6 @@ public abstract class Client { this.getConfig().configureJacksonMapper(om); JacksonJaxbJsonProvider provider = new JacksonJaxbJsonProvider(om, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS); - provider.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); - provider.disable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE); - this.getConfig().configureJacksonProvider(provider); if (this.getConfig().isWrapRootValueEnabled()) @@ -91,7 +88,6 @@ public abstract class Client { if (authFilter != null) clientBuilder.register(authFilter); this.buildClient(clientBuilder); - this.getConfig().configureClient(clientBuilder); return clientBuilder.build(); diff --git a/src/main/java/com/inteligr8/rs/ClientImpl.java b/src/main/java/com/inteligr8/rs/ClientImpl.java new file mode 100644 index 0000000..330ebc2 --- /dev/null +++ b/src/main/java/com/inteligr8/rs/ClientImpl.java @@ -0,0 +1,83 @@ +/* + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package com.inteligr8.rs; + +import javax.annotation.PostConstruct; +import javax.ws.rs.client.ClientBuilder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * A class that provides pre-configured JAX-RS Client & WebTarget objects + * for Jersey. + * + * @author brian@inteligr8.com + */ +@Component("client.jaxrs") +public class ClientImpl extends Client { + + private final Logger logger = LoggerFactory.getLogger(ClientImpl.class); + + private ClientConfiguration config; + + /** + * This constructor is for Spring or POJO use. + * @param config The client configuration. + */ + @Autowired + public ClientImpl(ClientConfiguration config) { + this.config = config; + } + + /** + * This method registers the Jersey library as the default provider for the + * JAX-RS specification. + */ + @PostConstruct + public void register() { + this.logger.info("API Base URL: {}", this.getConfig().getBaseUrl()); + } + + /** + * @param clientBuilder A client builder. + */ + @Override + public void buildClient(ClientBuilder clientBuilder) { + } + + /** + * @return The client configuration. + */ + public ClientConfiguration getConfig() { + return this.config; + } + + /** + * This method retrieves a JAX-RS implementation of the specified API with + * the specified authorization. + * + * @param authFilter A dynamic authorization filter. + * @param apiClass A JAX-RS annotation API class. + * @return An instance of the API class. + */ + @Override + public T getApi(AuthorizationFilter authFilter, Class apiClass) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/com/inteligr8/rs/LoggingFilter.java b/src/main/java/com/inteligr8/rs/LoggingFilter.java index 3fedd1c..0631659 100644 --- a/src/main/java/com/inteligr8/rs/LoggingFilter.java +++ b/src/main/java/com/inteligr8/rs/LoggingFilter.java @@ -58,7 +58,7 @@ public class LoggingFilter implements ClientRequestFilter, ClientResponseFilter logger.trace("request: {} {}: {}", requestContext.getMethod(), requestContext.getUri(), ((Form)requestContext.getEntity()).asMap()); } else { - this.loggerRequest.trace("request: {} {}: failed to output form", requestContext.getMethod(), requestContext.getUri()); + logger.trace("request: {} {}: failed to output form", requestContext.getMethod(), requestContext.getUri()); } } else { this.logUnhandledRequest(requestContext, logger); diff --git a/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java index 128cefe..77073bc 100755 --- a/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthAuthorizationCodeAuthorizationFilter.java @@ -74,11 +74,15 @@ public class OAuthAuthorizationCodeAuthorizationFilter extends OAuthAuthorizatio @Override protected Form createForm() { - Form form = new Form().param("grant_type", "authorization_code") - .param("code", this.code); + Form form = new Form().param("grant_type", "authorization_code"); if (this.redirectUri != null) form.param("redirect_uri", this.redirectUri.toString()); return form; } + + @Override + protected void extendFormSensitive(Form form) { + form.param("code", this.code); + } } diff --git a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java index be2d42b..389d263 100755 --- a/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthAuthorizationFilter.java @@ -17,12 +17,18 @@ package com.inteligr8.rs; import java.util.Map; import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Form; import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status.Family; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; @@ -33,6 +39,8 @@ import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; */ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final String tokenUrl; private final String clientId; private final String clientSecret; @@ -111,29 +119,49 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { } form.param("client_id", this.clientId); - if (this.clientSecret != null) - form.param("client_secret", this.clientSecret); if (this.scope != null) form.param("scope", this.scope); - this.extendRefreshTokenForm(form); + + this.logger.trace("Sending OAuth request: {}", form); + + if (this.refreshToken != null) { + this.extendRefreshFormSensitive(form); + } else { + this.extendFormSensitive(form); + } + + if (this.clientSecret != null) + form.param("client_secret", this.clientSecret); Entity
entity = Entity.form(form); - WebTarget target = ClientBuilder.newBuilder() - .register(new JacksonJaxbJsonProvider()) - .build() - .target(this.tokenUrl); + Client client = ClientBuilder.newBuilder() + .register(new JacksonJaxbJsonProvider()) + .build(); + WebTarget target = client.target(this.tokenUrl); - @SuppressWarnings("unchecked") - Map response = target.request().post(entity, Map.class); + Response response = target.request().post(entity); - if (response.containsKey("error")) - throw new WebApplicationException((String)response.get("error"), 400); + this.logger.debug("Received OAuth response: {}", response.getStatus()); + + @SuppressWarnings("unchecked") + Map responseMap = response.readEntity(Map.class); + + this.logger.trace("Received OAuth response: {}", responseMap); - this.accessToken = (String)response.get("access_token"); - this.expiration = System.currentTimeMillis() + ((Number)response.get("expires_in")).longValue() * 1000L; - this.refreshToken = (String)response.get("refresh_token"); - this.extendRefreshTokenResponse(response); + if (response.getStatusInfo().getFamily() != Family.SUCCESSFUL) { + String code = (String) responseMap.get("error"); + if (code != null) { + String description = (String) responseMap.get("error_description"); + throw new WebApplicationException(code + ": " + description, response.getStatus()); + } else { + throw new WebApplicationException(response); + } + } + + this.accessToken = (String)responseMap.get("access_token"); + this.expiration = System.currentTimeMillis() + ((Number)responseMap.get("expires_in")).longValue() * 1000L; + this.refreshToken = (String)responseMap.get("refresh_token"); } protected Form createRefreshForm() { @@ -143,10 +171,9 @@ public abstract class OAuthAuthorizationFilter implements AuthorizationFilter { protected abstract Form createForm(); - protected void extendRefreshTokenForm(Form form) { - } - - protected void extendRefreshTokenResponse(Map response) { + protected void extendRefreshFormSensitive(Form form) { } + protected abstract void extendFormSensitive(Form form); + } diff --git a/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java index 79e63da..40856e8 100755 --- a/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthClientCredentialAuthorizationFilter.java @@ -37,5 +37,9 @@ public class OAuthClientCredentialAuthorizationFilter extends OAuthAuthorization protected Form createForm() { return new Form().param("grant_type", "client_credentials"); } + + @Override + protected void extendFormSensitive(Form form) { + } } diff --git a/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java b/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java index 2037127..39a1a2e 100755 --- a/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java +++ b/src/main/java/com/inteligr8/rs/OAuthPasswordGrantAuthorizationFilter.java @@ -53,8 +53,12 @@ public class OAuthPasswordGrantAuthorizationFilter extends OAuthAuthorizationFil @Override protected Form createForm() { return new Form().param("grant_type", "password") - .param("username", this.username) - .param("password", this.password); + .param("username", this.username); + } + + @Override + protected void extendFormSensitive(Form form) { + form.param("password", this.password); } }