diff --git a/.gitignore b/.gitignore index 663b123..52a325b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,182 @@ -target -.classpath +# Created by https://www.toptal.com/developers/gitignore/api/eclipse,visualstudiocode,linux,macos,java,maven +# Edit at https://www.toptal.com/developers/gitignore?templates=eclipse,visualstudiocode,linux,macos,java,maven + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +### Eclipse Patch ### +# Spring Boot Tooling +.sts4-cache/ + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core .project -/.DS_Store +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/eclipse,visualstudiocode,linux,macos,java,maven \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cac25a..fb83217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm # Changelog for Document Store Backend Connector Library for Accounting Service -## [v2.0.1-SNAPSHOT] +## [v3.0.0-SNAPSHOT] -- Moved http links to https in comments +- Migrated code to comply with smartgears 4 +- Moved to Java 17 +- Upgraded maven-parent to 1.2.0 +- Upgraded gcbe-bom to 4.0.0 - Fixed test ## [v2.0.0] diff --git a/pom.xml b/pom.xml index ffcdb50..cae1b9a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,16 +4,19 @@ org.gcube.tools maven-parent - 1.1.0 + 1.2.0 org.gcube.data.publishing document-store-lib-accounting-service - 2.0.1-SNAPSHOT + 3.0.0-SNAPSHOT Document Store Backend Connector Library for Accounting Service Document Store Backend Connector Library for Accounting Service + 17 + ${java.version} + ${java.version} UTF-8 DataPublishing @@ -29,7 +32,7 @@ org.gcube.distribution gcube-bom - 2.0.0 + 4.0.0 pom import @@ -41,17 +44,9 @@ org.slf4j slf4j-api - - org.gcube.core - common-scope - org.gcube.common - authorization-client - - - org.gcube.common - common-authorization + gxHTTP org.gcube.core diff --git a/src/main/java/org/gcube/documentstore/persistence/HTTPCall.java b/src/main/java/org/gcube/documentstore/persistence/HTTPCall.java deleted file mode 100644 index a801a30..0000000 --- a/src/main/java/org/gcube/documentstore/persistence/HTTPCall.java +++ /dev/null @@ -1,232 +0,0 @@ -package org.gcube.documentstore.persistence; - -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -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.Map; - -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.scope.api.ScopeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HTTPCall { - - private static final Logger logger = LoggerFactory.getLogger(HTTPCall.class); - - public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json;charset=UTF-8"; - - public enum HTTPMETHOD { - HEAD, GET, POST, PUT, DELETE; - - @Override - public String toString() { - return this.name(); - } - } - - 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 final String address; - protected final String userAgent; - - public HTTPCall(String address, String userAgent) { - this.address = address; - this.userAgent = userAgent; - } - - protected String getParametersDataString(Map parameters) - throws UnsupportedEncodingException { - - if(parameters == null) { - return null; - } - - StringBuilder result = new StringBuilder(); - boolean first = true; - for(String key : parameters.keySet()) { - if(first) { - first = false; - } else { - result.append(PARAM_SEPARATOR); - } - result.append(URLEncoder.encode(key, UTF8)); - result.append(PARAM_EQUALS); - result.append(URLEncoder.encode(String.valueOf(parameters.get(key)), UTF8)); - } - - return result.toString(); - } - - protected URL getURL(String address, String path, String urlParameters) throws MalformedURLException { - - StringWriter stringWriter = new StringWriter(); - stringWriter.append(address); - - if(address.endsWith(PATH_SEPARATOR)) { - if(path.startsWith(PATH_SEPARATOR)) { - path = path.substring(1); - } - } else { - if(!path.startsWith(PATH_SEPARATOR)) { - stringWriter.append(PARAM_SEPARATOR); - } - } - - stringWriter.append(path); - - if(urlParameters != null) { - stringWriter.append(PARAM_STARTER); - stringWriter.append(urlParameters); - } - - return getURL(stringWriter.toString()); - } - - protected URL getURL(String urlString) throws MalformedURLException { - URL url = new URL(urlString); - if(url.getProtocol().compareTo("https") == 0) { - url = new URL(url.getProtocol(), url.getHost(), url.getDefaultPort(), url.getFile()); - } - return url; - } - - protected HttpURLConnection getConnection(String path, String urlParameters, HTTPMETHOD method, String body) - throws Exception { - URL url = getURL(address, path, urlParameters); - return getConnection(url, method, body); - } - - protected HttpURLConnection getConnection(URL url, HTTPMETHOD method, String body) throws Exception { - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - - if(SecurityTokenProvider.instance.get() == null) { - if(ScopeProvider.instance.get() == null) { - throw new RuntimeException("Null Token and Scope. Please set your token first."); - } - connection.setRequestProperty("gcube-scope", ScopeProvider.instance.get()); - } else { - connection.setRequestProperty(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY, - SecurityTokenProvider.instance.get()); - } - - connection.setDoOutput(true); - - connection.setRequestProperty("Content-type", APPLICATION_JSON_CHARSET_UTF_8); - connection.setRequestProperty("User-Agent", userAgent); - - connection.setRequestMethod(method.toString()); - - if(body != null && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) { - - DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); - wr.write(body.getBytes("UTF-8")); - wr.flush(); - wr.close(); - } - - int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); - logger.trace("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage); - - if(responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM - || responseCode == HttpURLConnection.HTTP_SEE_OTHER) { - - URL redirectURL = getURL(connection.getHeaderField("Location")); - - logger.trace("{} is going to be redirect to {}", url.toString(), redirectURL.toString()); - - connection = getConnection(redirectURL, method, body); - } - - return connection; - } - - protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException { - StringBuilder result = new StringBuilder(); - try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { - String line; - while((line = reader.readLine()) != null) { - result.append(line); - } - } - - return result; - } - - public C call(Class clz, String path, HTTPMETHOD method) throws Exception { - return call(clz, path, method, null, null); - } - - public C call(Class clz, String path, HTTPMETHOD method, Map parameters) - throws Exception { - return call(clz, path, method, parameters, null); - } - - public C call(Class clz, String path, HTTPMETHOD method, String body) throws Exception { - return call(clz, path, method, null, body); - } - - @SuppressWarnings("unchecked") - protected C call(Class clz, String path, HTTPMETHOD method, Map parameters, - String body) throws Exception { - - String urlParameters = getParametersDataString(parameters); - - HttpURLConnection connection = getConnection(path, urlParameters, method, body); - - try { - - int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); - logger.info("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage); - - if(method == HTTPMETHOD.HEAD) { - if(responseCode == HttpURLConnection.HTTP_NO_CONTENT) { - throw new Exception(responseMessage); - } - if(responseCode == HttpURLConnection.HTTP_NOT_FOUND) { - throw new Exception(responseMessage); - } - if(responseCode == HttpURLConnection.HTTP_FORBIDDEN) { - throw new Exception(responseMessage); - } - } - - if(responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) { - - InputStream inputStream = connection.getErrorStream(); - StringBuilder result = getStringBuilder(inputStream); - - String res = result.toString(); - - throw new Exception(res); - - } - - StringBuilder result = getStringBuilder(connection.getInputStream()); - - String res = result.toString(); - if(res != null && res.compareTo("")!=0) { - logger.trace("Server returned content : {}", res); - } - - return (C) res; - } finally { - connection.disconnect(); - } - } - -} diff --git a/src/main/java/org/gcube/documentstore/persistence/PersistenceAccountingService.java b/src/main/java/org/gcube/documentstore/persistence/PersistenceAccountingService.java index 35dafc8..c8f38d8 100644 --- a/src/main/java/org/gcube/documentstore/persistence/PersistenceAccountingService.java +++ b/src/main/java/org/gcube/documentstore/persistence/PersistenceAccountingService.java @@ -1,11 +1,19 @@ package org.gcube.documentstore.persistence; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Random; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.common.gxhttp.reference.GXConnection.HTTPMETHOD; +import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.documentstore.persistence.HTTPCall.HTTPMETHOD; import org.gcube.documentstore.records.DSMapper; import org.gcube.documentstore.records.Record; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; @@ -13,6 +21,10 @@ import org.gcube.resources.discovery.icclient.ICFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jakarta.ws.rs.ForbiddenException; +import jakarta.ws.rs.NotFoundException; +import jakarta.ws.rs.WebApplicationException; + /** * @author Alessandro Pieve (ISTI - CNR) alessandro.pieve@isti.cnr.it * @author Luca Frosini (ISTI - CNR) luca.frosini@isti.cnr.it @@ -23,6 +35,8 @@ public class PersistenceAccountingService extends PersistenceBackend { public static final String PATH_SERVICE_INSERT_ACCOUNTING = "/record"; + public static final String APPLICATION_JSON_CHARSET_UTF_8 = "application/json;charset=UTF-8"; + public static final String URL_PROPERTY_KEY = "URL"; public static final String SERVICE_CLASS = "Accounting"; @@ -32,8 +46,8 @@ public class PersistenceAccountingService extends PersistenceBackend { private static final String USER_AGENT = "document-store-lib-accounting-service"; private static String FORCED_URL; - - private HTTPCall httpCall; + + protected String url; private static String classFormat = "$resource/Profile/ServiceClass/text() eq '%1s'"; private static String nameFormat = "$resource/Profile/ServiceName/text() eq '%1s'"; @@ -57,7 +71,6 @@ public class PersistenceAccountingService extends PersistenceBackend { */ @Override protected void prepareConnection(PersistenceBackendConfiguration configuration) throws Exception { - String url = null; if(FORCED_URL!=null) { url = FORCED_URL; } else { @@ -73,22 +86,72 @@ public class PersistenceAccountingService extends PersistenceBackend { } Random random = new Random(); int index = random.nextInt(addresses.size()); - url = addresses.get(index); } } - logger.debug("Accounting Service URL to be contacted is {}", url); - httpCall = new HTTPCall(url, USER_AGENT); } + protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException { + StringBuilder result = new StringBuilder(); + try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String line; + while((line = reader.readLine()) != null) { + result.append(line); + } + } + return result; + } + + protected String parseHttpURLConnection(HttpURLConnection connection) throws WebApplicationException { + try { + int responseCode = connection.getResponseCode(); + // String responseMessage = connection.getResponseMessage(); + + if(connection.getRequestMethod().compareTo(HTTPMETHOD.HEAD.toString()) == 0) { + if(responseCode == HttpURLConnection.HTTP_NO_CONTENT) { + return null; + } + if(responseCode == HttpURLConnection.HTTP_NOT_FOUND) { + throw new NotFoundException(); + } + if(responseCode == HttpURLConnection.HTTP_FORBIDDEN) { + throw new ForbiddenException(); + } + } + + if(responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) { + InputStream inputStream = connection.getErrorStream(); + StringBuilder result = getStringBuilder(inputStream); + String res = result.toString(); + throw new WebApplicationException(res, responseCode); + } + + StringBuilder result = getStringBuilder(connection.getInputStream()); + return result.toString(); + } catch (WebApplicationException e) { + throw e; + } catch (Exception e) { + throw new WebApplicationException(e); + } finally { + connection.disconnect(); + } + } + protected void send(Record... records) throws Exception { List list = Arrays.asList(records); String body = DSMapper.marshal(list); logger.trace("Going to persist {}s {}", Record.class.getSimpleName(), body); - httpCall.call(String.class, PATH_SERVICE_INSERT_ACCOUNTING, HTTPMETHOD.POST, body); + + GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(url); + gxhttpStringRequest.path(PATH_SERVICE_INSERT_ACCOUNTING); + gxhttpStringRequest.header("Content-Type", APPLICATION_JSON_CHARSET_UTF_8); + gxhttpStringRequest.from(USER_AGENT); + gxhttpStringRequest.withBody(body); + HttpURLConnection httpURLConnection = gxhttpStringRequest.post(); + parseHttpURLConnection(httpURLConnection); } /**