390 lines
11 KiB
Java
390 lines
11 KiB
Java
package org.gcube.common.gxrest.request;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.URLEncoder;
|
|
import java.security.KeyManagementException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.security.cert.CertificateException;
|
|
import java.security.cert.X509Certificate;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Objects;
|
|
|
|
import javax.net.ssl.HostnameVerifier;
|
|
import javax.net.ssl.SSLContext;
|
|
import javax.net.ssl.SSLSession;
|
|
import javax.net.ssl.TrustManager;
|
|
import javax.net.ssl.X509TrustManager;
|
|
import javax.ws.rs.client.Client;
|
|
import javax.ws.rs.client.ClientBuilder;
|
|
import javax.ws.rs.client.Entity;
|
|
import javax.ws.rs.client.Invocation.Builder;
|
|
import javax.ws.rs.client.WebTarget;
|
|
import javax.ws.rs.core.MediaType;
|
|
import javax.ws.rs.core.MultivaluedHashMap;
|
|
import javax.ws.rs.core.MultivaluedMap;
|
|
import javax.ws.rs.core.Response;
|
|
|
|
import org.gcube.common.gxhttp.reference.GXConnection;
|
|
import org.gcube.common.gxhttp.reference.GXHTTP;
|
|
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
/**
|
|
* A GX request based on JAX-RS. It requires a runtime implementation of JAX-RS
|
|
* on the classpath (e.g. Jersey) to work.
|
|
*
|
|
* @author Manuele Simi (ISTI CNR)
|
|
*
|
|
*/
|
|
public class GXWebTargetAdapterRequest implements GXHTTP<Entity<?>,GXInboundResponse> {
|
|
|
|
private WebTarget adaptee;
|
|
private static final Logger logger = LoggerFactory.getLogger(GXWebTargetAdapterRequest.class);
|
|
private MediaType[] mediaType;
|
|
MultivaluedMap<String, Object> headers = new MultivaluedHashMap<String, Object>();
|
|
|
|
/**
|
|
* Creates a new request.
|
|
*
|
|
* @param address
|
|
* the address of the web app to call
|
|
* @return the request
|
|
*/
|
|
public static GXWebTargetAdapterRequest newRequest(String address) {
|
|
return new GXWebTargetAdapterRequest(address, false, "Default");
|
|
}
|
|
|
|
/**
|
|
* Creates a new secure request.
|
|
*
|
|
* @param address
|
|
* the address of the web app to call
|
|
* @param tslprotocol
|
|
* the secure socket protocol to use in the call
|
|
* @return the request
|
|
*/
|
|
public static GXWebTargetAdapterRequest newHTTPSRequest(String address, String tslprotocol) {
|
|
return new GXWebTargetAdapterRequest(address, false, tslprotocol);
|
|
}
|
|
|
|
/**
|
|
* Creates a new request.
|
|
*
|
|
* @param address
|
|
* the address of the web app to call
|
|
|
|
* @return the request
|
|
*/
|
|
public static GXWebTargetAdapterRequest newHTTPSRequest(String address) {
|
|
return new GXWebTargetAdapterRequest(address, true,"Default");
|
|
}
|
|
|
|
/**
|
|
* @param address
|
|
*/
|
|
private GXWebTargetAdapterRequest(String address, boolean withHTTPS, String tslprotocol ) {
|
|
Client client = ClientBuilder.newClient();
|
|
if (withHTTPS) {
|
|
try {
|
|
SSLContext sc = SSLContext.getInstance(tslprotocol);
|
|
TrustManager[] certs = new TrustManager[] { new X509TrustManager() {
|
|
@Override
|
|
public X509Certificate[] getAcceptedIssuers() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void checkServerTrusted(X509Certificate[] chain, String authType)
|
|
throws CertificateException {
|
|
}
|
|
|
|
@Override
|
|
public void checkClientTrusted(X509Certificate[] chain, String authType)
|
|
throws CertificateException {
|
|
}
|
|
} };
|
|
sc.init(null, certs, new java.security.SecureRandom());
|
|
HostnameVerifier allHostsValid = new HostnameVerifier() {
|
|
// insecure host verifier
|
|
@Override
|
|
public boolean verify(String hostname, SSLSession session) {
|
|
return true;
|
|
}
|
|
};
|
|
client = ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier(allHostsValid).build();
|
|
} catch (KeyManagementException | NoSuchAlgorithmException e) {
|
|
client = ClientBuilder.newClient();
|
|
}
|
|
}
|
|
this.adaptee = client.target(address);
|
|
this.headers.add("User-Agent", this.getClass().getSimpleName());
|
|
}
|
|
|
|
/**
|
|
* Sets the identity user agent associated to the request.
|
|
*
|
|
* @param agent
|
|
* @return the request
|
|
*/
|
|
public GXWebTargetAdapterRequest from(String agent) {
|
|
this.headers.add("User-Agent", this.getClass().getSimpleName());
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets a new property in the request.
|
|
*
|
|
* @param name
|
|
* the name of the property
|
|
* @param value
|
|
* the value of the property
|
|
* @return the request
|
|
*/
|
|
public GXWebTargetAdapterRequest configProperty(String name, String value) {
|
|
this.adaptee = this.adaptee.property(name, value);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Registers an instance of a custom JAX-RS component (such as an extension
|
|
* provider or a {@link javax.ws.rs.core.Feature feature} meta-provider) to
|
|
* be instantiated and used in the scope of this request.
|
|
*
|
|
* @param component
|
|
* the component to register
|
|
* @return the request
|
|
*/
|
|
public GXWebTargetAdapterRequest register(Object component) {
|
|
this.adaptee = this.adaptee.register(component);
|
|
return this;
|
|
|
|
}
|
|
|
|
/**
|
|
* Registers a class of a custom JAX-RS component (such as an extension
|
|
* provider or a {@link javax.ws.rs.core.Feature feature} meta-provider) to
|
|
* be instantiated and used in the scope of this request.
|
|
*
|
|
* @param component
|
|
* the class of the component to register
|
|
* @return the request
|
|
*/
|
|
public GXWebTargetAdapterRequest register(Class<?> component) {
|
|
this.adaptee = this.adaptee.register(component);
|
|
return this;
|
|
|
|
}
|
|
|
|
/**
|
|
* Adds a positional path parameter to the request.
|
|
*
|
|
* @param path
|
|
* the new token in the path
|
|
* @return the request
|
|
* @throws UnsupportedEncodingException
|
|
*/
|
|
public GXWebTargetAdapterRequest path(String path) throws UnsupportedEncodingException {
|
|
this.adaptee = this.adaptee.path(path);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets the query parameters for the request.
|
|
*
|
|
* @param parameters
|
|
* the parameters that go in the URL after the address and the
|
|
* path params.
|
|
* @return the request
|
|
* @throws UnsupportedEncodingException
|
|
*/
|
|
public GXWebTargetAdapterRequest queryParams(Map<String, Object[]> parameters) throws UnsupportedEncodingException {
|
|
if (Objects.nonNull(parameters) && !parameters.isEmpty()) {
|
|
for (Entry<String, Object[]> parameter : parameters.entrySet()) {
|
|
this.adaptee = this.adaptee.queryParam(URLEncoder.encode(parameter.getKey(), GXConnection.UTF8),
|
|
parameter.getValue());
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Defines the accepted response media types.
|
|
*
|
|
* @param acceptedResponseTypes
|
|
* accepted response media types.
|
|
* @return builder for a request targeted at the URI referenced by this
|
|
* target instance.
|
|
*/
|
|
public GXWebTargetAdapterRequest setAcceptedResponseType(MediaType... acceptedResponseTypes) {
|
|
this.mediaType = acceptedResponseTypes;
|
|
return this;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#delete()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse delete() throws Exception {
|
|
logger.trace("Sending a DELETE request...");
|
|
Response response = this.buildRequest().delete();
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#head()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse head() throws Exception {
|
|
logger.trace("Sending a HEAD request...");
|
|
Response response = this.buildRequest().head();
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#get()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse get() throws Exception {
|
|
logger.trace("Sending a GET request...");
|
|
Response response = this.buildRequest().get(Response.class);
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Builds the request builder.
|
|
*
|
|
* @return the builder
|
|
*/
|
|
private Builder buildRequest() {
|
|
Builder builder = this.adaptee.request();
|
|
builder.headers(this.headers);
|
|
return builder;
|
|
}
|
|
|
|
/**
|
|
* Add an arbitrary header.
|
|
*
|
|
* @return the builder
|
|
*/
|
|
public GXWebTargetAdapterRequest header(String name, Object value) {
|
|
headers.add(name, value);
|
|
return this;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#put(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public GXInboundResponse put(Entity<?> body) throws Exception {
|
|
logger.trace("Sending a PUT request...");
|
|
if (Objects.nonNull(body))
|
|
return buildGXResponse(this.buildRequest().put(body));
|
|
else
|
|
throw new IllegalArgumentException("Invalid body for the PUT request");
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#put()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse put() throws Exception {
|
|
logger.trace("Sending a PUT request with no body...");
|
|
return buildGXResponse(this.buildRequest().put(null));
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#post(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public GXInboundResponse post(Entity<?> body) throws Exception {
|
|
Objects.requireNonNull(body, "Cannot send a POST request with a null body.");
|
|
logger.trace("Sending a POST request...");
|
|
Response response = this.buildRequest().post(body, Response.class);
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#post()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse post() throws Exception {
|
|
logger.trace("Sending a POST request with no body...");
|
|
Response response = this.buildRequest().post(null, Response.class);
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/**
|
|
* Builds the response.
|
|
*
|
|
* @param source
|
|
* the original response returned by the JAX-RS implementation
|
|
* @return the inbound response
|
|
*/
|
|
private GXInboundResponse buildGXResponse(Response source) {
|
|
return (Objects.isNull(this.mediaType)) ? new GXInboundResponse(source)
|
|
: new GXInboundResponse(source, this.mediaType);
|
|
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#trace()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse trace() throws Exception {
|
|
logger.trace("Sending a TRACE request with no body...");
|
|
Response response = this.buildRequest().trace(Response.class);
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#patch()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse patch() throws Exception {
|
|
throw new UnsupportedOperationException("WebTarget does not support PATCH");
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#options()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse options() throws Exception {
|
|
logger.trace("Sending an OPTIONS request with no body...");
|
|
Response response = this.buildRequest().options(Response.class);
|
|
return buildGXResponse(response);
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see org.gcube.common.gxrest.request.GXHTTP#connect()
|
|
*/
|
|
@Override
|
|
public GXInboundResponse connect() throws Exception {
|
|
throw new UnsupportedOperationException("WebTarget does not support CONNECT");
|
|
}
|
|
|
|
}
|