com.urbanairship.api.client.UrbanAirshipClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-client Show documentation
Show all versions of java-client Show documentation
The Urban Airship Java client library
/*
* Copyright (c) 2013-2016. Urban Airship and Contributors
*/
package com.urbanairship.api.client;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.io.BaseEncoding;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import com.ning.http.client.ProxyServer;
import com.ning.http.client.filter.FilterContext;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* The UrbanAirshipClient class handles HTTP requests to the Urban Airship API.
*/
public class UrbanAirshipClient implements Closeable {
private static final Logger log = LoggerFactory.getLogger(UrbanAirshipClient.class);
private final String appKey;
private final String appSecret;
private final URI baseUri;
private final AsyncHttpClient client;
private UrbanAirshipClient(Builder builder) {
this.appKey = builder.key;
this.appSecret = builder.secret;
this.baseUri = URI.create(builder.baseUri);
AsyncHttpClientConfig.Builder clientConfigBuilder = builder.clientConfigBuilder;
clientConfigBuilder.setUserAgent(getUserAgent());
clientConfigBuilder.addResponseFilter(new RequestRetryFilter(builder.maxRetries, Optional.fromNullable(builder.retryPredicate)));
Optional proxyServer = convertProxyInfo(Optional.fromNullable(builder.proxyInfo));
if (proxyServer.isPresent()) {
clientConfigBuilder.setProxyServer(proxyServer.get());
}
this.client = new AsyncHttpClient(clientConfigBuilder.build());
}
/**
* UrbanAirshipClient builder
* @return Builder
*/
public static Builder newBuilder() {
return new Builder();
}
/**
* Get the app key.
*
* @return The app key.
*/
public String getAppKey() {
return appKey;
}
/**
* Get the app secret.
*
* @return The app secret.
*/
public String getAppSecret() {
return appSecret;
}
/**
* Get the base URI.
*
* @return The base URI.
*/
public URI getBaseUri() {
return baseUri;
}
/**
* Get the underlying HTTP client.
*
* @return The HTTP client.
*/
public AsyncHttpClient getClient() {
return client;
}
/**
* Command for executing Urban Airship requests asynchronously with a ResponseCallback.
*
* @param request An Urban Airship request object.
* @param callback A ResponseCallback instance.
* @return A client response future.
*/
public Future executeAsync(final Request request, final ResponseCallback callback) throws IOException {
AsyncHttpClient.BoundRequestBuilder requestBuilder;
String uri;
try {
uri = request.getUri(baseUri).toString();
} catch (URISyntaxException e) {
log.error("Failed to generate a request URI from base URI " + baseUri.toString(), e);
throw new RuntimeException(e);
}
switch (request.getHttpMethod()) {
case GET:
requestBuilder = client.prepareGet(uri);
break;
case PUT:
requestBuilder = client.preparePut(uri);
break;
case POST:
requestBuilder = client.preparePost(uri);
break;
case DELETE:
requestBuilder = client.prepareDelete(uri);
break;
default:
requestBuilder = client.prepareGet(uri);
break;
}
// Headers
Map requestHeaders = request.getRequestHeaders();
if (requestHeaders != null) {
for (Map.Entry entry : requestHeaders.entrySet()) {
requestBuilder.addHeader(entry.getKey(), entry.getValue());
}
}
// Auth
requestBuilder.setHeader(
"Authorization",
"Basic " + BaseEncoding.base64().encode((appKey + ":" + appSecret).getBytes())
);
// Body
String body = request.getRequestBody();
ContentType contentType = request.getContentType();
if (body != null && contentType != null) {
requestBuilder.setBody(body.getBytes(contentType.getCharset()));
}
log.debug(String.format("Executing Urban Airship request to %s with body %s.", uri, request.getRequestBody()));
ResponseAsyncHandler handler = new ResponseAsyncHandler<>(Optional.fromNullable(callback), request.getResponseParser());
return requestBuilder.execute(handler);
}
/**
* Command for executing Urban Airship requests asynchronously without a ResponseCallback.
*
* @param request An Urban Airship request object.
* @return A client response future.
* @throws IOException
*/
public Future executeAsync(final Request request) throws IOException {
return executeAsync(request, null);
}
/**
* Command for executing Urban Airship requests synchronously with a ResponseCallback.
*
* @param request An Urban Airship request object.
* @param callback A ResponseCallback instance.
* @throws IOException
*/
public Response execute(Request request, ResponseCallback callback) throws IOException {
try {
return executeAsync(request, callback).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Thread interrupted while retrieving response from future", e);
} catch (ExecutionException e) {
throw new RuntimeException("Failed to retrieve response from future", e);
}
}
/**
* Command for executing Urban Airship requests synchronously without a ResponseCallback.
*
* @param request An Urban Airship request object.
* @return A client response.
*/
public Response execute(Request request) throws IOException {
return execute(request, null);
}
/**
* Close the underlying HTTP client's thread pool.
*/
@Override
public void close() {
log.info("Closing client");
client.close();
}
/**
* Retrieve the client user agent.
*
* @return The user agent.
*/
@VisibleForTesting
public String getUserAgent() {
String userAgent = "UNKNOWN";
InputStream stream = getClass().getResourceAsStream("/client.properties");
if (stream != null) {
Properties props = new Properties();
try {
props.load(stream);
stream.close();
userAgent = "UAJavaLib/" + props.get("client.version");
} catch (IOException e) {
log.error("Failed to retrieve client user agent due to IOException - setting to \"UNKNOWN\"", e);
}
}
return userAgent;
}
/**
* Convert the ProxyInfo wrapper into a ProxyServer instance.
*
* @param proxyInfo An optional ProxyInfo instance.
* @return An optional ProxyServer instance.
*/
private Optional convertProxyInfo(Optional proxyInfo) {
if (proxyInfo.isPresent()) {
ProxyServer.Protocol protocol = ProxyServer.Protocol.HTTPS;
for (ProxyServer.Protocol proto : ProxyServer.Protocol.values()) {
if (proxyInfo.get().getProtocol().equals(proto.getProtocol())) {
protocol = proto;
}
}
ProxyServer proxyServer = new ProxyServer(
protocol,
proxyInfo.get().getHost(),
proxyInfo.get().getPort(),
proxyInfo.get().getPrincipal(),
proxyInfo.get().getPassword()
);
return Optional.of(proxyServer);
}
return Optional.absent();
}
/* Object methods */
@Override
public String toString() {
return "UrbanAirshipClient{" +
"appKey='" + appKey + '\'' +
", appSecret='" + appSecret + '\'' +
", baseUri=" + baseUri +
", client=" + client +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof UrbanAirshipClient)) return false;
UrbanAirshipClient that = (UrbanAirshipClient) o;
if (appKey != null ? !appKey.equals(that.appKey) : that.appKey != null) return false;
if (appSecret != null ? !appSecret.equals(that.appSecret) : that.appSecret != null) return false;
if (baseUri != null ? !baseUri.equals(that.baseUri) : that.baseUri != null) return false;
if (client != null ? !client.equals(that.client) : that.client != null) return false;
return true;
}
@Override
public int hashCode() {
int result = appKey != null ? appKey.hashCode() : 0;
result = 31 * result + (appSecret != null ? appSecret.hashCode() : 0);
result = 31 * result + (baseUri != null ? baseUri.hashCode() : 0);
result = 31 * result + (client != null ? client.hashCode() : 0);
return result;
}
/* Builder for newAPIClient */
public static class Builder {
private String key;
private String secret;
private String baseUri;
private Integer maxRetries = 10;
private AsyncHttpClientConfig.Builder clientConfigBuilder = new AsyncHttpClientConfig.Builder();
private ProxyInfo proxyInfo = null;
private Predicate retryPredicate = null;
private Builder() {
baseUri = "https://go.urbanairship.com";
}
/**
* Set the app key.
* @param key String app key
* @return Builder
*/
public Builder setKey(String key) {
this.key = key;
return this;
}
/**
* Set the app secret.
* @param appSecret String app secret
* @return Builder
*/
public Builder setSecret(String appSecret) {
this.secret = appSecret;
return this;
}
/**
* Set the base URI -- defaults to "https://go.urbanairship.com"
* @param URI String base URI
* @return Builder
*/
public Builder setBaseUri(String URI) {
this.baseUri = URI;
return this;
}
/**
* Set the maximum for non-POST request retries on 5xxs -- defaults to 10.
*
* @param maxRetries The maximum.
* @return Builder
*/
public Builder setMaxRetries(Integer maxRetries) {
this.maxRetries = maxRetries;
return this;
}
/**
* Set the client config builder -- defaults to a new builder. Available for custom settings.
*
* @param builder The client config builder.
* @return Builder
*/
public Builder setClientConfigBuilder(AsyncHttpClientConfig.Builder builder) {
this.clientConfigBuilder = builder;
return this;
}
/**
* Set the proxy info.
*
* @param proxyInfo The proxy info.
* @return Builder
*/
public Builder setProxyInfo(ProxyInfo proxyInfo) {
this.proxyInfo = proxyInfo;
return this;
}
/**
* Set an optional predicate for allowing request retries on 5xxs.
*
* @param retryPredicate The retry predicate.
* @return Builder
*/
public Builder setRetryPredicate(Predicate retryPredicate) {
this.retryPredicate = retryPredicate;
return this;
}
/**
* Build an UrbanAirshipClient object. Will fail if any of the following
* preconditions are not met.
*
* 1. App key must be set.
* 2. App secret must be set.
* 3. The base URI has been overridden but not set.
* 4. Max for non-POST 5xx retries must be set, already defaults to 10.
* 5. HTTP client config builder must be set, already defaults to a new builder.
*
*
* @return UrbanAirshipClient
*/
public UrbanAirshipClient build() {
Preconditions.checkNotNull(key, "app key needed to build APIClient");
Preconditions.checkNotNull(secret, "app secret needed to build APIClient");
Preconditions.checkNotNull(baseUri, "base URI needed to build APIClient");
Preconditions.checkNotNull(maxRetries, "max non-POST retries needed to build APIClient");
Preconditions.checkNotNull(clientConfigBuilder, "Async HTTP client config builder needed to build APIClient");
return new UrbanAirshipClient(this);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy