3135: Uri Resolver enhancements: create a Genetwork Resolver

Task-Url: https://support.d4science.org/issues/3135

Added new servlet/resolver Geonetwork
Updated pom version at 1.6.0

git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/data-transfer/uri-resolver@126760 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
Francesco Mangiacrapa 2016-04-05 09:57:55 +00:00
parent aad8c90e04
commit ae7ed9ce32
9 changed files with 1171 additions and 51 deletions

View File

@ -8,7 +8,7 @@
</parent> </parent>
<groupId>org.gcube.data.transfer</groupId> <groupId>org.gcube.data.transfer</groupId>
<artifactId>uri-resolver</artifactId> <artifactId>uri-resolver</artifactId>
<version>1.5.0-SNAPSHOT</version> <version>1.6.0-SNAPSHOT</version>
<packaging>war</packaging> <packaging>war</packaging>
<description>The URI Resolver is an HTTP URI resolver implemented as an HTTP servlet which gives access trough HTTP to different protocols URIs. </description> <description>The URI Resolver is an HTTP URI resolver implemented as an HTTP servlet which gives access trough HTTP to different protocols URIs. </description>
@ -95,6 +95,12 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>2.0.2</version>
</dependency>
<!-- END GIS RESOLVER DEPENDENCIES --> <!-- END GIS RESOLVER DEPENDENCIES -->
<dependency> <dependency>

View File

@ -13,19 +13,24 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.gcube.datatransfer.resolver.gis.geonetwork.GeonetworkResolver;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* The Class UriResolverRewriteFilter.
* *
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Nov 20, 2015 * Apr 5, 2016
*/ */
public class UriResolverRewriteFilter implements Filter{ public class UriResolverRewriteFilter implements Filter{
public static final String SERVLET_GEONETWORK = "/geonetwork";
protected static final String SMP_ID = "smp-id"; protected static final String SMP_ID = "smp-id";
protected static final String SERVLET_RESOLVER_BY_ID = "id"; protected static final String SERVLET_RESOLVER_BY_ID = "id";
protected static final Logger logger = LoggerFactory.getLogger(UriResolverRewriteFilter.class); protected static final Logger logger = LoggerFactory.getLogger(UriResolverRewriteFilter.class);
private FilterConfig config;
/* (non-Javadoc) /* (non-Javadoc)
* @see javax.servlet.Filter#destroy() * @see javax.servlet.Filter#destroy()
*/ */
@ -43,7 +48,18 @@ public class UriResolverRewriteFilter implements Filter{
HttpServletRequest request = (HttpServletRequest) req; HttpServletRequest request = (HttpServletRequest) req;
String requestURI = request.getRequestURI(); String requestURI = request.getRequestURI();
String queryString = request.getQueryString(); String queryString = request.getQueryString();
logger.debug("Request URI: " + requestURI + ", QueryString: " +queryString); logger.debug("Request URI: " + requestURI + ", QueryString: " +queryString+ ", Servlet path: "+request.getServletPath());
//IS A REQUEST FOR GEONETWORK AUTHENTICATION? (CKAN HARVESTING?)
if(isGeonetworkRequest(request.getServletPath())){
logger.debug("is geonetwork");
String path = request.getServletPath();
String scope = getScope(path);
String newURI = SERVLET_GEONETWORK + "?" + GeonetworkResolver.SCOPE + "=" + scope;
logger.debug("forward "+newURI);
req.getRequestDispatcher(newURI).forward(req, res);
}else{
//IS WORKSPACE REQUEST?
if (queryString == null) { // IS A /XXXXX if (queryString == null) { // IS A /XXXXX
logger.debug("QueryString is null, is It a new SMP public uri by ID?"); logger.debug("QueryString is null, is It a new SMP public uri by ID?");
int lastSlash = requestURI.lastIndexOf("/"); int lastSlash = requestURI.lastIndexOf("/");
@ -66,13 +82,37 @@ public class UriResolverRewriteFilter implements Filter{
chain.doFilter(req, res); chain.doFilter(req, res);
} }
} }
}
/**
* Gets the scope.
*
* @param servletPath the servlet path
* @return the scope
*/
private String getScope(String servletPath){
logger.debug("Read servlet path: "+servletPath);
String scope = servletPath.substring(servletPath.lastIndexOf("/"), servletPath.length());
return scope.replaceAll("_", "/");
}
/**
* Checks if is geonetwork request.
*
* @param servletPath the servlet path
* @return true, if is geonetwork request
*/
private boolean isGeonetworkRequest(String servletPath){
return servletPath.startsWith(SERVLET_GEONETWORK);
}
/* (non-Javadoc) /* (non-Javadoc)
* @see javax.servlet.Filter#init(javax.servlet.FilterConfig) * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
*/ */
@Override @Override
public void init(FilterConfig arg0) throws ServletException { public void init(FilterConfig config) throws ServletException {
logger.trace("run init"); logger.trace("run init");
this.config = config;
} }
} }

View File

@ -45,7 +45,7 @@ public class GeoRuntimeReader {
boolean isGeoserver = geoservice.equals(GEO_SERVICE.GEOSERVER); boolean isGeoserver = geoservice.equals(GEO_SERVICE.GEOSERVER);
String resourceName = (isGeoserver ? GEOSERVER_RESOURCE_NAME : GEONETWORK_RESOURCE_NAME); String resourceName = isGeoserver ? GEOSERVER_RESOURCE_NAME : GEONETWORK_RESOURCE_NAME;
ScopeProvider.instance.set(scope); ScopeProvider.instance.set(scope);
@ -69,14 +69,11 @@ public class GeoRuntimeReader {
parameters.setUser(ap.username()); //username parameters.setUser(ap.username()); //username
String decryptedPassword = StringEncrypter.getEncrypter().decrypt(ap.password()); String decryptedPassword = StringEncrypter.getEncrypter().decrypt(ap.password());
parameters.setPassword(decryptedPassword); //password parameters.setPassword(decryptedPassword); //password
if (isGeoserver){ if (isGeoserver){
Group<Property> properties = ap.properties(); Group<Property> properties = ap.properties();
if(properties.size()==0) throw new Exception("Properties in resource "+resourceName+" not found"); if(properties.size()==0) throw new Exception("Properties in resource "+resourceName+" not found");
Iterator<Property> iter = properties.iterator(); Iterator<Property> iter = properties.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {

View File

@ -4,19 +4,27 @@
package org.gcube.datatransfer.resolver.gis; package org.gcube.datatransfer.resolver.gis;
/** /**
* The Interface GeonetworkServiceInterface.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* @Oct 7, 2014 * @Oct 7, 2014
*
*/ */
public interface GeonetworkServiceInterface { public interface GeonetworkServiceInterface {
/** /**
* @param scope * Gets the geonetwork instance.
* @param geonetworkInstance *
* @return * @param authenticate the authenticate
* @return the geonetwork instance
* @throws Exception the exception
*/ */
public GeonetworkInstance getGeonetworkInstance(boolean authenticate) throws Exception; public GeonetworkInstance getGeonetworkInstance(boolean authenticate) throws Exception;
/**
* Gets the scope.
*
* @return the scope
*/
public String getScope(); public String getScope();
} }

View File

@ -200,7 +200,7 @@ public class GisResolver extends HttpServlet{
return; return;
} }
logger.info("SCOPE is: " + gisUUID); logger.info("SCOPE is: " + scope);
try { try {

View File

@ -0,0 +1,84 @@
/**
*
*/
package org.gcube.datatransfer.resolver.gis.geonetwork;
import org.apache.commons.httpclient.HttpStatus;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class GNAuthentication.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Apr 4, 2016
*/
public class GNAuthentication {
private static Logger logger = LoggerFactory.getLogger(GNAuthentication.class);
public static final String XML_USER_LOGOUT = "xml.user.logout";
private static final String SRV_EN_XML_USER_LOGIN = "/srv/en/xml.user.login";
/**
* Perform a GN login.<br/>
* GN auth is carried out via a JSESSIONID cookie returned by a successful login
* call.<br/>
*
* <ul>
* <li>Url: <tt>http://<i>server</i>:<i>port</i>/geonetwork/srv/en/xml.user.login</tt></li>
* <li>Mime-type: <tt>application/xml</tt></li>
* <li>Post request: <pre>{@code
* <?xml version="1.0" encoding="UTF-8"?>
* <request>
* <username>user</username>
* <password>pwd</password>
* </request>
* }</pre></li>
* </ul>
*
* @param connection the connection
* @param serviceURL the service url
* @param username the username
* @param password the password
* @return true, if successful
*/
public static boolean login(HTTPCallsUtils connection, String serviceURL, String username, String password) {
Element request = new Element("request");
request.addContent(new Element("username").setText(username));
request.addContent(new Element("password").setText(password));
XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat());
String xml = outputter.outputString(request);
logger.trace("Authentication on Geonetwork: "+xml);
String loginURL = serviceURL+SRV_EN_XML_USER_LOGIN;
connection.postXml(loginURL, xml);
return connection.getLastHttpStatus() == HttpStatus.SC_OK;
}
/**
* Logout.
*
* @param connection the connection
* @param serviceURL the service url
* @return true, if successful
*/
public static boolean logout(HTTPCallsUtils connection, String serviceURL) {
Element request = new Element("request");
XMLOutputter outputter = new XMLOutputter(Format.getCompactFormat());
String xml = outputter.outputString(request);
String logOut = serviceURL+XML_USER_LOGOUT;
connection.postXml(logOut, xml);
return connection.getLastHttpStatus() == HttpStatus.SC_OK;
}
}

View File

@ -0,0 +1,339 @@
/**
*
*/
package org.gcube.datatransfer.resolver.gis.geonetwork;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.gcube.datatransfer.resolver.gis.GeoRuntimeReader;
import org.gcube.datatransfer.resolver.gis.GeoRuntimeReader.GEO_SERVICE;
import org.gcube.datatransfer.resolver.gis.GeonetowrkAccessParameter;
import org.gcube.datatransfer.resolver.gis.GeonetworkServiceInterface;
import org.gcube.datatransfer.resolver.gis.MetadataConverter;
import org.gcube.datatransfer.resolver.gis.entity.ServerParameters;
import org.gcube.datatransfer.resolver.gis.exception.GeonetworkInstanceException;
import org.gcube.datatransfer.resolver.gis.exception.IllegalArgumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class GeonetworkResolver.
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Apr 4, 2016
*
* This class authenticate all query on Geonetwork
*/
public class GeonetworkResolver extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -61097584153314181L;
public static final String SCOPE = "scope";
public static final String CSW_SERVER = "srv/en/csw";
/** The logger. */
private static final Logger logger = LoggerFactory.getLogger(GeonetworkResolver.class);
protected Map<String, ServerParameters> cacheGNServerParams; //A cache: scope - geonetwork parameters
private Timer timer;
//THIRTY MINUTES
public static final long CACHE_RESET_TIME = 30*60*1000;
//TEN MINUTES
public static final long CACHE_RESET_DELAY = 10*1000;
/* (non-Javadoc)
* @see javax.servlet.GenericServlet#init()
*/
@Override
public void init() throws ServletException {
super.init();
timer = new Timer(true);
timer.schedule(new TimerTask() {
@Override
public void run() {
logger.info("Resetting Geonetwork configuratios cache...");
reseCacheServerParameters();
}
}, CACHE_RESET_DELAY, CACHE_RESET_TIME);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String scope = req.getParameter(SCOPE);
if (scope == null || scope.equals("")) {
logger.debug("Scope not found");
sendError(resp, HttpServletResponse.SC_BAD_REQUEST, SCOPE+" not found or empty");
return;
}
logger.info("SCOPE is: " + scope);
try {
ServerParameters geonetworkParams = getGeonetworkCachedServerParameters(scope);
HTTPCallsUtils httpUtils = new HTTPCallsUtils();
boolean authorized = GNAuthentication.login(httpUtils, geonetworkParams.getUrl(), geonetworkParams.getUser(), geonetworkParams.getPassword());
logger.trace("Authorized on "+geonetworkParams +" ? "+authorized);
String gnGetlURL = geonetworkParams.getUrl()+"/"+CSW_SERVER+"?"+req.getQueryString();
logger.info("Sending get request to URL: "+gnGetlURL);
String response = httpUtils.get(geonetworkParams.getUrl()+CSW_SERVER+"?"+req.getQueryString());
InputStream in = IOUtils.toInputStream(response);
OutputStream out = resp.getOutputStream();
try{
int bytes = IOUtils.copy(in, out);
if(bytes==0)
logger.warn("ResponseBody is empty, returning empty resp");
}catch(Exception e){
logger.error("Error on copy response:", e);
}finally{
IOUtils.closeQuietly(in);
}
} catch (IllegalArgumentException e){
logger.error("IllegalArgumentException:", e);
sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "Illegal argument to carry out the request!");
return;
} catch (Exception e) {
logger.error("Exception:", e);
String error = "Sorry, an error occurred on resolving geonetwork request with scope "+scope+". Please, contact support!";
sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
return;
}
}
private String getScope(String servletPath){
String path = servletPath;
logger.debug("Read servlet context: "+path);
String scope = path.substring(path.lastIndexOf("/")+1, path.length());
return scope.replaceAll("_", "/");
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {
String scope = req.getParameter(SCOPE);
if (scope == null || scope.equals("")) {
logger.debug("Scope not found");
sendError(resp, HttpServletResponse.SC_BAD_REQUEST, SCOPE+" not found or empty");
return;
}
logger.info("SCOPE is: " + scope);
try {
ServerParameters geonetworkParams = getGeonetworkCachedServerParameters(scope);
HTTPCallsUtils httpUtils = new HTTPCallsUtils();
boolean authorized = GNAuthentication.login(httpUtils, geonetworkParams.getUrl(), geonetworkParams.getUser(), geonetworkParams.getPassword());
logger.trace("Authorized on "+geonetworkParams +" ? "+authorized);
String gnCSWlURL = geonetworkParams.getUrl()+"/"+CSW_SERVER;
logger.info("Sending CSW request to URL: "+gnCSWlURL);
String response = httpUtils.post(gnCSWlURL, req.getInputStream(), req.getContentType());
InputStream in = IOUtils.toInputStream(response);
OutputStream out = resp.getOutputStream();
try{
int bytes = IOUtils.copy(IOUtils.toInputStream(response), out);
if(bytes==0)
logger.warn("ResponseBody is empty, returning empty resp");
}catch(Exception e){
logger.error("Error on copy response:", e);
}finally{
IOUtils.closeQuietly(in);
}
} catch (IllegalArgumentException e){
logger.error("IllegalArgumentException:", e);
sendError(resp, HttpServletResponse.SC_BAD_REQUEST, "Illegal argument to carry out the request!");
return;
} catch (Exception e) {
logger.error("Exception:", e);
String error = "Sorry, an error occurred on resolving geonetwork request with scope "+scope+". Please, contact support!";
sendError(resp, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
return;
}
}
/**
* Gets the geonetwork cached server parameters.
*
* @param scope the scope
* @return the geonetwork cached server parameters
* @throws Exception the exception
*/
protected ServerParameters getGeonetworkCachedServerParameters(String scope) throws Exception{
if(cacheGNServerParams==null)
reseCacheServerParameters();
logger.info("Tentative for recovering geonetwork server parameters from cache with scope: "+scope);
ServerParameters serverParam = cacheGNServerParams.get(scope);
if(serverParam==null){
logger.info("Cache having null Geonetwork server parameters, reading from IS..");
GeoRuntimeReader reader = new GeoRuntimeReader();
try {
serverParam = reader.retrieveGisParameters(scope, GEO_SERVICE.GEONETWORK);
cacheGNServerParams.put(scope, serverParam);
logger.info("Updated Cache for Geonetwork server parameters! Scope "+scope+" linking "+serverParam);
} catch (Exception e) {
logger.error("An error occurred on reading application profile to "+GEO_SERVICE.GEONETWORK, e);
throw new Exception("Sorry, An error occurred on reading configuration to "+GEO_SERVICE.GEONETWORK);
}
}else
logger.info("Cache gis server param is not null using it");
logger.info("returning geonetworkParams "+serverParam);
return serverParam;
}
/**
* Rese cache server parameters.
*/
private void reseCacheServerParameters(){
cacheGNServerParams = new HashMap<String, ServerParameters>();
logger.info("Cache Geonetwork server params reset!");
}
/**
* Gets the layer wms request.
*
* @param scope the scope
* @param gisUUID the gis uuid
* @param geonetworkParams the geonetwork params
* @return the layer wms request
* @throws Exception the exception
*/
protected String getLayerWmsRequest(String scope, String gisUUID, ServerParameters geonetworkParams) throws Exception{
try {
GeonetworkServiceInterface gntwAccess = new GeonetowrkAccessParameter(scope, geonetworkParams);
return MetadataConverter.getWMSOnLineResource(gntwAccess.getGeonetworkInstance(true), gisUUID);
}catch (GeonetworkInstanceException e){
logger.error("An error occurred when instancing geonetowrk gis layer with UUID "+gisUUID, e);
throw new IllegalArgumentException("Sorry, An error occurred when instancing geonetwork with UUID: "+gisUUID);
} catch (Exception e) {
logger.error("An error occurred when retrieving gis layer with UUID "+gisUUID, e);
throw new IllegalArgumentException("Sorry, An error occurred when retrieving gis layer with UUID "+gisUUID);
}
}
/**
* Send error.
*
* @param response the response
* @param status the status
* @param message the message
* @throws IOException Signals that an I/O exception has occurred.
*/
protected void sendError(HttpServletResponse response, int status, String message) throws IOException
{
// response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.setStatus(status);
logger.info("error message: "+message);
logger.info("writing response...");
StringReader sr = new StringReader(message);
IOUtils.copy(sr, response.getOutputStream());
// response.getWriter().write(resultMessage.toString());
logger.info("response writed");
response.flushBuffer();
}
/**
* Url redirect.
*
* @param req the req
* @param response the response
* @param redirectTo the redirect to
* @throws IOException Signals that an I/O exception has occurred.
*/
protected void urlRedirect(HttpServletRequest req, HttpServletResponse response, String redirectTo) throws IOException {
response.sendRedirect(response.encodeRedirectURL(redirectTo));
return;
}
/**
* Gets the request url.
*
* @param req the req
* @return the request url
*/
public static String getRequestURL(HttpServletRequest req) {
String scheme = req.getScheme(); // http
String serverName = req.getServerName(); // hostname.com
int serverPort = req.getServerPort(); // 80
String contextPath = req.getContextPath(); // /mywebapp
// String servletPath = req.getServletPath(); // /servlet/MyServlet
// String pathInfo = req.getPathInfo(); // /a/b;c=123
// String queryString = req.getQueryString(); // d=789
// Reconstruct original requesting URL
StringBuffer url = new StringBuffer();
url.append(scheme).append("://").append(serverName);
if (serverPort != 80 && serverPort != 443) {
url.append(":").append(serverPort);
}
logger.trace("server: "+url);
logger.trace("omitted contextPath: "+contextPath);
return url.toString();
}
/*
public static void main(String[] args) {
GisResolver gisResolver = new GisResolver();
String scope = "/gcube/devsec/devVRE";
String UUID = "177e1c3c-4a22-4ad9-b015-bfc443d16cb8";
try {
ServerParameters geonetworkParams = gisResolver.getCachedServerParameters(scope);
String wmsRequest = gisResolver.getLayerWmsRequest(scope, UUID, geonetworkParams);
logger.info("Final url is: " + wmsRequest);
wmsRequest = URLEncoder.encode(wmsRequest, UTF_8);
logger.info("Encoded WMS request is: " + wmsRequest);
String gisPortletUrl = gisResolver.getGisViewerApplicationURL(scope);
logger.info("Gis Viewer Application url is: " + gisPortletUrl);
// logger.info("WmsRequest is: " + wmsRequest);
// wmsRequest = encodeURLWithParamDelimiter(wmsRequest);
// logger.info("Encoded url is: " + wmsRequest);
// wmsRequest = appendParamReplacement(wmsRequest);
gisPortletUrl+="?wmsrequest="+wmsRequest;
System.out.println(gisPortletUrl);
// urlRedirect(req, resp, gisPortletUrl);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}*/
}

View File

@ -0,0 +1,634 @@
/**
*
*/
package org.gcube.datatransfer.resolver.gis.geonetwork;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.FileRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.jdom2.Document;
import org.jdom2.input.SAXBuilder;
/**
* The Class HTTPCallsUtils.
* copied by Geosolution
*
* @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it
* Apr 5, 2016
*/
public class HTTPCallsUtils {
private static final Logger logger = Logger.getLogger(HTTPCallsUtils.class);
private final String username;
private final String pw;
/**
* This instance is shared among the various calls, so that the
* state (mainly cookies) will be preserved.
*/
private HttpClient client = new HttpClient();
/**
* Some apps may require application/xml, so you can set it to whatever is needed.
*/
private String xmlContentType = "text/xml";
private int lastHttpStatus;
private boolean ignoreResponseContentOnSuccess = false;
/**
* Instantiates a new HTTP utils.
*/
public HTTPCallsUtils() {
this(null, null);
}
/**
* Instantiates a new HTTP utils.
*
* @param userName the user name
* @param password the password
*/
public HTTPCallsUtils(String userName, String password) {
this.username = userName;
this.pw = password;
}
/**
* Sets the xml content type.
*
* @param xmlContentType the new xml content type
*/
public void setXmlContentType(String xmlContentType) {
this.xmlContentType = xmlContentType;
}
/**
* Gets the last http status.
*
* @return the last http status
*/
public int getLastHttpStatus() {
return lastHttpStatus;
}
/**
* Checks if is ignore response content on success.
*
* @return true, if is ignore response content on success
*/
public boolean isIgnoreResponseContentOnSuccess() {
return ignoreResponseContentOnSuccess;
}
/**
* Sets the ignore response content on success.
*
* @param ignoreResponseContentOnSuccess the new ignore response content on success
*/
public void setIgnoreResponseContentOnSuccess(boolean ignoreResponseContentOnSuccess) {
this.ignoreResponseContentOnSuccess = ignoreResponseContentOnSuccess;
}
/**
* Performs an HTTP GET on the given URL.
*
* @param url The URL where to connect to.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* @throws MalformedURLException the malformed url exception
*/
public String get(String url) throws MalformedURLException {
GetMethod httpMethod = null;
try {
setAuth(client, url, username, pw);
httpMethod = new GetMethod(url);
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
lastHttpStatus = client.executeMethod(httpMethod);
if(lastHttpStatus == HttpStatus.SC_OK) {
InputStream is = httpMethod.getResponseBodyAsStream();
String response = IOUtils.toString(is);
if(response.trim().length()==0) { // sometime gs rest fails
logger.warn("ResponseBody is empty");
return null;
} else {
return response;
}
} else {
logger.info("("+lastHttpStatus+") " + HttpStatus.getStatusText(lastHttpStatus) + " -- " + url );
}
} catch (ConnectException e) {
logger.info("Couldn't connect to ["+url+"]");
} catch (IOException e) {
logger.info("Error talking to ["+url+"]", e);
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
return null;
}
/**
* Performs an HTTP GET on the given URL and return reponse body.
*
* @param url The URL where to connect to.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* @throws MalformedURLException the malformed url exception
*/
public InputStream getBody(String url) throws MalformedURLException {
GetMethod httpMethod = null;
try {
setAuth(client, url, username, pw);
httpMethod = new GetMethod(url);
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
lastHttpStatus = client.executeMethod(httpMethod);
if(lastHttpStatus == HttpStatus.SC_OK) {
return httpMethod.getResponseBodyAsStream();
} else {
logger.info("("+lastHttpStatus+") " + HttpStatus.getStatusText(lastHttpStatus) + " -- " + url );
}
} catch (ConnectException e) {
logger.info("Couldn't connect to ["+url+"]");
} catch (IOException e) {
logger.info("Error talking to ["+url+"]", e);
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
return null;
}
//==========================================================================
//=== PUT
//==========================================================================
/**
* Gets the client.
*
* @return the client
*/
public HttpClient getClient() {
return client;
}
/**
* PUTs a String representing an XML document to the given URL.
*
* @param url The URL where to connect to.
* @param content The XML content to be sent as a String.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String putXml(String url, String content) {
return put(url, content, xmlContentType);
}
/**
* PUTs a File to the given URL.
*
* @param url The URL where to connect to.
* @param file The File to be sent.
* @param contentType The content-type to advert in the PUT.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String put(String url, File file, String contentType) {
return put(url, new FileRequestEntity(file, contentType));
}
/**
* PUTs a String to the given URL.
*
* @param url The URL where to connect to.
* @param content The content to be sent as a String.
* @param contentType The content-type to advert in the PUT.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String put(String url, String content, String contentType) {
try {
return put(url, new StringRequestEntity(content, contentType, null));
} catch (UnsupportedEncodingException ex) {
logger.error("Cannot PUT " + url, ex);
return null;
}
}
/**
* Performs a PUT to the given URL.
*
* @param url The URL where to connect to.
* @param requestEntity The request to be sent.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String put(String url, RequestEntity requestEntity) {
return send(new PutMethod(url), url, requestEntity);
}
//==========================================================================
//=== POST
//==========================================================================
/**
* POSTs a String representing an XML document to the given URL.
*
* @param url The URL where to connect to.
* @param content The XML content to be sent as a String.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String postXml(String url, String content) {
return post(url, content, xmlContentType);
}
/**
* POSTs a Stream content representing an XML document to the given URL.
*
* @param url The URL where to connect to.
* @param content The content to be sent as an InputStream.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String postXml(String url, InputStream content) {
return post(url, content, xmlContentType);
}
/**
* POSTs a File to the given URL.
*
* @param url The URL where to connect to.
* @param file The File to be sent.
* @param contentType The content-type to advert in the POST.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String post(String url, File file, String contentType) {
return post(url, new FileRequestEntity(file, contentType));
}
/**
* POSTs a String to the given URL.
*
* @param url The URL where to connect to.
* @param content The content to be sent as a String.
* @param contentType The content-type to advert in the POST.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String post(String url, String content, String contentType) {
try {
return post(url, new StringRequestEntity(content, contentType, null));
} catch (UnsupportedEncodingException ex) {
logger.error("Cannot POST " + url, ex);
return null;
}
}
/**
* POSTs a Stream content to the given URL.
*
* @param url The URL where to connect to.
* @param content The content to be sent as an InputStream.
* @param contentType The content-type to advert in the POST.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String post(String url, InputStream content, String contentType) {
return post(url, new InputStreamRequestEntity(content, contentType));
}
/**
* Performs a POST to the given URL.
* <BR>Basic auth is used if both username and pw are not null.
*
* @param url The URL where to connect to.
* @param requestEntity The request to be sent.
* @return The HTTP response as a String if the HTTP response code was 200 (OK).
* the HTTP response or <TT>null</TT> on errors.
*/
public String post(String url, RequestEntity requestEntity) {
return send(new PostMethod(url), url, requestEntity);
}
//==========================================================================
//=== HTTP requests
//==========================================================================
/**
* Send an HTTP request (PUT or POST) to a server.
* <BR>Basic auth is used if both username and pw are not null.
* <P>
* Only <UL>
* <LI>200: OK</LI>
* <LI>201: ACCEPTED</LI>
* <LI>202: CREATED</LI>
* </UL> are accepted as successful codes; in these cases the response string will be returned.
*
* @param httpMethod the http method
* @param url the url
* @param requestEntity the request entity
* @return the HTTP response or <TT>null</TT> on errors.
*/
protected String send(final EntityEnclosingMethod httpMethod, String url, RequestEntity requestEntity) {
try {
setAuth(client, url, username, pw);
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
if(requestEntity != null)
httpMethod.setRequestEntity(requestEntity);
lastHttpStatus = client.executeMethod(httpMethod);
switch(lastHttpStatus) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_CREATED:
case HttpURLConnection.HTTP_ACCEPTED:
if(logger.isDebugEnabled())
logger.debug("HTTP "+ httpMethod.getStatusText() + " <-- " + url);
if(ignoreResponseContentOnSuccess)
return "";
String response = IOUtils.toString(httpMethod.getResponseBodyAsStream());
return response;
default:
String badresponse = IOUtils.toString(httpMethod.getResponseBodyAsStream());
String message = getGeoNetworkErrorMessage(badresponse);
logger.warn("Bad response: "+lastHttpStatus
+ " " + httpMethod.getStatusText()
+ " -- " + httpMethod.getName()
+ " " +url
+ " : "
+ message
);
if(logger.isDebugEnabled())
logger.debug("GeoNetwork response:\n"+badresponse);
return null;
}
} catch (ConnectException e) {
logger.info("Couldn't connect to ["+url+"]");
return null;
} catch (IOException e) {
logger.error("Error talking to " + url + " : " + e.getLocalizedMessage());
return null;
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
}
/**
* Send an HTTP request (PUT or POST) to a server.
* <BR>Basic auth is used if both username and pw are not null.
* <P>
* Only <UL>
* <LI>200: OK</LI>
* <LI>201: ACCEPTED</LI>
* <LI>202: CREATED</LI>
* </UL> are accepted as successful codes; in these cases the response string will be returned.
*
* @param httpMethod the http method
* @param url the url
* @param requestEntity the request entity
* @return the HTTP response or <TT>null</TT> on errors.
*/
protected InputStream sendPost(final EntityEnclosingMethod httpMethod, String url, RequestEntity requestEntity) {
try {
setAuth(client, url, username, pw);
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
if(requestEntity != null)
httpMethod.setRequestEntity(requestEntity);
lastHttpStatus = client.executeMethod(httpMethod);
switch(lastHttpStatus) {
case HttpURLConnection.HTTP_OK:
case HttpURLConnection.HTTP_CREATED:
case HttpURLConnection.HTTP_ACCEPTED:
if(logger.isDebugEnabled())
logger.debug("HTTP "+ httpMethod.getStatusText() + " <-- " + url);
return httpMethod.getResponseBodyAsStream();
default:
logger.warn("Bad response: "+lastHttpStatus
+ " " + httpMethod.getStatusText()
+ " -- " + httpMethod.getName()
+ " " +url
);
return httpMethod.getResponseBodyAsStream();
}
} catch (ConnectException e) {
logger.info("Couldn't connect to ["+url+"]");
return null;
} catch (IOException e) {
logger.error("Error talking to " + url + " : " + e.getLocalizedMessage());
return null;
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
}
/**
* Delete.
*
* @param url the url
* @return true, if successful
*/
public boolean delete(String url) {
DeleteMethod httpMethod = null;
try {
// HttpClient client = new HttpClient();
setAuth(client, url, username, pw);
httpMethod = new DeleteMethod(url);
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
lastHttpStatus = client.executeMethod(httpMethod);
String response = "";
if(lastHttpStatus == HttpStatus.SC_OK) {
if(logger.isDebugEnabled())
logger.debug("("+lastHttpStatus+") " + httpMethod.getStatusText() + " -- " + url );
if( ! ignoreResponseContentOnSuccess) {
InputStream is = httpMethod.getResponseBodyAsStream();
response = IOUtils.toString(is);
if(response.trim().equals("")) {
if(logger.isDebugEnabled())
logger.debug("ResponseBody is empty (this may be not an error since we just performed a DELETE call)");
}
}
return true;
} else {
logger.info("("+lastHttpStatus+") " + httpMethod.getStatusText() + " -- " + url );
logger.info("Response: '"+response+"'" );
}
} catch (ConnectException e) {
logger.info("Couldn't connect to ["+url+"]");
} catch (IOException e) {
logger.info("Error talking to ["+url+"]", e);
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
return false;
}
/**
* Http ping.
*
* @param url the url
* @return true if the server response was an HTTP_OK
*/
public boolean httpPing(String url) {
GetMethod httpMethod = null;
try {
// HttpClient client = new HttpClient();
setAuth(client, url, username, pw);
httpMethod = new GetMethod(url);
client.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
lastHttpStatus = client.executeMethod(httpMethod);
if(lastHttpStatus != HttpStatus.SC_OK) {
logger.warn("PING failed at '"+url+"': ("+lastHttpStatus+") " + httpMethod.getStatusText());
return false;
} else {
return true;
}
} catch (ConnectException e) {
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
}
/**
* Used to query for REST resources.
*
* @param url The URL of the REST resource to query about.
* @return true on 200, false on 404.
*/
public boolean exists(String url) {
GetMethod httpMethod = null;
try {
// HttpClient client = new HttpClient();
setAuth(client, url, username, pw);
httpMethod = new GetMethod(url);
client.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
lastHttpStatus = client.executeMethod(httpMethod);
switch(lastHttpStatus) {
case HttpStatus.SC_OK:
return true;
case HttpStatus.SC_NOT_FOUND:
return false;
default:
throw new RuntimeException("Unhandled response status at '"+url+"': ("+lastHttpStatus+") " + httpMethod.getStatusText());
}
} catch (ConnectException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(httpMethod != null)
httpMethod.releaseConnection();
}
}
/**
* Sets the auth.
*
* @param client the client
* @param url the url
* @param username the username
* @param pw the pw
* @throws MalformedURLException the malformed url exception
*/
private static void setAuth(HttpClient client, String url, String username, String pw) throws MalformedURLException {
URL u = new URL(url);
if(username != null && pw != null) {
Credentials defaultcreds = new UsernamePasswordCredentials(username, pw);
client.getState().setCredentials(new AuthScope(u.getHost(), u.getPort()), defaultcreds);
client.getParams().setAuthenticationPreemptive(true); // GS2 by default always requires authentication
} else {
if(logger.isTraceEnabled()) {
logger.trace("Not setting credentials to access to " + url);
}
}
}
/**
* Gets the geo network error message.
*
* @param msg the msg
* @return the geo network error message
*/
protected static String getGeoNetworkErrorMessage(String msg) {
try {
SAXBuilder builder = new SAXBuilder();
Document error = builder.build(new StringReader(msg));
return error.getRootElement().getChildText("message");
} catch (Exception ex) {
return "-";
}
}
/**
* Gets the geo network error message.
*
* @param msg the msg
* @return the geo network error message
*/
protected static String getGeoNetworkErrorMessage(InputStream msg) {
try {
SAXBuilder builder = new SAXBuilder();
Document error = builder.build(msg);
return error.getRootElement().getChildText("message");
} catch (Exception ex) {
return "-";
}
}
}

View File

@ -35,6 +35,13 @@
<load-on-startup>1</load-on-startup> <load-on-startup>1</load-on-startup>
</servlet> </servlet>
<servlet>
<servlet-name>geonetwork</servlet-name>
<display-name>geonetwork</display-name>
<servlet-class>org.gcube.datatransfer.resolver.gis.geonetwork.GeonetworkResolver</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping> <servlet-mapping>
<servlet-name>smp</servlet-name> <servlet-name>smp</servlet-name>
<url-pattern>/smp</url-pattern> <url-pattern>/smp</url-pattern>
@ -50,4 +57,9 @@
<url-pattern>/id</url-pattern> <url-pattern>/id</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>geonetwork</servlet-name>
<url-pattern>/geonetwork</url-pattern>
</servlet-mapping>
</web-app> </web-app>