Aligning pom artifactId to svn location

git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/Common/gxREST@178656 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Luca Frosini 2019-03-22 11:21:36 +00:00
commit 7bba7ebe6e
65 changed files with 4256 additions and 0 deletions

5
.classpath Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

23
.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gxRest</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

36
gxHTTP/.classpath Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

23
gxHTTP/.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gxHTTP</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,6 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8

4
gxHTTP/distro/LICENSE Normal file
View File

@ -0,0 +1,4 @@
gCube System - License
------------------------------------------------------------
${gcube.license}

67
gxHTTP/distro/README Normal file
View File

@ -0,0 +1,67 @@
The gCube System - ${name}
--------------------------------------------------
${description}
${gcube.description}
${gcube.funding}
Version
--------------------------------------------------
${version} (${buildDate})
Please see the file named "changelog.xml" in this directory for the release notes.
Authors
--------------------------------------------------
* Manuele Simi (manuele.simi-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Maintainers
-----------
* Manuele Simi (manuele.simi-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
Binaries can be downloaded from the gCube website:
${gcube.website}
Installation
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}/
Documentation
--------------------------------------------------
Documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}/
Support
--------------------------------------------------
Bugs and support requests can be reported in the gCube issue tracking tool:
${gcube.issueTracking}
Licensing
--------------------------------------------------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<ReleaseNotes>
<Changeset component="org.gcube.common.gxHTTP.1-1-1" date="${buildDate}">
<Change></Change>
</Changeset>
<Changeset component="org.gcube.common.gxHTTP.1-1-0" date="2019-02-26">
<Change>Separated plaing HTTP requests from gxRest</Change>
</Changeset>
<Changeset component="org.gcube.common.gxHTTP.1-0-0" date="2018-12-01">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

28
gxHTTP/distro/profile.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Resource>
<ID />
<Type>Service</Type>
<Profile>
<Description>${description}</Description>
<Class>${serviceClass}</Class>
<Name>${artifactId}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Description>${description}</Description>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Type>Library</Type>
<Files>
<File>${build.finalName}.${project.packaging}</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

63
gxHTTP/pom.xml Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.gcube.common</groupId>
<artifactId>gxREST</artifactId>
<version>1.1.2-SNAPSHOT</version>
</parent>
<groupId>org.gcube.common</groupId>
<artifactId>gxHTTP</artifactId>
<name>gCube eXtensions to REST with HTTP</name>
<description>gCube eXtensions to REST based on HTTP</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<distroDirectory>${project.basedir}/distro</distroDirectory>
</properties>
<scm>
<connection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</connection>
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</developerConnection>
<url>https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</url>
</scm>
<dependencies>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-servicearchive</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,263 @@
package org.gcube.common.gxhttp.reference;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A remote connection for a {@link GXHTTPStringRequest}.
*
* @author Manuele Simi (ISTI-CNR)
* @author Luca Frosini (ISTI-CNR)
*/
public class GXConnection {
public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json;charset=UTF-8";
public static final String PATH_SEPARATOR = "/";
public static final String PARAM_STARTER = "?";
public static final String PARAM_EQUALS = "=";
public static final String PARAM_SEPARATOR = "&";
public static final String UTF8 = "UTF-8";
protected static final Logger logger = LoggerFactory.getLogger(GXConnection.class);
public enum HTTPMETHOD {
HEAD, GET, POST, PUT, DELETE, TRACE, PATCH, OPTIONS, CONNECT;
@Override
public String toString() {
return this.name();
}
}
protected final String address;
protected String path = "", agent;
private String queryParameters;
private String pathParameters;
private String body;
private InputStream bodyAsStream;
private Map<String, String> properties = new HashMap<>();
private boolean extCall = false;
public GXConnection(String address) {
this.address = address;
}
protected void addPath(String pathPart) throws UnsupportedEncodingException {
if (this.path.compareTo("")!=0 && !this.path.endsWith(GXConnection.PATH_SEPARATOR))
this.path += GXConnection.PATH_SEPARATOR;
this.path += Arrays.stream(pathPart.split(GXConnection.PATH_SEPARATOR))
.map(part -> encodePart(part, true))
.collect(Collectors.joining(GXConnection.PATH_SEPARATOR));
}
private String encodePart(String part, boolean path) {
try {
// URL spaces are encoded with + for query parameter
// URL spaces are encoded with %20 for path parts
String encoded = URLEncoder.encode(part, GXConnection.UTF8);
if(path) {
encoded = encoded.replace("+","%20");
}
return encoded;
} catch (UnsupportedEncodingException e) {
return part;
}
}
private URL buildURL() throws MalformedURLException {
StringWriter prepareURL = new StringWriter();
prepareURL.append(address);
Objects.requireNonNull(path, "Null path detected in the request!");
if (address.endsWith(PATH_SEPARATOR)) {
if (path.startsWith(PATH_SEPARATOR)) {
path = path.substring(1);
}
} else {
if (!path.startsWith(PATH_SEPARATOR) && !path.isEmpty()) {
prepareURL.append(PATH_SEPARATOR);
}
}
prepareURL.append(path);
if (Objects.nonNull(this.pathParameters))
prepareURL.append(this.pathParameters);
if (Objects.nonNull(this.queryParameters) && !this.queryParameters.isEmpty()) {
prepareURL.append(PARAM_STARTER);
prepareURL.append(queryParameters);
}
URL url = new URL(prepareURL.toString());
if (url.getProtocol().compareTo("https") == 0) {
url = new URL(url.getProtocol(), url.getHost(), url.getPort()==-1 ? url.getDefaultPort() : url.getPort(), url.getFile());
}
return url;
}
/**
* Sends the request with the given method
*
* @param method
* @return the connection
* @throws Exception
*/
public HttpURLConnection send(HTTPMETHOD method) throws Exception {
return send(this.buildURL(), method);
}
private HttpURLConnection send(URL url, HTTPMETHOD method) throws Exception {
HttpURLConnection uConn = (HttpURLConnection) url.openConnection();
if (!this.extCall) {
String token = SecurityTokenProvider.instance.get();
if (Objects.isNull(token) || token.isEmpty())
throw new IllegalStateException("The security token in the current environment is null.");
uConn.setRequestProperty(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY,
token);
}
uConn.setDoOutput(true);
// uConn.setRequestProperty("Content-type", APPLICATION_JSON_CHARSET_UTF_8);
if(this.agent!=null) {
uConn.setRequestProperty("User-Agent", this.agent);
}
for (String key : properties.keySet()) {
uConn.setRequestProperty(key, properties.get(key));
}
uConn.setRequestMethod(method.toString());
HttpURLConnection.setFollowRedirects(true);
// attach the body
if (Objects.nonNull(this.body) && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) {
DataOutputStream wr = new DataOutputStream(uConn.getOutputStream());
wr.write(this.body.getBytes(GXConnection.UTF8));
wr.flush();
wr.close();
}
// upload the stream
if (Objects.nonNull(this.bodyAsStream) && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) {
DataOutputStream wr = new DataOutputStream(uConn.getOutputStream());
byte[] buffer = new byte[1024];
int len;
while((len = this.bodyAsStream.read(buffer)) > 0) {
wr.write(buffer, 0, len);
}
wr.flush();
wr.close();
}
int responseCode = uConn.getResponseCode();
String responseMessage = uConn.getResponseMessage();
logger.trace("{} {} : {} - {}", method, uConn.getURL(), responseCode, responseMessage);
// if we get a redirect code, we invoke the connection to the new URL
if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
URL redirectURL = getURL(uConn.getHeaderField("Location"));
logger.trace("{} is going to be redirected to {}", url.toString(), redirectURL.toString());
return send(redirectURL, method);
}
return uConn;
}
private URL getURL(String urlString) throws MalformedURLException {
URL url = new URL(urlString);
if (url.getProtocol().equals("https")) {
url = new URL(url.getProtocol(), url.getHost(), url.getDefaultPort(), url.getFile());
}
return url;
}
/**
* @param agent
*/
protected void setAgent(String agent) {
this.agent = agent;
}
/**
* Sets the path parameters for the connection.
*
* @param parameters
*/
public void setPathParameters(String parameters) {
this.pathParameters = parameters;
}
/**
* Sets the query parameters for the connection.
*
* @param parameters
*/
public void setQueryParameters(String parameters) {
this.queryParameters = parameters;
}
/**
* Resets the connection.
*/
public void reset() {
this.pathParameters = "";
this.queryParameters = "";
this.body = "";
}
/**
* The body of the request.
*
* @param body
*/
public void addBody(String body) {
if (Objects.isNull(this.bodyAsStream))
this.body = body;
else
throw new IllegalArgumentException("Cannot set the input stream because addBodyAsStream(InputStream) was already invoked.");
}
/**
* @param bodyAsStream the stream to set as input
*/
public void addBodyAsStream(InputStream bodyAsStream) {
if (Objects.isNull(this.body))
this.bodyAsStream = bodyAsStream;
else
throw new IllegalArgumentException("Cannot set the input stream because addBody(String) was already invoked.");
}
/**
* Adds a property as header.
* @param name
* @param value
*/
public void setProperty(String name, String value) {
this.properties.put(name, value);
}
/**
* @param extCall the extCall to set
*/
public void setExtCall(boolean extCall) {
this.extCall = extCall;
}
/**
* @return the extCall
*/
public boolean isExtCall() {
return extCall;
}
}

View File

@ -0,0 +1,101 @@
package org.gcube.common.gxhttp.reference;
/**
*
* HTTP methods for requests.
*
* @author Manuele Simi (ISTI-CNR)
*
* @param <BODY> the type of the body request
* @param <RESPONSE> the type of the response
*/
public interface GXHTTP<BODY,RESPONSE> {
/**
* Sends the PUT request to the web application.
* @param body the body of the request
* @return the response
*/
RESPONSE put(BODY body) throws Exception;
/**
* Sends the PUT request to the web application with no body.
* @return the response
*/
RESPONSE put() throws Exception;
/**
* Sends the DELETE request to the web application.
* @return the response
*/
RESPONSE delete() throws Exception;
/**
* Sends the HEAD request to the web application.
* @return the response
*/
RESPONSE head() throws Exception;
/**
* Sends the GET request to the web application.
* @return the response
*/
RESPONSE get() throws Exception;
/**
* Sends the POST request to the web application.
* @param body the body of the request
* @return the response
* @throws Exception
*/
RESPONSE post(BODY body) throws Exception;
/**
* Sends the POST request to the web application with no body.
* @return the response
* @throws Exception
*/
RESPONSE post() throws Exception;
/**
* Sends the TRACE request to the web application with no body.
* @return the response
* @throws Exception
*/
RESPONSE trace() throws Exception;
/**
* Sends the PATCH request to the web application with no body.
* @return the response
* @throws Exception
*/
RESPONSE patch() throws Exception;
/**
* Sends the OPTIONS request to the web application with no body.
* @return the response
* @throws Exception
*/
RESPONSE options() throws Exception;
/**
* Sends the CONNECT request to the web application with no body.
* @return the response
* @throws Exception
*/
RESPONSE connect() throws Exception;
/**
* Overrides the default security token.
* @param token the new token
*/
void setSecurityToken(String token);
/**
* States if the service being called in an external service (not gCube).
* @param ext true if external, false otherwise
*/
void isExternalCall(boolean ext);
}

View File

@ -0,0 +1,207 @@
package org.gcube.common.gxhttp.reference;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;
import java.util.Map.Entry;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Builder for GXHTTP Requests.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXHTTPRequestBuilder {
protected static final Logger logger = LoggerFactory.getLogger(GXHTTPRequestBuilder.class);
public GXConnection connection;
/**
* Sets the identity user agent associated to the request.
*
* @param agent
* @return the request
*/
public GXHTTPRequestBuilder from(String agent) {
this.connection.setAgent(agent);
return this;
}
/**
* Adds s positional path parameter to the request.
*
* @param path
* @return the request
* @throws UnsupportedEncodingException
*/
public GXHTTPRequestBuilder path(String path) throws UnsupportedEncodingException {
this.connection.addPath(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 GXHTTPRequestBuilder queryParams(Map<String, String> parameters) throws UnsupportedEncodingException {
if (Objects.nonNull(parameters) && !parameters.isEmpty()) {
StringBuilder result = new StringBuilder();
boolean first = true;
for (Entry<String, String> parameter : parameters.entrySet()) {
if (first) {
first = false;
} else {
result.append(GXConnection.PARAM_SEPARATOR);
}
result.append(URLEncoder.encode(parameter.getKey(), GXConnection.UTF8));
result.append(GXConnection.PARAM_EQUALS);
result.append(URLEncoder.encode(parameter.getValue(), GXConnection.UTF8));
}
connection.setQueryParameters(result.toString());
}
return this;
}
/**
* Overrides the default security token.
*
* @param token
*/
public void setSecurityToken(String token) {
if (!this.connection.isExtCall())
this.connection.setProperty(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY, token);
else
throw new UnsupportedOperationException("Cannot set the security token on an external call");
}
/**
* Add headers to the request.
*
* @param name
* @param value
*/
public GXHTTPRequestBuilder header(String name, String value) {
this.connection.setProperty(name, value);
return this;
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#put()
*/
public HttpURLConnection put() throws Exception {
logger.trace("Sending a PUT request...");
return this.connection.send(HTTPMETHOD.PUT);
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#post()
*/
public HttpURLConnection post() throws Exception {
logger.trace("Sending a POST request...");
return this.connection.send(HTTPMETHOD.POST);
}
/**
* Sends the GET request to the web application.
*
* @return the response
*/
public HttpURLConnection get() throws Exception {
logger.trace("Sending a GET request...");
return this.connection.send(HTTPMETHOD.GET);
}
/**
* Sends the DELETE request to the web application.
*
* @return the response
* @throws Exception
*/
public HttpURLConnection delete() throws Exception {
logger.trace("Sending a DELETE request...");
return this.connection.send(HTTPMETHOD.DELETE);
}
/**
* Sends the HEAD request to the web application.
*
* @return the response
* @throws Exception
*/
public HttpURLConnection head() throws Exception {
logger.trace("Sending a HEAD request...");
return this.connection.send(HTTPMETHOD.HEAD);
}
/**
* Clears all the parameter except the address.
*/
public void clear() {
this.connection.reset();
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#trace()
*/
public HttpURLConnection trace() throws Exception {
logger.trace("Sending a TRACE request...");
return this.connection.send(HTTPMETHOD.TRACE);
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#patch()
*/
public HttpURLConnection patch() throws Exception {
logger.trace("Sending a TRACE request...");
return this.connection.send(HTTPMETHOD.PATCH);
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#options()
*/
public HttpURLConnection options() throws Exception {
logger.trace("Sending an OPTIONS request...");
return this.connection.send(HTTPMETHOD.OPTIONS);
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#connect()
*/
public HttpURLConnection connect() throws Exception {
logger.trace("Sending a CONNECT request...");
return this.connection.send(HTTPMETHOD.CONNECT);
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#isExternalCall(boolean)
*/
public void isExternalCall(boolean ext) {
this.connection.setExtCall(ext);
}
}

View File

@ -0,0 +1,7 @@
/**
* GXHTTP core.
*
* @author Manuele Simi (ISTI CNR)
*
*/
package org.gcube.common.gxhttp.reference;

View File

@ -0,0 +1,107 @@
package org.gcube.common.gxhttp.request;
import java.net.HttpURLConnection;
import org.gcube.common.gxhttp.reference.GXHTTPRequestBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Common logic across GXHTTP requests.
*
* @author Manuele Simi (ISTI CNR)
*
*/
class GXHTTPCommonRequest {
protected static final Logger logger = LoggerFactory.getLogger(GXHTTPStringRequest.class);
protected GXHTTPRequestBuilder builder = new GXHTTPRequestBuilder();
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#put()
*/
public HttpURLConnection put() throws Exception {
return builder.put();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#delete()
*/
public HttpURLConnection delete() throws Exception {
return builder.delete();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#head()
*/
public HttpURLConnection head() throws Exception {
return builder.head();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#get()
*/
public HttpURLConnection get() throws Exception {
return builder.get();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#post()
*/
public HttpURLConnection post() throws Exception {
return builder.post();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#trace()
*/
public HttpURLConnection trace() throws Exception {
return builder.trace();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#patch()
*/
public HttpURLConnection patch() throws Exception {
return builder.patch();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#options()
*/
public HttpURLConnection options() throws Exception {
return builder.options();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#connect()
*/
public HttpURLConnection connect() throws Exception {
return builder.connect();
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#setSecurityToken(java.lang.String)
*/
public void setSecurityToken(String token) {
builder.setSecurityToken(token);
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#isExternalCall(boolean)
*/
public void isExternalCall(boolean ext) {
builder.isExternalCall(ext);
}
/**
* Clear up the request.
*/
public void clear() {
builder.clear();
}
}

View File

@ -0,0 +1,102 @@
package org.gcube.common.gxhttp.request;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.Objects;
import org.gcube.common.gxhttp.reference.GXConnection;
import org.gcube.common.gxhttp.reference.GXHTTP;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
/**
* A context-aware request to a web application.
* It supports sending streams through Put/Post requests.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXHTTPStreamRequest extends GXHTTPCommonRequest
implements GXHTTP<InputStream,HttpURLConnection> {
/**
* A new request.
*/
private GXHTTPStreamRequest(String address) {
builder.connection = new GXConnection(address);
}
/**
* Creates a new request.
*
* @param address
* the address of the web app to call
* @return the request
*/
public static GXHTTPStreamRequest newRequest(String address) {
return new GXHTTPStreamRequest(address);
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#put(java.lang.Object)
*/
@Override
public HttpURLConnection put(InputStream body) throws Exception {
if (Objects.nonNull(body))
builder.connection.addBodyAsStream(body);
logger.trace("Sending a PUT request...");
return builder.connection.send(HTTPMETHOD.PUT);
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#post(java.lang.Object)
*/
@Override
public HttpURLConnection post(InputStream body) throws Exception {
logger.trace("Sending a POST request...");
if (Objects.nonNull(body))
builder.connection.addBodyAsStream(body);
return builder.connection.send(HTTPMETHOD.POST);
}
/**
* @param string
* @return the request
*/
public GXHTTPStreamRequest from(String agent) {
builder.from(agent) ;
return this;
}
/**
* @param path
* @return the request
* @throws UnsupportedEncodingException
*
*/
public GXHTTPStreamRequest path(String path) throws UnsupportedEncodingException {
builder.path(path);
return this;
}
/**
* @param name
* @param value
* @return the request
*/
public GXHTTPStreamRequest header(String name, String value) {
builder.header(name, value);
return this;
}
/**
* @param queryParams
* @return the request
* @throws UnsupportedEncodingException
*/
public GXHTTPStreamRequest queryParams(Map<String, String> queryParams) throws UnsupportedEncodingException {
builder.queryParams(queryParams);
return this;
}
}

View File

@ -0,0 +1,114 @@
package org.gcube.common.gxhttp.request;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.Objects;
import org.gcube.common.gxhttp.reference.GXConnection;
import org.gcube.common.gxhttp.reference.GXHTTP;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
/**
* A context-aware request to a web application.
* It supports sending strings through Put/Post requests.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXHTTPStringRequest extends GXHTTPCommonRequest implements GXHTTP<String,HttpURLConnection> {
/**
* A new request.
*/
private GXHTTPStringRequest(String address) {
builder.connection = new GXConnection(address);
}
/**
* Creates a new request.
*
* @param address
* the address of the web app to call
* @return the request
*/
public static GXHTTPStringRequest newRequest(String address) {
return new GXHTTPStringRequest(address);
}
/**
* Sets the body of the request.
*
* @param body
* @return the request
*/
public GXHTTPStringRequest withBody(String body) {
builder.connection.addBody(body);
return this;
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#put(java.lang.Object)
*/
@Override
public HttpURLConnection put(String body) throws Exception {
if (Objects.nonNull(body))
builder.connection.addBody(body);
logger.trace("Sending a PUT request...");
return builder.connection.send(HTTPMETHOD.PUT);
}
/* (non-Javadoc)
* @see org.gcube.common.gxhttp.reference.GXHTTP#post(java.lang.Object)
*/
@Override
public HttpURLConnection post(String body) throws Exception {
logger.trace("Sending a POST request...");
if (Objects.nonNull(body))
builder.connection.addBody(body);
return builder.connection.send(HTTPMETHOD.POST);
}
/**
* @param string
* @return the request
*/
public GXHTTPStringRequest from(String agent) {
builder.from(agent) ;
return this;
}
/**
* @param string
* @return the request
* @throws UnsupportedEncodingException
*
*/
public GXHTTPStringRequest path(String path) throws UnsupportedEncodingException {
builder.path(path);
return this;
}
/**
* @param name
* @param value
* @return the request
*/
public GXHTTPStringRequest header(String name, String value) {
builder.header(name, value);
return this;
}
/**
* @param queryParams
* @return the request
* @throws UnsupportedEncodingException
*/
public GXHTTPStringRequest queryParams(Map<String, String> queryParams) throws UnsupportedEncodingException {
builder.queryParams(queryParams);
return this;
}
}

View File

@ -0,0 +1,7 @@
/**
* GXHTTP requests.
*
* @author Manuele Simi (ISTI CNR)
*
*/
package org.gcube.common.gxhttp.request;

View File

@ -0,0 +1,140 @@
package org.gcube.common.gxhttp.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/**
* Manipulation of a response's content.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final public class ContentUtils {
/**
* Converts an object to an array of bytes
* @param obj
* @return the bytes
* @throws IOException
*/
public static byte[] toByteArray(Object obj) throws IOException {
byte[] bytes = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray();
} finally {
if (oos != null) {
oos.close();
}
if (bos != null) {
bos.close();
}
}
return bytes;
}
/**
*
* @param inputStream
* @param class1
* @return an instance of type "type"
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static <T> T toObject(InputStream inputStream, Class<T> class1) throws IOException, ClassNotFoundException {
ObjectInput in = null;
T o = null;
try {
in = new ObjectInputStream(inputStream);
o = (T) in.readObject();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
// ignore close exception
}
}
return o;
}
/**
* Converts the array of bytes into an object.
* @param data
* @return the object
* @throws IOException
* @throws ClassNotFoundException
*/
public Object toObject(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
return is.readObject();
}
/**
* Gets the contents of an <code>InputStream</code> as a <code>byte[]</code>.
*
* @param input the <code>InputStream</code> to read from
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
public static byte[] toByteArray(final InputStream input) throws IOException {
return _toByteArray(input);
}
/**
* Gets the contents of an <code>InputStream</code> as a <code>byte[]</code>.
* <p>
* This method buffers the input internally, so there is no need to use a
* <code>BufferedInputStream</code>.
*
* @param input the <code>InputStream</code> to read from
* @return the requested byte array
* @throws NullPointerException if the input is null
* @throws IOException if an I/O error occurs
*/
private static byte[] _toByteArray(final InputStream input) throws IOException {
try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
copyStream(input, output);
return output.toByteArray();
}
}
private static int copyStream(final InputStream input, final OutputStream output) throws IOException {
final byte[] buffer = new byte[1024 * 4];
long count = 0;
int n;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
/**
*
* @param bytes
* @return the string
*/
public static String toString(byte[] bytes) {
return new String(bytes);
}
}

View File

@ -0,0 +1,7 @@
/**
* Utilities.
*
* @author Manuele Simi (ISTI CNR)
*
*/
package org.gcube.common.gxhttp.util;

View File

@ -0,0 +1,116 @@
package org.gcube.common.gxhttp;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;
import org.gcube.common.authorization.client.Constants;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.gxhttp.request.GXHTTPStringRequest;
import org.gcube.common.gxhttp.util.ContentUtils;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test cases for {@link GXHTTPStringRequest}
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class GXHTTPStringRequestTest {
private GXHTTPStringRequest request;
public static String DEFAULT_TEST_SCOPE = "";
static String DEFAULT_RM_URL = "";
static String DEFAULT_RR_URL = "";
private static boolean skipTest = false;
static {
Properties properties = new Properties();
try (InputStream input = GXHTTPStringRequestTest.class.getClassLoader().getResourceAsStream("token.props")) {
// load the properties file
properties.load(input);
DEFAULT_TEST_SCOPE = properties.getProperty("DEFAULT_SCOPE_TOKEN");
if (DEFAULT_TEST_SCOPE.isEmpty())
skipTest = true;
DEFAULT_RM_URL = properties.getProperty("RM_URL");
DEFAULT_RR_URL = properties.getProperty("RR_URL");
} catch (IOException | NullPointerException e) {
skipTest = true;
}
}
@BeforeClass
public static void beforeClass() throws Exception {
setContext(DEFAULT_TEST_SCOPE);
}
public static void setContext(String token) throws ObjectNotFound, Exception {
if (DEFAULT_TEST_SCOPE.isEmpty()) {
skipTest = true;
return;
}
SecurityTokenProvider.instance.set(token);
}
public static String getCurrentScope(String token) throws ObjectNotFound, Exception {
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
String context = authorizationEntry.getContext();
return context;
}
@AfterClass
public static void afterClass() throws Exception {
SecurityTokenProvider.instance.reset();
}
/**
* Test method for {@link org.gcube.common.gxhttp.request.GXHTTPStringRequest#newRequest(java.lang.String)}.
*/
@Before
public void testNewRequest() {
request = GXHTTPStringRequest.newRequest(DEFAULT_RM_URL).from("GXRequestTest");
}
/**
* Test method for {@link org.gcube.common.gxhttp.request.GXHTTPStringRequest#post(java.lang.String)}.
*/
@Test
public void testPostString() {
if (skipTest)
return;
request.clear();
String context ="{\"@class\":\"Context\",\"header\":{\"@class\":\"Header\",\"uuid\":\"6f86dc81-2f59-486b-8aa9-3ab5486313c4\",\"creator\":null,\"modifiedBy\":\"gxRestTest\",\"creationTime\":null,\"lastUpdateTime\":null},\"name\":\"gxTest\",\"parent\":null,\"children\":[]}";
Map<String,String> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", DEFAULT_RR_URL);
try {
HttpURLConnection response = request.path("gxrest")
.header("Another header", "GXHTTPRequestTest")
.queryParams(queryParams).post(context);
assertTrue("Unexpected returned code.", response.getResponseCode() == 200);
String body = ContentUtils.toString(ContentUtils.toByteArray(response.getInputStream()));
System.out.println("Returned string " + body);
} catch (Exception e) {
e.printStackTrace();
fail("Failed to send a POST request");
}
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n</pattern>
</encoder>
</appender>
<logger name="org.gcube" level="INFO" />
<logger name="org.gcube.common.gxrest" level="TRACE" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>

36
gxJRS/.classpath Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

23
gxJRS/.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gxRest</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,6 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding//src/test/resources=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.8

4
gxJRS/distro/LICENSE Normal file
View File

@ -0,0 +1,4 @@
gCube System - License
------------------------------------------------------------
${gcube.license}

67
gxJRS/distro/README Normal file
View File

@ -0,0 +1,67 @@
The gCube System - ${name}
--------------------------------------------------
${description}
${gcube.description}
${gcube.funding}
Version
--------------------------------------------------
${version} (${buildDate})
Please see the file named "changelog.xml" in this directory for the release notes.
Authors
--------------------------------------------------
* Manuele Simi (manuele.simi-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Maintainers
-----------
* Manuele Simi (manuele.simi-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
Binaries can be downloaded from the gCube website:
${gcube.website}
Installation
--------------------------------------------------
Installation documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}/
Documentation
--------------------------------------------------
Documentation is available on-line in the gCube Wiki:
${gcube.wikiRoot}/
Support
--------------------------------------------------
Bugs and support requests can be reported in the gCube issue tracking tool:
${gcube.issueTracking}
Licensing
--------------------------------------------------
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<ReleaseNotes>
<Changeset component="org.gcube.common.gxRest.1-1-1" date="${buildDate}">
<Change></Change>
</Changeset>
<Changeset component="org.gcube.common.gxRest.1-1-0" date="2019-02-26">
<Change>Separated plaing HTTP requests from gxRest</Change>
</Changeset>
<Changeset component="org.gcube.common.gxRest.1-0-0" date="2018-12-01">
<Change>First Release</Change>
</Changeset>
</ReleaseNotes>

28
gxJRS/distro/profile.xml Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Resource>
<ID />
<Type>Service</Type>
<Profile>
<Description>${description}</Description>
<Class>${serviceClass}</Class>
<Name>${artifactId}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Description>${description}</Description>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Type>Library</Type>
<Files>
<File>${build.finalName}.${project.packaging}</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

127
gxJRS/pom.xml Normal file
View File

@ -0,0 +1,127 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.gcube.common</groupId>
<artifactId>gxREST</artifactId>
<version>1.1.2-SNAPSHOT</version>
</parent>
<artifactId>gxJRS</artifactId>
<packaging>jar</packaging>
<name>gCube eXtensions to JAX-RS</name>
<description>gCube eXtensions to REST based on JAX-RS</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<distroDirectory>${project.basedir}/distro</distroDirectory>
</properties>
<scm>
<connection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</connection>
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</developerConnection>
<url>https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${parent.artifactId}/${project.artifactId}</url>
</scm>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey/jersey-bom -->
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>information-system-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>${jaxrs.version}</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>gxHTTP</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Test Dependency -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-servicearchive</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,5 @@
/**
* @author Manuele Simi (ISTI - CNR)
*
*/
package org.gcube.common.gxrest.methods;

View File

@ -0,0 +1,202 @@
package org.gcube.common.gxrest.request;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Objects;
import org.gcube.common.gxhttp.reference.GXConnection;
import org.gcube.common.gxhttp.reference.GXHTTP;
import org.gcube.common.gxhttp.reference.GXHTTPRequestBuilder;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A context-aware request to a web application.
* It supports sending streams through Put/Post requests.
*
* @author Manuele Simi (ISTI-CNR)
* @author Luca Frosini (ISTI-CNR)
*
*/
public class GXHTTPStreamRequest implements GXHTTP<InputStream,GXInboundResponse> {
protected static final Logger logger = LoggerFactory.getLogger(GXHTTPStreamRequest.class);
GXHTTPRequestBuilder builder = new GXHTTPRequestBuilder();
/**
* A new request.
*/
private GXHTTPStreamRequest(String address) {
builder.connection = new GXConnection(address);
}
/**
* Creates a new request.
*
* @param address
* the address of the web app to call
* @return the request
*/
public static GXHTTPStreamRequest newRequest(String address) {
return new GXHTTPStreamRequest(address);
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#put(java.lang.Object)
*/
@Override
public GXInboundResponse put(InputStream body) throws Exception {
if (Objects.nonNull(body))
builder.connection.addBodyAsStream(body);
logger.trace("Sending a PUT request...");
return new GXInboundResponse(builder.connection.send(HTTPMETHOD.PUT));
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#post(java.lang.Object)
*/
@Override
public GXInboundResponse post(InputStream body) throws Exception {
logger.trace("Sending a POST request...");
if (Objects.nonNull(body))
builder.connection.addBodyAsStream(body);
return new GXInboundResponse(builder.connection.send(HTTPMETHOD.POST));
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#put()
*/
@Override
public GXInboundResponse put() throws Exception {
return new GXInboundResponse(builder.put());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#delete()
*/
@Override
public GXInboundResponse delete() throws Exception {
return new GXInboundResponse(builder.delete());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#head()
*/
@Override
public GXInboundResponse head() throws Exception {
return new GXInboundResponse(builder.head());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#get()
*/
@Override
public GXInboundResponse get() throws Exception {
return new GXInboundResponse(builder.get());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#post()
*/
@Override
public GXInboundResponse post() throws Exception {
return new GXInboundResponse(builder.post());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#trace()
*/
@Override
public GXInboundResponse trace() throws Exception {
return new GXInboundResponse(builder.trace());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#patch()
*/
@Override
public GXInboundResponse patch() throws Exception {
return new GXInboundResponse(builder.patch());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#options()
*/
@Override
public GXInboundResponse options() throws Exception {
return new GXInboundResponse(builder.options());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#connect()
*/
@Override
public GXInboundResponse connect() throws Exception {
return new GXInboundResponse(builder.connect());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#setSecurityToken(java.lang.String)
*/
@Override
public void setSecurityToken(String token) {
builder.setSecurityToken(token);
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#isExternalCall(boolean)
*/
@Override
public void isExternalCall(boolean ext) {
builder.isExternalCall(ext);
}
/**
* @param string
* @return the request
*/
public GXHTTPStreamRequest from(String agent) {
builder.from(agent) ;
return this;
}
/**
* Clear up the request.
*/
public void clear() {
builder.clear();
}
/**
* @param path
* @return the request
* @throws UnsupportedEncodingException
*
*/
public GXHTTPStreamRequest path(String path) throws UnsupportedEncodingException {
builder.path(path);
return this;
}
/**
* @param name
* @param value
* @return the request
*/
public GXHTTPStreamRequest header(String name, String value) {
builder.header(name, value);
return this;
}
/**
* @param queryParams
* @return the request
* @throws UnsupportedEncodingException
*/
public GXHTTPStreamRequest queryParams(Map<String, String> queryParams) throws UnsupportedEncodingException {
builder.queryParams(queryParams);
return this;
}
}

View File

@ -0,0 +1,223 @@
package org.gcube.common.gxrest.request;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Objects;
import org.gcube.common.gxhttp.reference.GXConnection;
import org.gcube.common.gxhttp.reference.GXHTTP;
import org.gcube.common.gxhttp.reference.GXHTTPRequestBuilder;
import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD;
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A context-aware request to a web application.
* It supports sending strings through Put/Post requests.
*
* @author Manuele Simi (ISTI-CNR)
* @author Luca Frosini (ISTI-CNR)
*
*/
public class GXHTTPStringRequest implements GXHTTP<String,GXInboundResponse> {
protected static final Logger logger = LoggerFactory.getLogger(GXHTTPStringRequest.class);
GXHTTPRequestBuilder builder = new GXHTTPRequestBuilder();
/**
* A new request.
*/
private GXHTTPStringRequest(String address) {
builder.connection = new GXConnection(address);
}
/**
* Creates a new request.
*
* @param address
* the address of the web app to call
* @return the request
*/
public static GXHTTPStringRequest newRequest(String address) {
return new GXHTTPStringRequest(address);
}
/**
* Sets the body of the request.
*
* @param body
* @return the request
*/
public GXHTTPStringRequest withBody(String body) {
builder.connection.addBody(body);
return this;
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#put(java.lang.Object)
*/
@Override
public GXInboundResponse put(String body) throws Exception {
if (Objects.nonNull(body))
builder.connection.addBody(body);
logger.trace("Sending a PUT request...");
return new GXInboundResponse(builder.connection.send(HTTPMETHOD.PUT));
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#post()
*/
@Override
public GXInboundResponse post(String body) throws Exception {
logger.trace("Sending a POST request...");
if (Objects.nonNull(body))
builder.connection.addBody(body);
return new GXInboundResponse(builder.connection.send(HTTPMETHOD.POST));
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#put()
*/
@Override
public GXInboundResponse put() throws Exception {
return new GXInboundResponse(builder.put());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#delete()
*/
@Override
public GXInboundResponse delete() throws Exception {
return new GXInboundResponse(builder.delete());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#head()
*/
@Override
public GXInboundResponse head() throws Exception {
return new GXInboundResponse(builder.head());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#get()
*/
@Override
public GXInboundResponse get() throws Exception {
return new GXInboundResponse(builder.get());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#post()
*/
@Override
public GXInboundResponse post() throws Exception {
return new GXInboundResponse(builder.post());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#trace()
*/
@Override
public GXInboundResponse trace() throws Exception {
return new GXInboundResponse(builder.trace());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#patch()
*/
@Override
public GXInboundResponse patch() throws Exception {
return new GXInboundResponse(builder.patch());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#options()
*/
@Override
public GXInboundResponse options() throws Exception {
return new GXInboundResponse(builder.options());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#connect()
*/
@Override
public GXInboundResponse connect() throws Exception {
return new GXInboundResponse(builder.connect());
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#setSecurityToken(java.lang.String)
*/
@Override
public void setSecurityToken(String token) {
builder.setSecurityToken(token);
}
/* (non-Javadoc)
* @see org.gcube.common.gxrest.request.GXHTTP#isExternalCall(boolean)
*/
@Override
public void isExternalCall(boolean ext) {
builder.isExternalCall(ext);
}
/**
* @param string
* @return the request
*/
public GXHTTPStringRequest from(String agent) {
builder.from(agent) ;
return this;
}
/**
* Clear up the request.
*/
public void clear() {
builder.clear();
}
/**
* @param string
* @return the request
* @throws UnsupportedEncodingException
*
*/
public GXHTTPStringRequest path(String path) throws UnsupportedEncodingException {
builder.path(path);
return this;
}
/**
* @param name
* @param value
* @return the request
*/
public GXHTTPStringRequest header(String name, String value) {
builder.header(name, value);
return this;
}
/**
* @param queryParams
* @return the request
* @throws UnsupportedEncodingException
*/
public GXHTTPStringRequest queryParams(Map<String, String> queryParams) throws UnsupportedEncodingException {
builder.queryParams(queryParams);
return this;
}
}

View File

@ -0,0 +1,397 @@
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.Objects;
import java.util.Map.Entry;
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.authorization.library.provider.SecurityTokenProvider;
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>();
private boolean extCall = false;
/**
* 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);
}
public static GXWebTargetAdapterRequest newHTTPSRequest(String address) {
return new GXWebTargetAdapterRequest(address, true);
}
/**
* @param address
*/
private GXWebTargetAdapterRequest(String address, boolean withHTTPS) {
Client client = ClientBuilder.newClient();
if (withHTTPS) {
try {
SSLContext sc = SSLContext.getInstance("TLSv1");
System.setProperty("https.protocols", "TLSv1");
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(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY,
SecurityTokenProvider.instance.get());
this.headers.add("User-Agent", this.getClass().getSimpleName());
}
/**
* Overrides the default security token.
*
* @param token
* the new token
*/
@Override
public void setSecurityToken(String token) {
if (!this.extCall)
this.headers.add(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY, token);
else
throw new UnsupportedOperationException("Cannot set the security token on an external call");
}
/**
* 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");
}
/*
* (non-Javadoc)
*
* @see org.gcube.common.gxrest.request.GXHTTP#isExternalCall(boolean)
*/
@Override
public void isExternalCall(boolean ext) {
this.extCall = ext;
}
}

View File

@ -0,0 +1,7 @@
/**
* Requests to web application.
*
* @author Manuele Simi (ISTI - CNR)
*
*/
package org.gcube.common.gxrest.request;

View File

@ -0,0 +1,20 @@
package org.gcube.common.gxrest.response.entity;
import javax.ws.rs.core.GenericEntity;
/**
* An entity to wrap {@link SerializableErrorEntity}s into a {@link WebCodeException}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class CodeEntity extends GenericEntity<SerializableErrorEntity> {
/**
* @param entity
*/
public CodeEntity(SerializableErrorEntity entity) {
super(entity);
}
}

View File

@ -0,0 +1,17 @@
package org.gcube.common.gxrest.response.entity;
/**
*
* Values of the HTTP Entity Tag, used as the value
* of an ETag response header.
*
* @author Manuele Simi (ISTI CNR)
* @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11">HTTP/1.1 section 3.11</a>
*/
public final class EntityTag {
public static final String gxSuccess = "GXSuccessResponse";
public static final String gxError = "GXErrorResponse";
}

View File

@ -0,0 +1,78 @@
package org.gcube.common.gxrest.response.entity;
import org.gcube.common.gxrest.response.outbound.ErrorCode;
/**
* An entity that can be serialized in a {@link WebCodeException}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class SerializableErrorEntity {
private int id = -1;
private String message;
private String exceptionClass;
private String encodedTrace = "";
public SerializableErrorEntity() {}
/**
* @param id
* @param message
*/
public SerializableErrorEntity(ErrorCode errorCode) {
this.id = errorCode.getId();
this.message = errorCode.getMessage();
}
/**
*
* @param e
*/
public SerializableErrorEntity(Exception e) {
this.exceptionClass = e.getClass().getCanonicalName();
this.message = e.getMessage();
}
/**
*
* @param e
*/
public SerializableErrorEntity(Exception e, int lines) {
this.exceptionClass = e.getClass().getCanonicalName();
this.message = e.getMessage();
this.encodedTrace = StackTraceEncoder.encodeTrace(e.getStackTrace(), lines);
}
public int getId() {
return this.id;
}
public String getMessage() {
return this.message;
}
/**
* @return the full qualified name of the embedded {@link Exception}
*/
public String getExceptionClass() {
return this.exceptionClass;
}
/**
* @return the encoded stacktrace
*/
public String getEncodedTrace() {
return encodedTrace;
}
/**
* Checks if a stacktrace is available.
* @return true if a stacktrace is serialized in the entity.
*/
public boolean hasStackTrace() {
return !this.encodedTrace.isEmpty();
}
}

View File

@ -0,0 +1,57 @@
package org.gcube.common.gxrest.response.entity;
import java.util.StringJoiner;
/**
* Encoder for {@link StackTraceElement}.
*
* @author Manuele Simi (ISTI-CNR)
*
*/
public class StackTraceEncoder {
private final static String FIELD_SEPARATOR = "~~";
private final static String ELEMENT_SEPARATOR = "~!~";
private StackTraceEncoder() {
}
/**
* Encodes the stacktrace element as string.
*
* @param element
* @return the encoded element
*/
public static String encodeElement(StackTraceElement element) {
return element.getClassName() + FIELD_SEPARATOR + element.getMethodName() + FIELD_SEPARATOR
+ element.getFileName() + FIELD_SEPARATOR + element.getLineNumber();
}
/**
* Decodes the string as stacktrace element.
*
* @param encoded
* @return the decoded element
*/
public static StackTraceElement decodeElement(String encoded) {
String[] elements = encoded.split(FIELD_SEPARATOR, 4);
return new StackTraceElement(elements[0], elements[1], elements[2], Integer.valueOf(elements[3]));
}
public static String encodeTrace(StackTraceElement[] elements, int lines) {
StringJoiner joiner = new StringJoiner(ELEMENT_SEPARATOR);
for (int i = 0; i < lines; i++)
joiner.add(encodeElement(elements[i]));
return joiner.toString();
}
public static StackTraceElement[] decodeTrace(String joinedTrace) {
String[] encodedElements = joinedTrace.split(ELEMENT_SEPARATOR);
StackTraceElement[] elements = new StackTraceElement[encodedElements.length];
for (int i = 0; i < encodedElements.length; i++)
elements[i] = StackTraceEncoder.decodeElement(encodedElements[i]);
return elements;
}
}

View File

@ -0,0 +1,7 @@
/**
* Core data held by a response.
*
* @author Manuele Simi (ISTI CNR)
*
*/
package org.gcube.common.gxrest.response.entity;

View File

@ -0,0 +1,40 @@
package org.gcube.common.gxrest.response.inbound;
import org.gcube.common.gxrest.response.outbound.ErrorCode;
/**
* Deserializer for {@link ErrorCode}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final class ErrorCodeDeserializer {
/**
*
*/
private ErrorCodeDeserializer() {}
/**
* The error code, if any
* @return the error code or null
*/
protected static ErrorCode deserialize(int id, String message) {
if (id != 1) {
return new ErrorCode() {
@Override
public String getMessage() {
return message;
}
@Override
public int getId() {
return id;
}
};
} else
return null;
}
}

View File

@ -0,0 +1,52 @@
package org.gcube.common.gxrest.response.inbound;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import org.gcube.common.gxrest.response.entity.StackTraceEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Deserializer for {@link Exception}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final class ExceptionDeserializer {
/**
*
*/
private ExceptionDeserializer() {}
private static final Logger logger = LoggerFactory.getLogger(ExceptionDeserializer.class);
/**
* Deserializes the exception.
*
* @param exceptionClass the full qualified class name of the exception to deserialize
* @param message the error message to associate to the exception
* @return
*/
@SuppressWarnings("unchecked")
protected static <E extends Exception> E deserialize(String exceptionClass, String message) {
try {
final Class<?>[] ctorParams = {String.class};
return (E) Class.forName(exceptionClass).getConstructor(ctorParams).newInstance(message);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
logger.error("Failed to deserialize: " + exceptionClass);
return null;
}
}
/**
* Enrich the exception with the stacktrace elements encoded with {@link StackTraceEncoder}
* @param exception
* @param joinedTrace
*/
protected static <E extends Exception> void addStackTrace(E exception, String joinedTrace) {
if (Objects.nonNull(exception))
exception.setStackTrace(StackTraceEncoder.decodeTrace(joinedTrace));
}
}

View File

@ -0,0 +1,361 @@
package org.gcube.common.gxrest.response.inbound;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.gcube.common.gxhttp.util.ContentUtils;
import org.gcube.common.gxrest.response.entity.EntityTag;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntity;
import org.gcube.common.gxrest.response.outbound.ErrorCode;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The response returned from the web application.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXInboundResponse {
private SerializableErrorEntity entity;
private final int responseCode;
private String contentType = "";
private String message = "";
private String body = "";
private byte[] streamedContent;
private Map<String, List<String>> headerFields;
private static final Logger logger = LoggerFactory.getLogger(GXInboundResponse.class);
private boolean hasGXError = false;
private Response source;
private HttpURLConnection connection;
// the content cannot be read more than one time from the response or input
// stream
private boolean contentAlreadyConsumed = false;
private boolean fromConnection = false;
private boolean fromResponse = false;
/**
* Builds a new inbound response.
*
* @param source
* the original response
*/
public GXInboundResponse(Response source) {
this.fromResponse = true;
this.source = source;
this.responseCode = source.getStatusInfo().getStatusCode();
this.message = source.getStatusInfo().getReasonPhrase();
this.headerFields = source.getStringHeaders();
if (Objects.nonNull(source.getMediaType()))
this.contentType = source.getMediaType().getType();
try {
if (Objects.nonNull(source.getEntityTag()) && source.getEntityTag().getValue().equals(EntityTag.gxError)) {
this.entity = source.readEntity(SerializableErrorEntity.class);
this.hasGXError = true;
this.contentAlreadyConsumed = true;
}
} catch (ProcessingException | IllegalStateException ie) {
// if it fails, it's likely message response
// this.message = (String) source.getEntity();
}
}
/**
* @param connection
* the connection from which to parse the information
* @throws IOException
*/
public GXInboundResponse(HttpURLConnection connection) throws IOException {
this.fromConnection = true;
this.connection = connection;
this.responseCode = connection.getResponseCode();
this.message = connection.getResponseMessage();
this.headerFields = connection.getHeaderFields();
this.contentType = connection.getContentType();
// header fields are usually wrapped around double quotes
String eTag = connection.getHeaderField("ETag");
if (Objects.nonNull(eTag) && eTag.replaceAll("^\"|\"$", "").equals(EntityTag.gxError)) {
logger.debug("GXErrorResponse detected.");
this.hasGXError = true;
try {
this.streamedContent = ContentUtils.toByteArray(connection.getErrorStream());
this.contentAlreadyConsumed = true;
this.body = ContentUtils.toString(streamedContent);
this.entity = JsonUtils.fromJson(this.body, SerializableErrorEntity.class);
logger.trace("Response's content: " + this.body);
} catch (Exception ioe) {
logger.warn("No data are available in the response.");
}
} else {
try {
// this.streamedContent =
// ContentUtils.toByteArray(connection.getInputStream());
if (this.contentType.equals(MediaType.TEXT_PLAIN)
|| this.contentType.equals(MediaType.APPLICATION_JSON)) {
this.body = ContentUtils.toString(ContentUtils.toByteArray(connection.getInputStream()));
logger.trace("Response's content: " + this.body);
this.contentAlreadyConsumed = true;
}
} catch (Exception ioe) {
logger.warn("No data are available in the response.", ioe);
}
}
}
/**
* Builds a new inbound response.
*
* @param source
* the original response
* @param expectedMediaTypes
* the expected media type(s) in the response
*/
public GXInboundResponse(Response response, MediaType[] expectedMediaTypes) {
this(response);
if (Objects.isNull(expectedMediaTypes) || expectedMediaTypes.length == 0)
throw new IllegalArgumentException("No expected type was set)");
// validate the media type
boolean compatible = false;
for (MediaType media : expectedMediaTypes) {
if (Objects.nonNull(response.getMediaType()) && response.getMediaType().isCompatible(media))
compatible = true;
}
if (!compatible)
throw new IllegalArgumentException("Received MediaType is not compatible with the expected type(s)");
}
/**
* Checks if there is an {@link Exception} in the entity.
*
* @return true if the entity holds an exception, false otherwise
*/
public boolean hasException() {
return Objects.nonNull(this.entity) && Objects.nonNull(this.entity.getExceptionClass());
}
/**
* Checks if the response is in the range 4xx - 5xx
* .
*
* @return true if it is an error response.
*/
public boolean isErrorResponse() {
return this.getHTTPCode() >= 400 && this.getHTTPCode() < 600;
}
/**
* Checks if the response is in the range 2xx
* .
*
* @return true if it is a success response.
*/
public boolean isSuccessResponse() {
return this.getHTTPCode() >= 200 && this.getHTTPCode() < 300;
}
/**
* Checks if the response was generated as a {@link GXOutboundErrorResponse}
* .
*
* @return true if it is an error response generated with GXRest.
*/
public boolean hasGXError() {
return this.hasGXError;
}
/**
* Gets the {@link Exception} inside the entity.
*
* @return the exception or null
* @throws ClassNotFoundException
* if the exception's class is not available on the classpath
*/
public <E extends Exception> E getException() throws ClassNotFoundException {
if (Objects.nonNull(this.entity)) {
E e = ExceptionDeserializer.deserialize(this.entity.getExceptionClass(), this.entity.getMessage());
if (Objects.nonNull(e)) {
if (this.entity.hasStackTrace())
ExceptionDeserializer.addStackTrace(e, this.entity.getEncodedTrace());
else
e.setStackTrace(new StackTraceElement[] {});
return e;
} else
throw new ClassNotFoundException(
"Failed to deserialize: " + this.entity.getExceptionClass() + ". Not on the classpath?");
} else
return null;
}
/**
* Checks if there is an {@link ErrorCode} in the entity.
*
* @return true if the entity holds an errorcode, false otherwise
*/
public boolean hasErrorCode() {
if (Objects.nonNull(this.entity))
return this.entity.getId() != -1;
else
return false;
}
/**
* Gets the {@link ErrorCode} inside the entity.
*
* @return the error code or null
*/
public ErrorCode getErrorCode() {
if (Objects.nonNull(this.entity))
return ErrorCodeDeserializer.deserialize(this.entity.getId(), this.entity.getMessage());
else
return null;
};
/**
* Gets the message in the response
*
* @return the message
*/
public String getMessage() {
return this.message;
}
/**
* Gets the streamed content as a string, if possible.
*
* @return the content
* @throws IOException
* if unable to read the content
*/
public String getStreamedContentAsString() throws IOException {
if (this.body.isEmpty()) {
this.body = ContentUtils.toString(ContentUtils.toByteArray(getInputStream()));
}
return this.body;
}
public InputStream getInputStream() throws IOException {
if(!this.contentAlreadyConsumed) {
if (this.fromConnection) {
contentAlreadyConsumed = true;
return connection.getInputStream();
} else if (this.fromResponse) {
contentAlreadyConsumed = true;
return (InputStream) source.getEntity();
}
// This code should be never reached
return null;
}
throw new IOException("Content Already Consumed");
}
/**
* Returns the content of the response as byte array.
*
* @return the streamedContent
* @throws IOException
* if unable to read the content
*/
public byte[] getStreamedContent() throws IOException {
if (!this.body.isEmpty()) {
this.streamedContent = this.body.getBytes();
} else {
this.streamedContent = ContentUtils.toByteArray(getInputStream());
}
return this.streamedContent;
}
/**
* Tries to convert the content from its Json serialization, if possible.
*
* @param <T>
* the type of the desired object
* @return an object of type T from the content
* @throws Exception
* if the deserialization fails
*/
public <T> T tryConvertStreamedContentFromJson(Class<T> raw) throws Exception {
return JsonUtils.fromJson(this.getStreamedContentAsString(), raw);
}
/**
* Gets the status code from the HTTP response message.
*
* @return the HTTP code
*/
public int getHTTPCode() {
return this.responseCode;
}
/**
* Checks if the response has a CREATED (201) HTTP status.
*
* @return true if CREATED, false otherwise
*/
public boolean hasCREATEDCode() {
return (this.getHTTPCode() == Status.CREATED.getStatusCode());
}
/**
* Checks if the response has a OK (200) HTTP status.
*
* @return true if OK, false otherwise
*/
public boolean hasOKCode() {
return (this.getHTTPCode() == Status.OK.getStatusCode());
}
/**
* Checks if the response has a NOT_ACCEPTABLE (406) HTTP status.
*
* @return true if NOT_ACCEPTABLE, false otherwise
*/
public boolean hasNOT_ACCEPTABLECode() {
return (this.getHTTPCode() == Status.NOT_ACCEPTABLE.getStatusCode());
}
/**
* Checks if the response has a BAD_REQUEST (400) HTTP status.
*
* @return true if BAD_REQUEST, false otherwise
*/
public boolean hasBAD_REQUESTCode() {
return (this.getHTTPCode() == Status.BAD_REQUEST.getStatusCode());
}
/**
* Returns an unmodifiable Map of the header fields. The Map keys are
* Strings that represent the response-header field names. Each Map value is
* an unmodifiable List of Strings that represents the corresponding field
* values.
*
* @return a Map of header fields
*/
public Map<String, List<String>> getHeaderFields() {
return this.headerFields;
}
/**
* @return the source response, if available
* @throws UnsupportedOperationException
* if not available
*/
public Response getSource() throws UnsupportedOperationException {
if (Objects.isNull(this.source))
new UnsupportedOperationException();
return this.source;
}
}

View File

@ -0,0 +1,46 @@
package org.gcube.common.gxrest.response.inbound;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Manipulation of an {@link GXInboundResponse}'s content.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final public class JsonUtils {
/**
* Deserializes the specified Json bytes into an object of the specified class
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param classOfT the class of T
* @return an object of type T from the bytes
* @throws Exception if the deserialization fails
*/
public static <T> T fromJson(byte[] bytes, Class<T> raw) throws Exception {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(bytes, raw);
} catch (Exception e) {
throw new Exception("Cannot deserialize to the object.", e);
}
}
/**
* Deserializes the specified Json bytes into an object of the specified class
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param raw the class of T
* @return an object of type T from the bytes
* @throws Exception if the deserialization fails
*/
public static <T> T fromJson(String json, Class<T> raw) throws Exception {
try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, raw);
} catch (Exception e) {
throw new Exception("Cannot deserialize to the object.", e);
}
}
}

View File

@ -0,0 +1,8 @@
/**
* Inbound responses for client applications.
* These responses are received at the client side following up a request sent to the web application.
*
* @author Manuele Simi (ISTI CNR)
*
*/
package org.gcube.common.gxrest.response.inbound;

View File

@ -0,0 +1,24 @@
package org.gcube.common.gxrest.response.outbound;
import java.util.stream.Stream;
/**
* Helper methods to find an error code in an enumeration implementing {@link ErrorCode}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class CodeFinder {
/**
* Finds and convert the given code as enum value.
* @param code the code to look for.
* @param codes the enum values.
* @return the code as enum value or null if the code is not found.
*/
public static <E extends Enum<E> & ErrorCode> E findAndConvert(ErrorCode code, E[] codes) {
return Stream.of(codes).filter(e -> e.getId() == code.getId() && e.getMessage().equals(code.getMessage()))
.findFirst().orElse(null);
}
}

View File

@ -0,0 +1,22 @@
package org.gcube.common.gxrest.response.outbound;
/**
* Interface for error codes.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public interface ErrorCode {
/**
* Identifier of the code.
*/
public int getId();
/**
* The message associated to the code
* @return the message
*/
public String getMessage();
}

View File

@ -0,0 +1,77 @@
package org.gcube.common.gxrest.response.outbound;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
/**
* An outbound error response message for applications.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXOutboundErrorResponse {
private GXOutboundErrorResponse() {}
/**
* Throws the exception to the client.
* @param exception
*/
public static void throwException(Exception exception) {
throw new WebStreamException(exception);
}
/**
* Throws the exception to the client.
* @param exception
*/
public static void throwException(Exception exception, Response.Status status) {
throw new WebStreamException(exception, status);
}
/**
* Throws the exception to the client.
* @param exception
* @param keepLines number of lines in the stacktrace to keep (max is 5)
*/
public static void throwExceptionWithTrace(Exception exception, int keepLines, Response.Status status) {
throw new WebStreamException(exception, keepLines, status);
}
/**
* Throws the exception to the client.
* @param exception
* @param keepLines number of lines in the stacktrace to keep (max is 5)
*/
public static void throwExceptionWithTrace(Exception exception, int keepLines) {
throw new WebStreamException(exception, keepLines);
}
/**
* Throws the error code to the client.
* @param code
*/
public static void throwErrorCode(ErrorCode code) {
throw new WebCodeException(code);
}
/**
* Returns the error code to the client with the HTTP status.
* @param code
* @param status
*/
public static void throwErrorCode(ErrorCode code, Response.Status status) {
throw new WebCodeException(code, status);
}
/**
* Returns the HTTP status to the client as error.
* @param status
* @param message
*/
public static void throwHTTPErrorStatus(Response.Status status, String message) {
if (status.getStatusCode() < 400)
throw new IllegalArgumentException("Error status must be >= 400.");
throw new WebApplicationException(message, status.getStatusCode());
}
}

View File

@ -0,0 +1,132 @@
package org.gcube.common.gxrest.response.outbound;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import org.gcube.common.gxrest.response.entity.EntityTag;
/**
* An outbound success response message for applications.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class GXOutboundSuccessResponse {
private ResponseBuilder delegate;
private GXOutboundSuccessResponse() {
}
/**
* Builds a new response with the OK HTTP status.
*
* @return the updated response
*/
public static GXOutboundSuccessResponse newOKResponse() {
GXOutboundSuccessResponse response = new GXOutboundSuccessResponse();
response.delegate = Response.ok();
response.delegate.tag(EntityTag.gxSuccess);
return response;
}
/**
* Builds a new response with the CREATE HTTP status.
*
* @return the updated response
*/
public static GXOutboundSuccessResponse newCREATEResponse(URI location) {
GXOutboundSuccessResponse response = new GXOutboundSuccessResponse();
response.delegate = Response.created(location);
response.delegate.tag(EntityTag.gxSuccess);
return response;
}
/**
* Sets the object as response's content.
* Any Java type instance for a response entity, that is supported by the
* runtime can be passed.
*
* @param o the content
* @return the updated response
* @throws IOException
*/
public GXOutboundSuccessResponse withContent(Object o) throws IOException {
this.delegate.entity(o);
return this;
}
/**
* Reads from the stream the content to set in the response.
*
* @param is the stream
* @return the updated response
* @throws IOException
*/
public GXOutboundSuccessResponse withContent(InputStream is) throws IOException {
this.delegate.entity(is);
return this;
}
/**
* Sets the message as the response's content.
*
* @param message
* @return the updated response
*/
public GXOutboundSuccessResponse withContent(String message) {
this.delegate.entity(message);
this.delegate.type(MediaType.TEXT_PLAIN);
return this;
}
/**
* Adds a type to the response message.
*
* @param type
* @return the updated response
*/
public GXOutboundSuccessResponse ofType(MediaType type) {
this.delegate.type(type);
return this;
}
/**
* Adds a type to the response message.
*
* @param type
* @return the updated response
*/
public GXOutboundSuccessResponse ofType(String type) {
this.delegate.type(type);
return this;
}
/**
* Add an arbitrary header.
*
* @param name the name of the header
* @param value the value of the header, the header will be serialized
* using a {@link javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if
* one is available via {@link javax.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)}
* for the class of {@code value} or using its {@code toString} method
* if a header delegate is not available. If {@code value} is {@code null}
* then all current headers of the same name will be removed.
* @return the updated response.
*/
public GXOutboundSuccessResponse withHeader(String name, Object value) {
this.delegate.header(name, value);
return this;
}
/**
* Builds the response to return.
*
* @return the response
*/
public Response build() {
return this.delegate.build();
}
}

View File

@ -0,0 +1,29 @@
package org.gcube.common.gxrest.response.outbound;
/**
* A local exception wrapping an {@link ErrorCode}.
*
* @author Manuele Simi (ISTI CNR)
*
*/
public class LocalCodeException extends Exception implements ErrorCode {
private static final long serialVersionUID = 1872093579811881630L;
private final int id;
private final String message;
public LocalCodeException(ErrorCode code) {
super();
this.id = code.getId();
this.message = code.getMessage();
}
public int getId() {
return id;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,34 @@
package org.gcube.common.gxrest.response.outbound;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.gcube.common.gxrest.response.entity.CodeEntity;
import org.gcube.common.gxrest.response.entity.EntityTag;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntity;
/**
* Exception with error code returned by a resource method.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final class WebCodeException extends WebApplicationException {
private static final long serialVersionUID = 333945715086602250L;
protected WebCodeException() {
super(Response.status(Response.Status.NOT_ACCEPTABLE).build());
}
protected WebCodeException(ErrorCode code, Response.Status status) {
super(Response.status(status).entity(new CodeEntity(new SerializableErrorEntity(code))).tag(EntityTag.gxError)
.build());
}
protected WebCodeException(ErrorCode code) {
super(Response.status(Response.Status.NOT_ACCEPTABLE)
.entity(new CodeEntity(new SerializableErrorEntity(code))).tag(EntityTag.gxError).build());
}
}

View File

@ -0,0 +1,64 @@
package org.gcube.common.gxrest.response.outbound;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.gcube.common.gxrest.response.entity.CodeEntity;
import org.gcube.common.gxrest.response.entity.EntityTag;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntity;
/**
* An exception returned to the Rest client.
*
* @author Manuele Simi (ISTI CNR)
*
*/
final class WebStreamException extends WebApplicationException {
private static final long serialVersionUID = 822443082773903217L;
/**
* Returns the exception.
*
* @param exception
* @param keepLines
* @param status
* the HTTP status to associate to the response.
*/
protected <E extends Exception> WebStreamException(E exception, int keepLines, Response.Status status) {
super(exception.getCause(), Response.status(status)
.entity(new CodeEntity(new SerializableErrorEntity(exception, keepLines))).tag(EntityTag.gxError).build());
}
/**
* Returns the exception.
*
* @param exception
* @param status
* the HTTP status to associate to the response.
*/
protected <E extends Exception> WebStreamException(E exception, int keepLines) {
this(exception, keepLines, Response.Status.NOT_ACCEPTABLE);
}
/**
* Returns the exception.
*
* @param exception
*/
protected <E extends Exception> WebStreamException(E exception) {
this(exception, 0, Response.Status.NOT_ACCEPTABLE);
}
/**
* Returns the exception.
*
* @param exception
* @param status
* the HTTP status to associate to the response.
*/
protected <E extends Exception> WebStreamException(E exception, Response.Status status) {
this(exception, 0, status);
}
}

View File

@ -0,0 +1,8 @@
/**
* Outbound responses for web applications.
* These responses are returned by the resource methods of the web application.
*
* @author Manuele Simi (ISTI-CNR)
*
*/
package org.gcube.common.gxrest.response.outbound;

View File

@ -0,0 +1,240 @@
package org.gcube.common.gxrest.request;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;
import org.gcube.common.authorization.client.Constants;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import com.fasterxml.jackson.databind.JsonMappingException;
/**
* Test cases for {@link GXHTTPStringRequest}
*
* @author Manuele Simi (ISTI-CNR)
*
*/
@RunWith(BlockJUnit4ClassRunner.class)
public class GXHTTPStringRequestTest {
private GXHTTPStringRequest request;
public static String DEFAULT_TEST_SCOPE = "";
static String DEFAULT_RM_URL = "";
static String DEFAULT_RR_URL = "";
private static boolean skipTest = false;
static {
Properties properties = new Properties();
try (InputStream input = GXHTTPStringRequestTest.class.getClassLoader().getResourceAsStream("token.props")) {
// load the properties file
properties.load(input);
DEFAULT_TEST_SCOPE = properties.getProperty("DEFAULT_SCOPE_TOKEN");
if (DEFAULT_TEST_SCOPE.isEmpty())
skipTest = true;
DEFAULT_RM_URL = properties.getProperty("RM_URL");
DEFAULT_RR_URL = properties.getProperty("RR_URL");
} catch (IOException | NullPointerException e) {
skipTest = true;
}
}
@BeforeClass
public static void beforeClass() throws Exception {
setContext(DEFAULT_TEST_SCOPE);
}
public static void setContext(String token) throws ObjectNotFound, Exception {
if (DEFAULT_TEST_SCOPE.isEmpty()) {
skipTest = true;
return;
}
SecurityTokenProvider.instance.set(token);
}
public static String getCurrentScope(String token) throws ObjectNotFound, Exception {
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
String context = authorizationEntry.getContext();
return context;
}
@AfterClass
public static void afterClass() throws Exception {
SecurityTokenProvider.instance.reset();
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#newRequest(java.lang.String)}.
*/
@Before
public void testNewRequest() {
request = GXHTTPStringRequest.newRequest(DEFAULT_RM_URL).from("GXRequestTest");
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#post()}.
*/
@Test
public void testPost() {
if (skipTest)
return;
request.clear();
String context ="{\"@class\":\"Context\",\"header\":{\"@class\":\"Header\",\"uuid\":\"6f86dc81-2f59-486b-8aa9-3ab5486313c4\",\"creator\":null,\"modifiedBy\":\"gxRestTest\",\"creationTime\":null,\"lastUpdateTime\":null},\"name\":\"gxTest\",\"parent\":null,\"children\":[]}";
Map<String,String> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", DEFAULT_RR_URL);
try {
GXInboundResponse response = request.path("gxrest")
.header("Another header", "GXHTTPRequestTest")
.queryParams(queryParams).post(context);
assertTrue("Unexpected returned code.", response.hasCREATEDCode());
if (response.hasException()) {
try {
throw response.getException();
} catch (ClassNotFoundException e) {
//that's OK, we can tolerate this
} catch (Exception e) {
e.printStackTrace();
throw e;
}
} else {
System.out.println("Returned string " + response.getStreamedContentAsString());
}
} catch (Exception e) {
e.printStackTrace();
fail("Failed to send a POST request");
}
}
@Test(expected=com.fasterxml.jackson.databind.JsonMappingException.class)
public void testPostNoBody() throws Exception {
if (skipTest)
throw new JsonMappingException("");
request.clear();
Map<String,String> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", DEFAULT_RR_URL);
try {
GXInboundResponse response = request.path("gxrest")
.header("Another header", "GXHTTPRequestTest")
.queryParams(queryParams).post();
assertTrue("Unexpected returned code.", response.hasNOT_ACCEPTABLECode());
assertTrue("Unexpected GX status", response.hasGXError());
if (response.hasGXError()) {
try {
throw response.getException();
} catch (ClassNotFoundException e) {
//that's OK, we can tolerate this
} catch (Exception e) {
e.printStackTrace();
throw e;
}
} else {
System.out.println("Returned string " + response.getStreamedContentAsString());
}
} catch (Exception e) {
e.printStackTrace();
throw e;
//fail("Failed to send a POST request");
}
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#get()}.
*/
@Test
public void testGet() {
request.clear();
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#put()}.
*/
@Test
public void testPut() {
if (skipTest)
return;
request.clear();
Map<String,String> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", DEFAULT_RR_URL);
String context ="{\"@class\":\"Context\",\"header\":{\"@class\":\"Header\",\"uuid\":\"6f86dc81-2f59-486b-8aa9-3ab5486313c4\",\"creator\":null,\"modifiedBy\":\"gxRestTest\",\"creationTime\":null,\"lastUpdateTime\":null},\"name\":\"gxTest\",\"parent\":null,\"children\":[]}";
try {
GXInboundResponse response = request.path("gxrest")
.header("Another header", "GXHTTPRequestTest")
.path("5f86dc81-2f59-486b-8aa9-3ab5486313c4").queryParams(queryParams).put(context);
assertTrue("Unexpected returned code.", response.hasCREATEDCode());
if (response.hasException()) {
try {
throw response.getException();
} catch (ClassNotFoundException e) {
//that's OK, we can tolerate this
} catch (Exception e) {
e.printStackTrace();
throw e;
}
} else {
System.out.println("Returned string " + response.getStreamedContentAsString());
}
} catch (Exception e) {
e.printStackTrace();
fail("Failed to send a DELETE request");
}
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#delete()}.
*/
@Test
public void testDelete() {
if (skipTest)
return;
request.clear();
Map<String,String> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", DEFAULT_RR_URL);
try {
GXInboundResponse response = request.path("gxrest")
.header("Another header", "GXHTTPRequestTest")
.path("5f86dc81-2f59-486b-8aa9-3ab5486313c4").queryParams(queryParams).delete();
assertTrue("Unexpected returned code.", response.hasBAD_REQUESTCode());
if (response.hasException()) {
try {
throw response.getException();
} catch (ClassNotFoundException e) {
//that's OK, we can tolerate this
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
} catch (Exception e) {
e.printStackTrace();
fail("Failed to send a DELETE request");
}
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#head()}.
*/
@Test
public void testHead() {
request.clear();
}
}

View File

@ -0,0 +1,178 @@
package org.gcube.common.gxrest.request;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.WeakHashMap;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import org.gcube.common.authorization.client.Constants;
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
import org.gcube.common.authorization.library.AuthorizationEntry;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
/**
* Test cases for {@link GXWebTargetAdapterRequest}
*
* @author Manuele Simi (ISTI-CNR)
*
*/
@RunWith(BlockJUnit4ClassRunner.class)
public class GXWebTargetAdapterRequestTest {
private GXWebTargetAdapterRequest request;
public static String DEFAULT_TEST_SCOPE = "";
static String DEFAULT_RM_URL = "";
static String DEFAULT_RR_URL = "";
private static boolean skipTest = false;
static {
Properties properties = new Properties();
try (InputStream input = GXWebTargetAdapterRequest.class.getClassLoader().getResourceAsStream("token.props")) {
// load the properties file
properties.load(input);
DEFAULT_TEST_SCOPE = properties.getProperty("DEFAULT_SCOPE_TOKEN");
if (DEFAULT_TEST_SCOPE.isEmpty())
skipTest = true;
DEFAULT_RM_URL = properties.getProperty("RM_URL");
DEFAULT_RR_URL = properties.getProperty("RR_URL");
} catch (IOException | NullPointerException e) {
skipTest = true;
}
}
@BeforeClass
public static void beforeClass() throws Exception {
if (!skipTest)
setContext(DEFAULT_TEST_SCOPE);
}
public static void setContext(String token) throws ObjectNotFound, Exception {
if (skipTest || DEFAULT_TEST_SCOPE.isEmpty()) {
skipTest = true;
return;
} else {
SecurityTokenProvider.instance.set(token);
}
}
public static String getCurrentScope(String token) throws ObjectNotFound, Exception {
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
String context = authorizationEntry.getContext();
return context;
}
@AfterClass
public static void afterClass() throws Exception {
SecurityTokenProvider.instance.reset();
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXHTTPStringRequest#newRequest(java.lang.String)}.
*/
@Before
public void testNewRequest() {
request = GXWebTargetAdapterRequest.newRequest(DEFAULT_RM_URL).from("GXRequestTest");
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXWebTargetAdapterRequest#put()}.
*/
@Test
public void testPut() {
if (skipTest)
return;
//fail("Not yet implemented");
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXWebTargetAdapterRequest#delete()}.
*/
@Test
public void testDelete() {
if (skipTest)
return;
//fail("Not yet implemented");
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXWebTargetAdapterRequest#post()}.
*/
@Test
public void testPost() {
if (skipTest)
return;
String context ="{\"@class\":\"Context\",\"header\":{\"@class\":\"Header\",\"uuid\":\"6f86dc81-2f59-486b-8aa9-3ab5486313c4\",\"creator\":null,\"modifiedBy\":\"gxRestTest\",\"creationTime\":null,\"lastUpdateTime\":null},\"name\":\"gxTest\",\"parent\":null,\"children\":[]}";
Map<String,Object[]> queryParams = new WeakHashMap<>();
queryParams.put("rrURL", new String[]{DEFAULT_RR_URL});
try {
GXInboundResponse response = request.path("gxrest")
.header("User-Agent", this.getClass().getSimpleName())
.header("Another header", "another value")
.queryParams(queryParams).post(Entity.entity(context, MediaType.APPLICATION_JSON + ";charset=UTF-8"));
assertTrue("Unexpected returned code.", response.hasCREATEDCode());
if (response.hasGXError()) {
if (response.hasException()) {
try {
throw response.getException();
} catch (ClassNotFoundException e) {
//that's OK, we can tolerate this
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
} else {
if (response.hasCREATEDCode()) {
System.out.println("Resource successfully created!");
System.out.println("Returned message: " + response.getStreamedContentAsString());
} else {
System.out.println("Resource creation failed. Returned status:" + response.getHTTPCode());
//if you want to use the original responser
response.getSource();
//then consume the response
}
}
} catch (Exception e) {
e.printStackTrace();
fail("Failed to send a POST request");
}
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXWebTargetAdapterRequest#head()}.
*/
@Test
public void testHead() {
if (skipTest)
return;
//fail("Not yet implemented");
}
/**
* Test method for {@link org.gcube.common.gxrest.request.GXWebTargetAdapterRequest#get()}.
*/
@Test
public void testGet() {
if (skipTest)
return;
//fail("Not yet implemented");
}
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n</pattern>
</encoder>
</appender>
<logger name="org.gcube" level="INFO" />
<logger name="org.gcube.common.gxrest" level="TRACE" />
<root level="WARN">
<appender-ref ref="STDOUT" />
</root>
</configuration>

1
idea/.idea/.name Normal file
View File

@ -0,0 +1 @@
gxREST

14
idea/.idea/compiler.xml Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="gxHTTP" />
<module name="gxJRS" />
</profile>
</annotationProcessing>
</component>
</project>

8
idea/.idea/encodings.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/.." charset="UTF-8" />
<file url="file://$PROJECT_DIR$/../gxHTTP" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/../gxJRS" charset="UTF-8" />
</component>
</project>

35
idea/.idea/misc.xml Normal file
View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/../pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SvnBranchConfigurationManager">
<option name="myConfigurationMap">
<map>
<entry key="$PROJECT_DIR$/..">
<value>
<SvnBranchConfiguration>
<option name="branchUrls">
<list>
<option value="https://svn.d4science.research-infrastructures.eu/gcube/branches" />
<option value="https://svn.d4science.research-infrastructures.eu/gcube/misc" />
<option value="https://svn.d4science.research-infrastructures.eu/gcube/private" />
<option value="https://svn.d4science.research-infrastructures.eu/gcube/tags" />
</list>
</option>
<option name="trunkUrl" value="https://svn.d4science.research-infrastructures.eu/gcube/trunk" />
</SvnBranchConfiguration>
</value>
</entry>
</map>
</option>
</component>
</project>

6
idea/.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="svn" />
</component>
</project>

69
pom.xml Normal file
View File

@ -0,0 +1,69 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.gcube.tools</groupId>
<artifactId>maven-parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>org.gcube.common</groupId>
<artifactId>gxREST</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>gCube eXtensions to REST</name>
<description>gCube eXtensions to REST</description>
<modules>
<module>gxHTTP</module>
<module>gxJRS</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<serviceClass>Common</serviceClass>
<jersey.version>2.25.1</jersey.version>
<jaxrs.version>2.0.1</jaxrs.version>
</properties>
<scm>
<connection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${project.artifactId}</connection>
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${project.artifactId}</developerConnection>
<url>https://svn.d4science.research-infrastructures.eu/gcube/trunk/common/${project.artifactId}</url>
</scm>
<dependencyManagement>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey/jersey-bom -->
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.gcube.information-system</groupId>
<artifactId>information-system-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
</dependencies>
</project>