From 89c3f1f43553a1334b425edc65ac5a4d595dd49e Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 27 Mar 2024 11:47:46 +0100 Subject: [PATCH 01/83] new feature #27135 --- .settings/org.eclipse.wst.common.component | 45 ++++++++++++++++---- CHANGELOG.md | 4 ++ pom.xml | 4 +- src/test/java/gis/RuntimeResourceReader.java | 39 +++++++++++------ 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 18a79e2..a2bcb05 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,8 @@ - + + + + @@ -16,7 +19,10 @@ - + + + + @@ -33,7 +39,10 @@ - + + + + @@ -50,7 +59,10 @@ - + + + + @@ -67,7 +79,10 @@ - + + + + @@ -84,7 +99,10 @@ - + + + + @@ -101,7 +119,10 @@ - + + + + @@ -118,7 +139,10 @@ - + + + + @@ -135,7 +159,10 @@ - + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a117b..ddbad01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v2.10.0-SNAPSHOT] + +- GeoPortal-Resolver enhancement: share link towards Geoportal Data-Entry facility implemented [#27135] + ## [v2.9.0] - GeoPortal-Resolver implemented [#24792] diff --git a/pom.xml b/pom.xml index 374ecd4..3546e52 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,11 @@ maven-parent org.gcube.tools - 1.1.0 + 1.2.0 org.gcube.data.transfer uri-resolver - 2.9.0 + 2.10.0-SNAPSHOT war The URI Resolver is an HTTP URI resolver implemented as a REST service which gives access trough HTTP to different gcube Resolvers and gCube Applications. diff --git a/src/test/java/gis/RuntimeResourceReader.java b/src/test/java/gis/RuntimeResourceReader.java index 7896431..1c74c72 100644 --- a/src/test/java/gis/RuntimeResourceReader.java +++ b/src/test/java/gis/RuntimeResourceReader.java @@ -95,8 +95,6 @@ public class RuntimeResourceReader { System.err.println("Error on reading Access point not found"); } - System.out.println("sono qui"); - seb.setListAP(listAp); listSE.add(seb); } @@ -127,13 +125,31 @@ public class RuntimeResourceReader { */ public static void main(String[] args) { - String scope = "/gcube/devsec/devVRE"; - //String platformName = "GeoServer"; - - String platformName = "postgis"; - String category = "Database"; +// String scope = "/pred4s/preprod/preVRE"; +// String scope = "/d4science.research-infrastructures.eu/D4OS/GNA"; +// String scope = "/gcube/devsec/devVRE"; + String scope = "/d4science.research-infrastructures.eu/gCubeApps/Esquiline"; - //scope = "/pred4s/preprod/preVRE"; + // String platformName = "geonetwork"; +// String category = "Gis"; + + String platformName = "GeoServer"; + String category = "Gis"; + +// String platformName = "postgis"; +// String category = "Database"; + +// String platformName = "postgresql"; +// String category = "Database"; + +// String platformName = "mongodb"; +// String category = "Database"; + + // scope = "/pred4s/preprod/preVRE"; + +// scope = "/d4science.research-infrastructures.eu/D4OS/Blue-Cloud2026Project"; +// platformName = "Zenodo"; +// category = "Repository"; RuntimeResourceReader reader; try { @@ -148,14 +164,13 @@ public class RuntimeResourceReader { for (AccessPoint ap : listAp) { System.out.println("username: " + ap.username()); System.out.println("password: " + ap.password()); - try{ + try { String decryptedPassword = StringEncrypter.getEncrypter().decrypt(ap.password()); - System.out.println("Decrypted Password: "+decryptedPassword); - }catch(Exception e){ + System.out.println("Decrypted Password: " + decryptedPassword); + } catch (Exception e) { System.out.println("ignoring exception during pwd decrypting"); } - } } From 3edd9b81de6c3b5852602553cde0ab34fba4bdc8 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 3 Apr 2024 15:58:43 +0200 Subject: [PATCH 02/83] Implmented share link towards Geoportal Data-Entry facility [#27135] --- .settings/org.eclipse.wst.common.component | 29 ++++-- .../geoportal/GeoportalCommonConstants.java | 4 +- ...=> GeoportalConfigApplicationProfile.java} | 19 ++-- ...portalConfigApplicationProfileReader.java} | 45 +++++---- .../resolver/services/GeoportalResolver.java | 91 +++++++++---------- 5 files changed, 104 insertions(+), 84 deletions(-) rename src/main/java/org/gcube/datatransfer/resolver/geoportal/{GeoportalDataViewerConfigProfile.java => GeoportalConfigApplicationProfile.java} (77%) rename src/main/java/org/gcube/datatransfer/resolver/geoportal/{GeoportalDataViewerConfigProfileReader.java => GeoportalConfigApplicationProfileReader.java} (77%) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index a2bcb05..1813fec 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,5 @@ - + @@ -18,8 +18,10 @@ - - + + + + @@ -39,7 +41,8 @@ - + + @@ -59,7 +62,8 @@ - + + @@ -79,7 +83,8 @@ - + + @@ -99,7 +104,8 @@ - + + @@ -119,7 +125,8 @@ - + + @@ -139,7 +146,8 @@ - + + @@ -159,7 +167,8 @@ - + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalCommonConstants.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalCommonConstants.java index b2ff4d5..5ebabce 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalCommonConstants.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalCommonConstants.java @@ -12,6 +12,8 @@ public class GeoportalCommonConstants { public static final String GET_GEONA_ITEM_TYPE = "git"; public static final String GET_GEONA_ITEM_ID = "gid"; - public static final String GEOPORTAL_DATA_VIEWER_APP = "geoportal-data-viewer-app"; + public static final String GEOPORTAL_DATA_VIEWER_APP_ID = "geoportal-data-viewer-app"; + + public static final String GEOPORTAL_DATA_ENTRY_APP_ID = "geoportal-data-entry-app"; } diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfile.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfile.java similarity index 77% rename from src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfile.java rename to src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfile.java index b3c0c73..7496439 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfile.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfile.java @@ -3,25 +3,25 @@ package org.gcube.datatransfer.resolver.geoportal; import java.io.Serializable; /** - * The Class GeoportalDataViewerConfigProfile. + * The Class GeoportalConfigApplicationProfile. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * - * Dec 21, 2021 + * Apr 3, 2024 */ -public class GeoportalDataViewerConfigProfile implements Serializable { +public class GeoportalConfigApplicationProfile implements Serializable { /** * */ - private static final long serialVersionUID = 2968334957258327191L; + private static final long serialVersionUID = 8340275391003882511L; private String restrictedPortletURL; private String openPortletURL; /** * Instantiates a new geo na data viewer profile. */ - public GeoportalDataViewerConfigProfile() { + public GeoportalConfigApplicationProfile() { } @@ -61,15 +61,20 @@ public class GeoportalDataViewerConfigProfile implements Serializable { this.openPortletURL = openPortletURL; } + /** + * To string. + * + * @return the string + */ @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("GeoportalDataViewerConfigProfile [restrictedPortletURL="); + builder.append("GeoportalConfigApplicationProfile [restrictedPortletURL="); builder.append(restrictedPortletURL); builder.append(", openPortletURL="); builder.append(openPortletURL); builder.append("]"); return builder.toString(); } - + } diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfileReader.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfileReader.java similarity index 77% rename from src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfileReader.java rename to src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfileReader.java index 5b8fb8b..5642fa9 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalDataViewerConfigProfileReader.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalConfigApplicationProfileReader.java @@ -20,36 +20,35 @@ import org.w3c.dom.Document; import org.xml.sax.InputSource; /** - * The Class GeoportalDataViewerConfigProfileReader. + * The Class GeoportalConfigApplicationProfileReader. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * - * Mar 23, 2023 + * Apr 3, 2024 */ -public class GeoportalDataViewerConfigProfileReader { +public class GeoportalConfigApplicationProfileReader { + private static Logger LOG = LoggerFactory.getLogger(GeoportalConfigApplicationProfileReader.class); private static final String RESOURCE_PROFILE_BODY = "/Resource/Profile/Body"; public static final String SECONDARY_TYPE = "ApplicationProfile"; - public static final String GENERIC_RESOURCE_NAME = "Geoportal-DataViewer-Configs"; - private static Logger LOG = LoggerFactory.getLogger(GeoportalDataViewerConfigProfileReader.class); private String secondaryType; private String scope; private String appID; - private GeoportalDataViewerConfigProfile geoportalDataViewerConfigProfile; + private GeoportalConfigApplicationProfile geoportalConfigAppProfile; /** - * Instantiates a new geoportal data viewer config profile reader. + * Instantiates a new geoportal config application profile reader. * * @param appID the app ID * @throws Exception the exception */ - public GeoportalDataViewerConfigProfileReader(String appID) throws Exception { + public GeoportalConfigApplicationProfileReader(String appID) throws Exception { this.appID = appID; this.secondaryType = SECONDARY_TYPE; this.scope = ScopeProvider.instance.get(); - this.geoportalDataViewerConfigProfile = readProfileFromInfrastructure(); + this.geoportalConfigAppProfile = readProfileFromInfrastructure(); } /** @@ -58,7 +57,7 @@ public class GeoportalDataViewerConfigProfileReader { * @return the map * @throws Exception the exception */ - private GeoportalDataViewerConfigProfile readProfileFromInfrastructure() throws Exception { + private GeoportalConfigApplicationProfile readProfileFromInfrastructure() throws Exception { String queryString = getGcubeGenericQueryString(secondaryType, appID); LOG.info("Scope " + scope + ", trying to perform query: " + queryString); @@ -68,7 +67,7 @@ public class GeoportalDataViewerConfigProfileReader { if (scope == null) throw new Exception("Scope is null, set scope into ScopeProvider"); - GeoportalDataViewerConfigProfile profile = new GeoportalDataViewerConfigProfile(); + GeoportalConfigApplicationProfile profile = new GeoportalConfigApplicationProfile(); LOG.info("Trying to fetch ApplicationProfile in the scope: " + scope + ", SecondaryType: " + secondaryType + ", AppId: " + appID); @@ -107,8 +106,8 @@ public class GeoportalDataViewerConfigProfileReader { } } catch (Exception e) { - LOG.error("Error while trying to read the " + SECONDARY_TYPE + " with SecondaryType " - + GENERIC_RESOURCE_NAME + " from scope " + scope, e); + LOG.error("Error while trying to read the SecondaryType " + SECONDARY_TYPE + " with appID " + appID + + " from scope " + scope, e); return null; } finally { @@ -116,8 +115,13 @@ public class GeoportalDataViewerConfigProfileReader { } - public GeoportalDataViewerConfigProfile getGeoportalDataViewerConfigProfile() { - return geoportalDataViewerConfigProfile; + /** + * Gets the geoportal config app profile. + * + * @return the geoportal config app profile + */ + public GeoportalConfigApplicationProfile getGeoportalConfigAppProfile() { + return geoportalConfigAppProfile; } /** @@ -152,17 +156,22 @@ public class GeoportalDataViewerConfigProfileReader { return scope; } + /** + * To string. + * + * @return the string + */ @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("GeoportalDataViewerConfigProfileReader [secondaryType="); + builder.append("GeoportalConfigApplicationProfileReader [secondaryType="); builder.append(secondaryType); builder.append(", scope="); builder.append(scope); builder.append(", appID="); builder.append(appID); - builder.append(", geoportalDataViewerConfigProfile="); - builder.append(geoportalDataViewerConfigProfile); + builder.append(", geoportalConfigAppProfile="); + builder.append(geoportalConfigAppProfile); builder.append("]"); return builder.toString(); } diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index eab1704..af12ab3 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -24,8 +24,8 @@ import org.gcube.common.scope.impl.ScopeBean; import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.caches.LoadingMapOfScopeCache; import org.gcube.datatransfer.resolver.geoportal.GeoportalCommonConstants; -import org.gcube.datatransfer.resolver.geoportal.GeoportalDataViewerConfigProfile; -import org.gcube.datatransfer.resolver.geoportal.GeoportalDataViewerConfigProfileReader; +import org.gcube.datatransfer.resolver.geoportal.GeoportalConfigApplicationProfile; +import org.gcube.datatransfer.resolver.geoportal.GeoportalConfigApplicationProfileReader; import org.gcube.datatransfer.resolver.geoportal.GeoportalRequest; import org.gcube.datatransfer.resolver.geoportal.TargetAppGeoportalCodes; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; @@ -45,7 +45,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException; * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * - * Mar 23, 2023 + * Apr 03, 2024 */ @Path("/geo") public class GeoportalResolver { @@ -141,8 +141,7 @@ public class GeoportalResolver { public Response resolveDataViewerLink(@Context HttpServletRequest req, @QueryParam(GeoportalRequest.P_GCUBE_SCOPE) String gcubeScope, @QueryParam(GeoportalRequest.P_ITEM_ID) String itemId, - @QueryParam(GeoportalRequest.P_ITEM_TYPE) String itemType, - @QueryParam(QP_RESOLVE_AS) String resolveAs) + @QueryParam(GeoportalRequest.P_ITEM_TYPE) String itemType, @QueryParam(QP_RESOLVE_AS) String resolveAs) throws WebApplicationException { LOG.info(this.getClass().getSimpleName() + " resolveDataViewerLink - GET starts..."); @@ -321,21 +320,35 @@ public class GeoportalResolver { LOG.info("Found RESOLVE_AS_PARAMETER: " + resolveAs); String originalScope = ScopeProvider.instance.get(); - GeoportalDataViewerConfigProfileReader reader; + GeoportalConfigApplicationProfileReader reader; + String itemLink = null; + String appID = null; + + // Resolving towards Data-Viewer or Data-Entry Application + switch (resoruceGeoportalCodes) { + case GEO_DE: { + appID = org.gcube.datatransfer.resolver.geoportal.GeoportalCommonConstants.GEOPORTAL_DATA_ENTRY_APP_ID; + break; + } + case GEO_DV: + default: { + appID = org.gcube.datatransfer.resolver.geoportal.GeoportalCommonConstants.GEOPORTAL_DATA_VIEWER_APP_ID; + break; + } + } + try { String theScope = fullScopeBean.toString(); LOG.info("Full scope is: " + theScope); ScopeProvider.instance.set(theScope); - reader = new GeoportalDataViewerConfigProfileReader( - org.gcube.datatransfer.resolver.geoportal.GeoportalCommonConstants.GEOPORTAL_DATA_VIEWER_APP); + reader = new GeoportalConfigApplicationProfileReader(appID); } catch (Exception e) { - LOG.error("Error on reading the " + GeoportalDataViewerConfigProfileReader.SECONDARY_TYPE - + " with generic resource name: " - + GeoportalDataViewerConfigProfileReader.GENERIC_RESOURCE_NAME, e); - throw ExceptionManager.internalErrorException(req, - "Error on reading the " + GeoportalDataViewerConfigProfileReader.SECONDARY_TYPE + " for name " - + GeoportalDataViewerConfigProfileReader.GENERIC_RESOURCE_NAME - + ". Please contact the support", + String error = "Error on reading the generic resource with SecondaryType: " + + GeoportalConfigApplicationProfileReader.SECONDARY_TYPE + " and APP ID: " + appID + + " in the scope: " + appID; + LOG.error(error, e); + + throw ExceptionManager.internalErrorException(req, error + ". Please contact the support", this.getClass(), helpURI); } finally { if (originalScope != null && !originalScope.isEmpty()) { @@ -347,51 +360,33 @@ public class GeoportalResolver { } } - // Resolving towards Data-Viewer or Data-Entry Application - String itemLink = null; + GeoportalConfigApplicationProfile geonaDataProfile = reader.getGeoportalConfigAppProfile(); - switch (resoruceGeoportalCodes) { - case GEO_DV: { + switch (resolveTO) { + case PUBLIC: { + // Open Link + itemLink = String.format("%s?%s=%s&%s=%s", geonaDataProfile.getOpenPortletURL(), + GeoportalCommonConstants.GET_GEONA_ITEM_ID, projectID, + GeoportalCommonConstants.GET_GEONA_ITEM_TYPE, ucdID); + break; + } + case PRIVATE: { - GeoportalDataViewerConfigProfile geonaDataProfile = reader.getGeoportalDataViewerConfigProfile(); - - switch (resolveTO) { - case PUBLIC: - // Open Link - itemLink = String.format("%s?%s=%s&%s=%s", geonaDataProfile.getOpenPortletURL(), - GeoportalCommonConstants.GET_GEONA_ITEM_ID, projectID, - GeoportalCommonConstants.GET_GEONA_ITEM_TYPE, ucdID); - break; - case PRIVATE: - - // Restricted Link - itemLink = String.format("%s?%s=%s&%s=%s", geonaDataProfile.getRestrictedPortletURL(), - GeoportalCommonConstants.GET_GEONA_ITEM_ID, projectID, - GeoportalCommonConstants.GET_GEONA_ITEM_TYPE, ucdID); - - break; - - default: - break; - } + // Restricted Link + itemLink = String.format("%s?%s=%s&%s=%s", geonaDataProfile.getRestrictedPortletURL(), + GeoportalCommonConstants.GET_GEONA_ITEM_ID, projectID, + GeoportalCommonConstants.GET_GEONA_ITEM_TYPE, ucdID); break; } - case GEO_DE: { - - LOG.error("The Resolver towards '" + resoruceGeoportalCodes + "' not implemented yet"); - throw ExceptionManager.internalErrorException(req, - "The Resolver towards '" + resoruceGeoportalCodes + "' not implemented yet", this.getClass(), - helpURI); - - } default: break; } LOG.info("Returning link: " + itemLink); return Response.seeOther(new URL(itemLink).toURI()).build(); + } catch (Exception e) { if (!(e instanceof WebApplicationException)) { From 29fd3428c56ff8a968c58f824ee5172f476fd53c Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 4 Apr 2024 10:42:56 +0200 Subject: [PATCH 03/83] updated bad request message --- .settings/org.eclipse.wst.common.component | 30 +++++++++++++------ .../resolver/services/GeoportalResolver.java | 4 ++- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 1813fec..3d2a413 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -20,7 +21,8 @@ - + + @@ -41,7 +43,8 @@ - + + @@ -62,7 +65,8 @@ - + + @@ -83,7 +87,8 @@ - + + @@ -104,7 +109,11 @@ - + + uses + + + @@ -125,7 +134,8 @@ - + + @@ -146,7 +156,8 @@ - + + @@ -167,7 +178,8 @@ - + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index af12ab3..9923634 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -230,8 +230,10 @@ public class GeoportalResolver { LOG.error("Target application parameter is malformed"); List targetApps = Arrays.asList(TargetAppGeoportalCodes.values()).stream() .map(TargetAppGeoportalCodes::getTarget_app).collect(Collectors.toList()); + List targetPaths = Arrays.asList(TargetAppGeoportalCodes.values()).stream() + .map(TargetAppGeoportalCodes::getId).collect(Collectors.toList()); throw ExceptionManager.badRequestException(req, - "Target application is wrong. It must be one value of: " + targetApps, this.getClass(), + "Target application is wrong. Add a target path as /"+targetPaths+"+ values of the applications: " + targetApps, this.getClass(), helpURI); } } From 88201bf6173cecd12200f6cb6b4e64e12d041f4e Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 4 Apr 2024 16:36:53 +0200 Subject: [PATCH 04/83] Updated bad request message --- .../resolver/services/GeoportalResolver.java | 2 +- src/test/java/gis/RuntimeResourceReader.java | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index 9923634..fa069d4 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -233,7 +233,7 @@ public class GeoportalResolver { List targetPaths = Arrays.asList(TargetAppGeoportalCodes.values()).stream() .map(TargetAppGeoportalCodes::getId).collect(Collectors.toList()); throw ExceptionManager.badRequestException(req, - "Target application is wrong. Add a target path as /"+targetPaths+"+ values of the applications: " + targetApps, this.getClass(), + "Target application is wrong. Add a target path as /"+targetPaths+"+ to resolve towards the applications: " + targetApps, this.getClass(), helpURI); } } diff --git a/src/test/java/gis/RuntimeResourceReader.java b/src/test/java/gis/RuntimeResourceReader.java index 1c74c72..12cf884 100644 --- a/src/test/java/gis/RuntimeResourceReader.java +++ b/src/test/java/gis/RuntimeResourceReader.java @@ -128,14 +128,15 @@ public class RuntimeResourceReader { // String scope = "/pred4s/preprod/preVRE"; // String scope = "/d4science.research-infrastructures.eu/D4OS/GNA"; // String scope = "/gcube/devsec/devVRE"; - String scope = "/d4science.research-infrastructures.eu/gCubeApps/Esquiline"; + //String scope = "/d4science.research-infrastructures.eu/gCubeApps/Esquiline"; + String scope = "/d4science.research-infrastructures.eu/D4OS/ARIADNEplus_Project"; - // String platformName = "geonetwork"; -// String category = "Gis"; - - String platformName = "GeoServer"; + String platformName = "geonetwork"; String category = "Gis"; +// String platformName = "GeoServer"; +// String category = "Gis"; + // String platformName = "postgis"; // String category = "Database"; From 1d5d8bb43824ccd14008cb60b3a8f65ac45cdeb5 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 4 Apr 2024 16:45:41 +0200 Subject: [PATCH 05/83] fixed bad request message error --- .../gcube/datatransfer/resolver/services/GeoportalResolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index fa069d4..4548385 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -233,7 +233,7 @@ public class GeoportalResolver { List targetPaths = Arrays.asList(TargetAppGeoportalCodes.values()).stream() .map(TargetAppGeoportalCodes::getId).collect(Collectors.toList()); throw ExceptionManager.badRequestException(req, - "Target application is wrong. Add a target path as /"+targetPaths+"+ to resolve towards the applications: " + targetApps, this.getClass(), + "Target application is wrong. Add a target path as /"+targetPaths+" to resolve towards the applications: " + targetApps, this.getClass(), helpURI); } } From a63f3bbfaf1e89f0c651bd9d2669ad3aa420ad80 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 4 Apr 2024 17:07:16 +0200 Subject: [PATCH 06/83] updated GeoportalRequest bean --- .../datatransfer/resolver/geoportal/GeoportalRequest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalRequest.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalRequest.java index 3bf4206..ed91528 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalRequest.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/GeoportalRequest.java @@ -1,5 +1,6 @@ package org.gcube.datatransfer.resolver.geoportal; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @@ -15,11 +16,13 @@ import lombok.extern.slf4j.Slf4j; */ @Slf4j @Data +@JsonIgnoreProperties(ignoreUnknown = true) public class GeoportalRequest { public static final String P_GCUBE_SCOPE = "gcube_scope"; public static final String P_ITEM_TYPE = "item_type"; public static final String P_ITEM_ID = "item_id"; + public static final String P_RESOLVES_AS = "res"; public static final String P_QUERY_STRING = "query_string"; @JsonProperty(P_GCUBE_SCOPE) @@ -34,7 +37,11 @@ public class GeoportalRequest { */ @JsonProperty(P_ITEM_ID) private String itemID; + @JsonProperty(P_QUERY_STRING) private String queryString; + + @JsonProperty(P_RESOLVES_AS) + private String res; } From 62fd269a86c45bc2d7db313d52ac515dbb76158f Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 18 Apr 2024 17:03:16 +0200 Subject: [PATCH 07/83] - Implementing Geoportal Exporter as PDF [#26026] --- .settings/org.eclipse.wst.common.component | 62 ++++- CHANGELOG.md | 3 +- pom.xml | 30 ++- .../resolver/services/GeoportalExporter.java | 248 ++++++++++++++++++ .../resolver/services/GeoportalResolver.java | 12 +- src/main/webapp/WEB-INF/gcube-app.xml | 1 + src/main/webapp/img/loading-gears.gif | Bin 0 -> 56511 bytes src/test/java/gis/SE_Harvester_from_IS.java | 2 - 8 files changed, 336 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java create mode 100644 src/main/webapp/img/loading-gears.gif diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 3d2a413..f98fdce 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,9 @@ - + + + + + @@ -21,7 +25,11 @@ - + + + + + @@ -43,7 +51,11 @@ - + + + + + @@ -65,7 +77,11 @@ - + + + + + @@ -87,7 +103,11 @@ - + + + + + @@ -109,10 +129,20 @@ - + uses - + + uses + + + uses + + + + + + @@ -134,7 +164,11 @@ - + + + + + @@ -156,7 +190,11 @@ - + + + + + @@ -178,7 +216,11 @@ - + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index ddbad01..60c2135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v2.10.0-SNAPSHOT] -- GeoPortal-Resolver enhancement: share link towards Geoportal Data-Entry facility implemented [#27135] +- GeoPortal-Resolver enhancement: implemented share link towards Geoportal Data-Entry facility [#27135] +- Added Geoportal Exporter as PDF [#26026] ## [v2.9.0] diff --git a/pom.xml b/pom.xml index 3546e52..b86f958 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ org.gcube.distribution gcube-smartgears-bom - 2.4.0 + 2.5.0 pom import @@ -76,7 +76,7 @@ org.gcube.data-publishing storagehub-application-persistence - [1.0.0, 2.0.0-SNAPSHOT) + [1.0.0, 3.0.0-SNAPSHOT) org.gcube.common @@ -98,6 +98,12 @@ [1.0.0,2.0.0-SNAPSHOT) + + org.gcube.common + authorization-utils + [2.0.0, 3.0.0-SNAPSHOT) + + com.google.guava guava @@ -123,7 +129,6 @@ org.gcube.common storagehub-client-library - [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) @@ -250,6 +255,25 @@ + + org.gcube.application + geoportal-data-mapper + [1.0.0, 2.0.0-SNAPSHOT) + + + + org.gcube.contentmanagement + storage-manager-wrapper + + + org.gcube.contentmanagement + storage-manager-core + + + compile + + org.slf4j slf4j-api diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java new file mode 100644 index 0000000..9061f43 --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -0,0 +1,248 @@ +package org.gcube.datatransfer.resolver.services; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.gcube.application.geoportaldatamapper.exporter.Geoportal_PDF_Exporter; +import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource; +import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.datatransfer.resolver.ConstantsResolver; +import org.gcube.datatransfer.resolver.geoportal.TargetAppGeoportalCodes; +import org.gcube.datatransfer.resolver.services.GeoportalResolver.RESOLVE_AS; +import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class GeoportalExporter. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 16, 2024 + */ +@Path("/geoportal") +public class GeoportalExporter { + + public static final String EXPORT_TYPE = "type"; + + public static final String PATH_PROJECT_ID = GeoportalResolver.PATH_PROJECT_ID; + public static final String PATH_USECASE_ID = GeoportalResolver.PATH_USECASE_ID; + public static final String PATH_VRE_NAME = GeoportalResolver.PATH_VRE_NAME; + + private static final Logger LOG = LoggerFactory.getLogger(GeoportalExporter.class); + private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#Geoportal_Resolver"; + + public enum ACCEPTED_EXPORT_TYPE { + pdf + } + + /** + * Resolve geoportal no app def. + * + * @param req the req + * @param vreName the vre name + * @param exportType the export type + * @param ucdID the ucd ID + * @param projectID the project ID + * @return the response + * @throws WebApplicationException the web application exception + */ + @GET + @Path("/export/{type}/{usecase_id}/{project_id}") + public Response export(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, + @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) + throws WebApplicationException { + + LOG.info(this.getClass().getSimpleName() + " export - GET starts..."); + LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID); + + checkPathParameterNotNull(req, EXPORT_TYPE, export_type); + checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID); + checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID); + + ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type); + + try { + + SecretManager cm = SecretManagerProvider.instance.get(); + String context = cm.getContext(); + if (context == null) { + throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), + helpURI); + } + org.gcube.common.authorization.utils.user.User user = cm.getUser(); + LOG.info("Identified caller {} in context {}", user.getUsername(), context); + + Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); + boolean checked = pdfExporter.checkConfig(); + + if (!checked) + return Response.status(Status.NOT_FOUND).build(); + + ExporterProjectSource exporterSource = new ExporterProjectSource(); + RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC; + // #NB SET USERNAME = null to export with PUBLIC ACCESS + if (!cm.getUser().isApplication()) { + // here the token is of an user + resolveAs = RESOLVE_AS.PRIVATE; + exporterSource.setAccountname(user.getUsername()); + } + + exporterSource.setScope(context); + exporterSource.setProjectID(projectID); + exporterSource.setProfileID(ucdID); + + String vreName = context.substring(context.lastIndexOf("/") + 1, context.length()); + LOG.info("Requesting gis link to vre {}", vreName); + Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req, + TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name()); + String theGisLink = theReponseWithLink.getEntity().toString(); + LOG.info("Gis link returned {}", theGisLink); + exporterSource.setGisLink(theGisLink); + + if (checked) { + String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); + return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") + .build(); + } else { + return Response.status(Status.NOT_FOUND).entity(GeoportalExporter.class.getSimpleName() + " Config KO") + .type(MediaType.TEXT_PLAIN).build(); + } + + } catch (Exception e) { + LOG.error("Error on performing healthcheck", e); + throw ExceptionManager.internalErrorException(req, + "Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck", + this.getClass(), helpURI); + } + + } + + @GET + @Path("/export/{type}/healthcheck") + public Response healthcheck(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type) + throws WebApplicationException { + + LOG.info(this.getClass().getSimpleName() + " healthcheck - GET starts..."); + LOG.debug("param is: exportType: {}", export_type); + + checkPathParameterNotNull(req, EXPORT_TYPE, export_type); + + ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type); + + try { + + SecretManager cm = SecretManagerProvider.instance.get(); + String context = cm.getContext(); + if (context == null) { + throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), + helpURI); + } + org.gcube.common.authorization.utils.user.User user = cm.getUser(); + LOG.info("Identified caller {} in context {}", user.getUsername(), context); + +// Set roles = new HashSet<>(); +// roles.addAll(user.getRoles()); + + Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); + boolean checked = pdfExporter.checkConfig(); + + if (checked) { + return Response.ok(GeoportalExporter.class.getSimpleName() + " Config OK").build(); + } else { + return Response.status(Status.NOT_FOUND).entity(GeoportalExporter.class.getSimpleName() + " Config KO") + .type(MediaType.TEXT_PLAIN).build(); + } + + } catch (Exception e) { + LOG.error("Error on performing healthcheck", e); + throw ExceptionManager.internalErrorException(req, + "Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck", + this.getClass(), helpURI); + } + } + + public void checkPathParameterNotNull(HttpServletRequest req, String parameter, String value) + throws BadRequestException { + if (value == null || value.isEmpty()) { + LOG.error("The path parameter {} not found or empty in the path", parameter); + throw ExceptionManager.badRequestException(req, + "Mandatory path parameter " + parameter + " not found or empty", this.getClass(), helpURI); + } + } + + public ACCEPTED_EXPORT_TYPE toKnowExportType(HttpServletRequest req, String export_type) + throws BadRequestException { + ACCEPTED_EXPORT_TYPE exportType; + try { + exportType = ACCEPTED_EXPORT_TYPE.valueOf(export_type); + } catch (Exception e) { + throw ExceptionManager + .wrongParameterException(req, + "The path parameter " + EXPORT_TYPE + " has a bad value: " + export_type + + ". It must be value of " + ACCEPTED_EXPORT_TYPE.values(), + this.getClass(), helpURI); + } + + return exportType; + } + + /** + * Sets the HTML message. + * + * @param action the action + * @param message the message + * @param waiting the waiting + * @return the string + */ + protected String entityHTMLMessage(String action, String message, boolean waiting) { + + String html = "" + "" + "" + + "" + + "D4Science Geoportal - Action" + "" + ""; + + + html += "\"D4Science
"; + + html += "
"; + html += "

" + action + "

"; + + if (waiting) { + html += "\"D4Science
"; + } + + html += "

" + message + "

"; + html += "
"; + + return html; + } + +} diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index 4548385..e063e7b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -54,11 +54,11 @@ public class GeoportalResolver { public static final String GEO = "geo"; // geoportal public static final String GEO_DV = "dv"; // data-viewer - private static final String QP_RESOLVE_AS = "res"; - private static final String PATH_PROJECT_ID = "project_id"; - private static final String PATH_USECASE_ID = "usecase_id"; - private static final String PATH_VRE_NAME = "vre_name"; - private static final String PATH_TARGET_APP = "targetAppId"; + public static final String QP_RESOLVE_AS = "res"; + public static final String PATH_PROJECT_ID = "project_id"; + public static final String PATH_USECASE_ID = "usecase_id"; + public static final String PATH_VRE_NAME = "vre_name"; + public static final String PATH_TARGET_APP = "targetAppId"; private static final Logger LOG = LoggerFactory.getLogger(GeoportalResolver.class); private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#Geoportal_Resolver"; @@ -70,7 +70,7 @@ public class GeoportalResolver { * * Mar 24, 2023 */ - private static enum RESOLVE_AS { + public static enum RESOLVE_AS { PUBLIC, PRIVATE } diff --git a/src/main/webapp/WEB-INF/gcube-app.xml b/src/main/webapp/WEB-INF/gcube-app.xml index fe2bdfd..a8d3fb2 100644 --- a/src/main/webapp/WEB-INF/gcube-app.xml +++ b/src/main/webapp/WEB-INF/gcube-app.xml @@ -7,4 +7,5 @@ /knime/create/* /wekeo/gettoken/* /oat/get/* + /geoportal/export/* \ No newline at end of file diff --git a/src/main/webapp/img/loading-gears.gif b/src/main/webapp/img/loading-gears.gif new file mode 100644 index 0000000000000000000000000000000000000000..682a20da7d2cd154cb56cbc95a8618ab5a305ec5 GIT binary patch literal 56511 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 R*1$kUq4*UIAcB>&Uzqfuu*OB&a?V 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 Date: Thu, 18 Apr 2024 17:43:35 +0200 Subject: [PATCH 08/83] updated consumes --- .settings/org.eclipse.wst.common.component | 3 +++ .../datatransfer/resolver/services/GeoportalExporter.java | 5 ++++- .../datatransfer/resolver/services/GeoportalResolver.java | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index f98fdce..da8308c 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -129,6 +129,9 @@ + + uses + uses diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 9061f43..9641623 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; @@ -29,7 +30,7 @@ import org.slf4j.LoggerFactory; * * Apr 16, 2024 */ -@Path("/geoportal") +@Path("geoportal") public class GeoportalExporter { public static final String EXPORT_TYPE = "type"; @@ -58,6 +59,7 @@ public class GeoportalExporter { */ @GET @Path("/export/{type}/{usecase_id}/{project_id}") + @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) public Response export(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) throws WebApplicationException { @@ -129,6 +131,7 @@ public class GeoportalExporter { @GET @Path("/export/{type}/healthcheck") + @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) public Response healthcheck(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type) throws WebApplicationException { diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java index e063e7b..33d9dd0 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalResolver.java @@ -47,7 +47,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException; * * Apr 03, 2024 */ -@Path("/geo") +@Path("geo") public class GeoportalResolver { public static final String GEO_DE = "de"; // data-entry From 99cfe3976a723fa744fa31f1998e43430d4c0283 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 11:26:55 +0200 Subject: [PATCH 09/83] Implementing Geoportal_Exporter --- CHANGELOG.md | 2 +- .../requesthandler/RequestHandler.java | 266 +++++++++++------- .../resolver/services/GeoportalExporter.java | 194 ++++++++----- 3 files changed, 302 insertions(+), 160 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60c2135..437cf13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v2.10.0-SNAPSHOT] - GeoPortal-Resolver enhancement: implemented share link towards Geoportal Data-Entry facility [#27135] -- Added Geoportal Exporter as PDF [#26026] +- Added Geoportal Exporter as PDF [#27274] ## [v2.9.0] diff --git a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java index 98e3935..21715c1 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java +++ b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java @@ -19,20 +19,25 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.ext.Provider; +import org.gcube.common.authorization.library.provider.AccessTokenProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.authorization.utils.secret.GCubeSecret; +import org.gcube.common.authorization.utils.secret.JWTSecret; +import org.gcube.common.authorization.utils.secret.Secret; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.UriResolverServices; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * The Class RequestHandler. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * - * Mar 15, 2019 + * Mar 15, 2019 */ @Provider @PreMatching @@ -44,7 +49,8 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse private static final Logger log = LoggerFactory.getLogger(RequestHandler.class); - @Context ServletContext context; + @Context + ServletContext context; @Context HttpServletRequest webRequest; @@ -55,127 +61,195 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse @Context ResourceContext resourceContext; - /* (non-Javadoc) - * @see javax.ws.rs.container.ContainerRequestFilter#filter(javax.ws.rs.container.ContainerRequestContext) - */ - @Override - public void filter(ContainerRequestContext reqContext) throws IOException { - log.info(RequestHandler.class.getSimpleName() +" Request called"); - - if(SecurityTokenProvider.instance.get()==null) - SecurityTokenProvider.instance.set(context.getInitParameter(ROOT_APP_TOKEN)); + /** + * Filter. + * + * @param reqContext the req context + * @throws IOException Signals that an I/O exception has occurred. + */ + /* + * (non-Javadoc) + * + * @see + * javax.ws.rs.container.ContainerRequestFilter#filter(javax.ws.rs.container. + * ContainerRequestContext) + */ + @Override + public void filter(ContainerRequestContext reqContext) throws IOException { + log.info(RequestHandler.class.getSimpleName() + " Request called"); + setSecretManager(reqContext); - if(ScopeProvider.instance.get()==null) - ScopeProvider.instance.set(context.getInitParameter(ROOT_SCOPE)); - - log.info("Token and Scope Provider set called"); + if (SecurityTokenProvider.instance.get() == null) + SecurityTokenProvider.instance.set(context.getInitParameter(ROOT_APP_TOKEN)); + + if (ScopeProvider.instance.get() == null) + ScopeProvider.instance.set(context.getInitParameter(ROOT_SCOPE)); + + log.info("Token and Scope Provider set called"); List listOfPath = UriResolverServices.getInstance().getListOfResourcePath(application.getClasses()); - log.debug("The resources are: {}", listOfPath); + log.debug("The resources are: {}", listOfPath); - String path = reqContext.getUriInfo().getPath(); - log.debug("The path is: {}", path); - - //HOW TO READ THE QUERY STRING - /*MultivaluedMap queryParameters = reqContext.getUriInfo().getQueryParameters(); - String queryString = ""; - try { - queryString = Util.toQueryString(queryParameters); - }catch (Exception e) { - //silent - log.warn("Error on reading the query string, trying to continue..."); + String path = reqContext.getUriInfo().getPath(); + log.debug("The path is: {}", path); + + // HOW TO READ THE QUERY STRING + /* + * MultivaluedMap queryParameters = + * reqContext.getUriInfo().getQueryParameters(); String queryString = ""; try { + * queryString = Util.toQueryString(queryParameters); }catch (Exception e) { + * //silent + * log.warn("Error on reading the query string, trying to continue..."); } + * log.debug("The query string is: {}", queryString); + */ + + if (path == null || path.isEmpty()) { + log.debug("The path is null or empty, redirecting to /index"); + URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path("/index").build(); + reqContext.setRequestUri(newRequestURI); + return; } - log.debug("The query string is: {}", queryString); - */ - if(path==null || path.isEmpty()) { - log.debug("The path is null or empty, redirecting to /index"); - URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path("/index").build(); - reqContext.setRequestUri(newRequestURI); - return; - } - - String[] splittePath = null; - boolean resourceToRedirectFound = false; - String candidateResource = ""; - try { - splittePath = path.split("/"); - if(splittePath!=null && splittePath.length>0) { - String requestedResourceName = splittePath[0]; - log.debug("The resource requested is: {}",requestedResourceName); - - if(requestedResourceName!=null && !requestedResourceName.isEmpty()) { - for (String resource : listOfPath) { - log.trace("Is resource '{}' starting with '{}' ?",resource,requestedResourceName); - if(resource.startsWith(requestedResourceName)) { + String[] splittePath = null; + boolean resourceToRedirectFound = false; + String candidateResource = ""; + try { + splittePath = path.split("/"); + if (splittePath != null && splittePath.length > 0) { + String requestedResourceName = splittePath[0]; + log.debug("The resource requested is: {}", requestedResourceName); + + if (requestedResourceName != null && !requestedResourceName.isEmpty()) { + for (String resource : listOfPath) { + log.trace("Is resource '{}' starting with '{}' ?", resource, requestedResourceName); + if (resource.startsWith(requestedResourceName)) { log.trace("Yes it starts!"); candidateResource = requestedResourceName; - log.info("The candidate resource to manage the request is: {}",candidateResource); + log.info("The candidate resource to manage the request is: {}", candidateResource); resourceToRedirectFound = true; break; } } - - //Try to manage as Catalogue Request ctlg, ctlg-p, etc. - if(!resourceToRedirectFound) { - log.info("Trying to manage as hard-coded case among cases: {}", Arrays.asList(ConstantsResolver.resourcesHardCoded).toString()); - String[] hardCode = ConstantsResolver.resourcesHardCoded; - - for (String resource : hardCode) { - log.trace("Is requested resource '{}' starting with hard-coded resource '{}'?",requestedResourceName,resource); - if(requestedResourceName.startsWith(resource)) { + + // Try to manage as Catalogue Request ctlg, ctlg-p, etc. + if (!resourceToRedirectFound) { + log.info("Trying to manage as hard-coded case among cases: {}", + Arrays.asList(ConstantsResolver.resourcesHardCoded).toString()); + String[] hardCode = ConstantsResolver.resourcesHardCoded; + + for (String resource : hardCode) { + log.trace("Is requested resource '{}' starting with hard-coded resource '{}'?", + requestedResourceName, resource); + if (requestedResourceName.startsWith(resource)) { log.trace("Yes it starts!"); candidateResource = resource; - log.info("The candidate resource to manage the request is the hard-coded resource: {}",candidateResource); + log.info("The candidate resource to manage the request is the hard-coded resource: {}", + candidateResource); resourceToRedirectFound = true; break; } } - - } - - }else - log.warn("It was not possible to get the resource name from the splitted path {}. No action performed", path); - }else { - log.warn("It was not possible to split the path {}. No action performed", path); - } - }catch (Exception e) { + + } + + } else + log.warn( + "It was not possible to get the resource name from the splitted path {}. No action performed", + path); + } else { + log.warn("It was not possible to split the path {}. No action performed", path); + } + } catch (Exception e) { log.error("Error trying to retrieve the service able to manage the request. No action performed", e); } - - if(resourceToRedirectFound) { - log.debug("The input request '{}' can be managed by the service '{}'. No redirect performed", path, candidateResource); - }else { - log.info("No resource/service found to manage the input request '{}'", path); - String newPath = String.format("/%s/%s", ConstantsResolver.defaultServiceToRedirect,path); - //log.debug("The path to redirect is '{}'", newPath); - //URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build(); - UriBuilder uriBuilder = reqContext.getUriInfo().getBaseUriBuilder(); - //ADDING THE INPUT QUERY STRING - MultivaluedMap queryParameters = reqContext.getUriInfo().getQueryParameters(); - for (String param : queryParameters.keySet()) { - List values = queryParameters.get(param); - if(values!=null && !values.isEmpty()) - uriBuilder.queryParam(param,values.toArray()); - } - - URI newRequestURI = uriBuilder.path(newPath).build(); - log.info("Redirect to URI path '{}'", newRequestURI.toString()); - reqContext.setRequestUri(newRequestURI); - } - } - /* (non-Javadoc) - * @see javax.ws.rs.container.ContainerResponseFilter#filter(javax.ws.rs.container.ContainerRequestContext, javax.ws.rs.container.ContainerResponseContext) + if (resourceToRedirectFound) { + log.debug("The input request '{}' can be managed by the service '{}'. No redirect performed", path, + candidateResource); + } else { + log.info("No resource/service found to manage the input request '{}'", path); + String newPath = String.format("/%s/%s", ConstantsResolver.defaultServiceToRedirect, path); + // log.debug("The path to redirect is '{}'", newPath); + // URI newRequestURI = + // reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build(); + UriBuilder uriBuilder = reqContext.getUriInfo().getBaseUriBuilder(); + // ADDING THE INPUT QUERY STRING + MultivaluedMap queryParameters = reqContext.getUriInfo().getQueryParameters(); + for (String param : queryParameters.keySet()) { + List values = queryParameters.get(param); + if (values != null && !values.isEmpty()) + uriBuilder.queryParam(param, values.toArray()); + } + + URI newRequestURI = uriBuilder.path(newPath).build(); + log.info("Redirect to URI path '{}'", newRequestURI.toString()); + reqContext.setRequestUri(newRequestURI); + } + } + + /** + * Filter. + * + * @param requestContext the request context + * @param responseContext the response context + * @throws IOException Signals that an I/O exception has occurred. + */ + /* + * (non-Javadoc) + * + * @see + * javax.ws.rs.container.ContainerResponseFilter#filter(javax.ws.rs.container. + * ContainerRequestContext, javax.ws.rs.container.ContainerResponseContext) */ @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { - log.info(RequestHandler.class.getSimpleName() +" Response called"); + log.info(RequestHandler.class.getSimpleName() + " Response called"); SecurityTokenProvider.instance.reset(); ScopeProvider.instance.reset(); - log.info("Token and Scope Provider reset called"); + log.debug("Token and Scope Provider reset called"); + resetScretManager(requestContext, responseContext); } + /** + * Reset scret manager. + * + * @param requestContext the request context + * @param responseContext the response context + * @throws IOException Signals that an I/O exception has occurred. + */ + private void resetScretManager(ContainerRequestContext requestContext, ContainerResponseContext responseContext) + throws IOException { + log.debug("SecreteManager instance remove"); + SecretManagerProvider.instance.remove(); + } + + /** + * Sets the secret manager. + * + * @param requestContext the new secret manager + * @throws IOException Signals that an I/O exception has occurred. + */ + private void setSecretManager(ContainerRequestContext requestContext) throws IOException { + log.debug("setSecretManager called"); + + SecretManagerProvider.instance.remove(); + SecretManager secretManager = new SecretManager(); + + String token = AccessTokenProvider.instance.get(); + if (token != null) { + Secret secret = new JWTSecret(token); + secretManager.addSecret(secret); + } + + token = SecurityTokenProvider.instance.get(); + if (token != null) { + Secret secret = new GCubeSecret(token); + secretManager.addSecret(secret); + } + + SecretManagerProvider.instance.set(secretManager); + } + } \ No newline at end of file diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 9641623..ed4276d 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -1,5 +1,8 @@ package org.gcube.datatransfer.resolver.services; +import java.io.InputStream; +import java.net.URL; + import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -9,17 +12,23 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +import org.gcube.application.geoportalcommon.GeoportalCommon; +import org.gcube.application.geoportalcommon.shared.GeoportalItemReferences; +import org.gcube.application.geoportalcommon.shared.GeoportalItemReferences.SHARE_LINK_TO; import org.gcube.application.geoportaldatamapper.exporter.Geoportal_PDF_Exporter; import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource; +import org.gcube.application.geoportaldatamapper.shared.FileReference; import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import org.gcube.common.authorization.utils.user.User; import org.gcube.datatransfer.resolver.ConstantsResolver; -import org.gcube.datatransfer.resolver.geoportal.TargetAppGeoportalCodes; -import org.gcube.datatransfer.resolver.services.GeoportalResolver.RESOLVE_AS; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; +import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,11 +68,13 @@ public class GeoportalExporter { */ @GET @Path("/export/{type}/{usecase_id}/{project_id}") - @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) + @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN, MediaType.APPLICATION_OCTET_STREAM }) public Response export(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) throws WebApplicationException { + String userAgentName = req.getHeader("User-Agent"); + LOG.info(this.getClass().getSimpleName() + " export - GET starts..."); LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID); @@ -71,7 +82,7 @@ public class GeoportalExporter { checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID); checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID); - ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type); + checkExportType(req, export_type); try { @@ -87,43 +98,56 @@ public class GeoportalExporter { Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); boolean checked = pdfExporter.checkConfig(); - if (!checked) - return Response.status(Status.NOT_FOUND).build(); - - ExporterProjectSource exporterSource = new ExporterProjectSource(); - RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC; - // #NB SET USERNAME = null to export with PUBLIC ACCESS - if (!cm.getUser().isApplication()) { - // here the token is of an user - resolveAs = RESOLVE_AS.PRIVATE; - exporterSource.setAccountname(user.getUsername()); - } - - exporterSource.setScope(context); - exporterSource.setProjectID(projectID); - exporterSource.setProfileID(ucdID); - - String vreName = context.substring(context.lastIndexOf("/") + 1, context.length()); - LOG.info("Requesting gis link to vre {}", vreName); - Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req, - TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name()); - String theGisLink = theReponseWithLink.getEntity().toString(); - LOG.info("Gis link returned {}", theGisLink); - exporterSource.setGisLink(theGisLink); +// ExporterProjectSource exporterSource = new ExporterProjectSource(); +// RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC; +// // #NB SET USERNAME = null to export with PUBLIC ACCESS +// if (!cm.getUser().isApplication()) { +// // here the token is of an user +// resolveAs = RESOLVE_AS.PRIVATE; +// exporterSource.setAccountname(user.getUsername()); +// } +// +// exporterSource.setScope(context); +// exporterSource.setProjectID(projectID); +// exporterSource.setProfileID(ucdID); +// +// String vreName = context.substring(context.lastIndexOf("/") + 1, context.length()); +// LOG.info("Requesting gis link to vre {}", vreName); +// Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req, +// TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name()); +// String theGisLink = theReponseWithLink.getEntity().toString(); +// LOG.info("Gis link returned {}", theGisLink); +// exporterSource.setGisLink(theGisLink); if (checked) { - String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); - return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") - .build(); + String pdfURL = null; + if (userAgentName != null) { + LOG.info("Serving request as User-Agent {}", userAgentName); + String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); + return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") + .build(); + } else { + LOG.info("Serving request as client..."); + FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); + + InputStream input = new URL(pdfURL).openStream(); + StreamingOutput so = new SingleFileStreamingOutput(input); + + ResponseBuilder response = Response.ok(so) + .header(ConstantsResolver.CONTENT_DISPOSITION, + "inline; filename=\"" + pdfRef.getFileName() + "\"") + .header("Content-Type", pdfRef.getContentType()); + return response.build(); + } } else { - return Response.status(Status.NOT_FOUND).entity(GeoportalExporter.class.getSimpleName() + " Config KO") + return Response.status(Status.NOT_FOUND) + .entity(GeoportalExporter.class.getSimpleName() + " Config not found in the context " + context) .type(MediaType.TEXT_PLAIN).build(); } } catch (Exception e) { - LOG.error("Error on performing healthcheck", e); - throw ExceptionManager.internalErrorException(req, - "Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck", + LOG.error("Error on performing export", e); + throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", this.getClass(), helpURI); } @@ -131,7 +155,7 @@ public class GeoportalExporter { @GET @Path("/export/{type}/healthcheck") - @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) + @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) public Response healthcheck(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type) throws WebApplicationException { @@ -140,7 +164,7 @@ public class GeoportalExporter { checkPathParameterNotNull(req, EXPORT_TYPE, export_type); - ACCEPTED_EXPORT_TYPE exportType = toKnowExportType(req, export_type); + checkExportType(req, export_type); try { @@ -183,8 +207,7 @@ public class GeoportalExporter { } } - public ACCEPTED_EXPORT_TYPE toKnowExportType(HttpServletRequest req, String export_type) - throws BadRequestException { + public ACCEPTED_EXPORT_TYPE checkExportType(HttpServletRequest req, String export_type) throws BadRequestException { ACCEPTED_EXPORT_TYPE exportType; try { exportType = ACCEPTED_EXPORT_TYPE.valueOf(export_type); @@ -199,10 +222,71 @@ public class GeoportalExporter { return exportType; } + public FileReference exportAsPDF(HttpServletRequest req, String profileID, String projectID, String profileTitle, + String context, User user) throws WebApplicationException { + LOG.info("exportAsPDF for profileID: " + profileID + ", projectID: " + projectID + "called"); + LOG.info("exportAsPDF context is {}, user is {}", context, user); + + FileReference pdfRef = null; + try { + + Geoportal_PDF_Exporter gpdfe = new Geoportal_PDF_Exporter(); + ExporterProjectSource exportSource = new ExporterProjectSource(); + exportSource.setProfileID(profileID); + exportSource.setProfileTitle(profileTitle); + exportSource.setProjectID(projectID); + exportSource.setScope(context); + + GeoportalItemReferences geoportalItemReferences = new GeoportalItemReferences(projectID, profileID, + SHARE_LINK_TO.DATA_VIEWER); + GeoportalItemReferences gir = getPublicLinksFor(geoportalItemReferences, context); + + if (user.isApplication()) { + exportSource.setGisLink(gir.getOpenLink().getShortURL()); + exportSource.setAccountname(null); + } else { + exportSource.setGisLink(gir.getRestrictedLink().getShortURL()); + exportSource.setAccountname(user.getUsername()); + } + + pdfRef = gpdfe.createPDFFile(exportSource); + + } catch (Exception e1) { + LOG.error("Error occurred when exporting the project", e1); + throw ExceptionManager.internalErrorException(req, "Sorry, an error occurred when exporting the project", + this.getClass(), helpURI); + } + return pdfRef; + } + + public GeoportalItemReferences getPublicLinksFor(GeoportalItemReferences item, String context) throws Exception { + LOG.info("getPublicLinksFor called for: " + item); + + try { + + if (item == null) + throw new Exception("Bad request, the item is null"); + + if (item.getProjectID() == null) + throw new Exception("Bad request, the projectID is null"); + + if (item.getProfileID() == null) + throw new Exception("Bad request, the profileID is null"); + + GeoportalCommon gc = new GeoportalCommon(); + return gc.getPublicLinksFor(context, item, true); + + } catch (Exception e) { + LOG.error("Error on getPublicLinksFor for: " + item, e); + throw new Exception("Share link not available for this item. Try later or contact the support. Error: " + + e.getMessage()); + } + } + /** * Sets the HTML message. * - * @param action the action + * @param action the action * @param message the message * @param waiting the waiting * @return the string @@ -210,38 +294,22 @@ public class GeoportalExporter { protected String entityHTMLMessage(String action, String message, boolean waiting) { String html = "" + "" + "" - + "" + + "" + "D4Science Geoportal - Action" + "" + ""; - html += "\"D4Science
"; - + html += "
"; html += "

" + action + "

"; - + if (waiting) { html += "\"D4Science
"; } - + html += "

" + message + "

"; html += "
"; From ffcc6a15e10e66e15cbe9fd16ee9b6944f4d6220 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 11:38:05 +0200 Subject: [PATCH 10/83] commented User-Agent --- .../resolver/services/GeoportalExporter.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index ed4276d..c9799c2 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -121,12 +121,12 @@ public class GeoportalExporter { if (checked) { String pdfURL = null; - if (userAgentName != null) { - LOG.info("Serving request as User-Agent {}", userAgentName); - String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); - return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") - .build(); - } else { +// if (userAgentName != null) { +// LOG.info("Serving request as User-Agent {}", userAgentName); +// String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); +// return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") +// .build(); +// } else { LOG.info("Serving request as client..."); FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); @@ -138,7 +138,7 @@ public class GeoportalExporter { "inline; filename=\"" + pdfRef.getFileName() + "\"") .header("Content-Type", pdfRef.getContentType()); return response.build(); - } +// } } else { return Response.status(Status.NOT_FOUND) .entity(GeoportalExporter.class.getSimpleName() + " Config not found in the context " + context) From 1f33e820d52702dd2c2bbea9c70bc9c15dd9455d Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 12:28:56 +0200 Subject: [PATCH 11/83] fixed GeoportalExporter stream --- .settings/org.eclipse.wst.common.component | 33 ++++++++++--------- .../resolver/services/GeoportalExporter.java | 4 +-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index da8308c..3b11317 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -25,7 +26,8 @@ - + + @@ -51,7 +53,8 @@ - + + @@ -77,7 +80,8 @@ - + + @@ -103,7 +107,8 @@ - + + @@ -135,13 +140,8 @@ uses - - uses - - - uses - - + + @@ -167,7 +167,8 @@ - + + @@ -193,7 +194,8 @@ - + + @@ -219,7 +221,8 @@ - + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index c9799c2..bd9a15c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -130,7 +130,7 @@ public class GeoportalExporter { LOG.info("Serving request as client..."); FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); - InputStream input = new URL(pdfURL).openStream(); + InputStream input = pdfRef.getStorageVolatileURL().openStream(); StreamingOutput so = new SingleFileStreamingOutput(input); ResponseBuilder response = Response.ok(so) @@ -307,7 +307,7 @@ public class GeoportalExporter { html += "

" + action + "

"; if (waiting) { - html += "\"D4Science
"; + html += "\"D4Science
"; } html += "

" + message + "

"; From df64963bc38b3cedd6e3d19b324da358083a31f3 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 12:42:20 +0200 Subject: [PATCH 12/83] added user agent check --- .../resolver/services/GeoportalExporter.java | 36 ++++--------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index bd9a15c..81abda1 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -98,35 +98,13 @@ public class GeoportalExporter { Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); boolean checked = pdfExporter.checkConfig(); -// ExporterProjectSource exporterSource = new ExporterProjectSource(); -// RESOLVE_AS resolveAs = RESOLVE_AS.PUBLIC; -// // #NB SET USERNAME = null to export with PUBLIC ACCESS -// if (!cm.getUser().isApplication()) { -// // here the token is of an user -// resolveAs = RESOLVE_AS.PRIVATE; -// exporterSource.setAccountname(user.getUsername()); -// } -// -// exporterSource.setScope(context); -// exporterSource.setProjectID(projectID); -// exporterSource.setProfileID(ucdID); -// -// String vreName = context.substring(context.lastIndexOf("/") + 1, context.length()); -// LOG.info("Requesting gis link to vre {}", vreName); -// Response theReponseWithLink = new GeoportalResolver().genericResolveLink(req, -// TargetAppGeoportalCodes.GEO_DV, vreName, ucdID, projectID, resolveAs.name()); -// String theGisLink = theReponseWithLink.getEntity().toString(); -// LOG.info("Gis link returned {}", theGisLink); -// exporterSource.setGisLink(theGisLink); - if (checked) { - String pdfURL = null; -// if (userAgentName != null) { -// LOG.info("Serving request as User-Agent {}", userAgentName); -// String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); -// return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") -// .build(); -// } else { + if (userAgentName != null) { + LOG.info("Serving request as User-Agent {}", userAgentName); + String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); + return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") + .build(); + } else { LOG.info("Serving request as client..."); FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); @@ -138,7 +116,7 @@ public class GeoportalExporter { "inline; filename=\"" + pdfRef.getFileName() + "\"") .header("Content-Type", pdfRef.getContentType()); return response.build(); -// } + } } else { return Response.status(Status.NOT_FOUND) .entity(GeoportalExporter.class.getSimpleName() + " Config not found in the context " + context) From 324099ceb9123e5521f035e961f9f631ab6787d6 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 14:20:04 +0200 Subject: [PATCH 13/83] using jersey 2.25.1 --- pom.xml | 9 ++- .../datatransfer/resolver/UriResolver.java | 3 + .../UriResolverServletContextListener.java | 2 +- .../resolver/services/DocsGenerator.java | 9 ++- .../resolver/services/GeoportalExporter.java | 63 +++++++++++++++++++ .../resolver/services/UriResolverIndex.java | 12 ++-- .../resolver/services/UriResolverInfo.java | 4 +- .../resolver/services/WekeoResolver.java | 10 +-- .../webapp/WEB-INF/jsp/geoportal_exporter.jsp | 43 +++++++++++++ 9 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 src/main/webapp/WEB-INF/jsp/geoportal_exporter.jsp diff --git a/pom.xml b/pom.xml index b86f958..85a468f 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ - 2.24.1 + 2.25.1 1.8 1.8 2.14.0 @@ -137,7 +137,12 @@ ${jersey.version} compile
- + + org.glassfish.jersey.ext + jersey-mvc-jsp + ${jersey.version} + compile + org.glassfish.jersey.core jersey-server diff --git a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java index 8cc867c..9f30229 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java @@ -9,6 +9,7 @@ import org.gcube.datatransfer.resolver.services.CatalogueResolver; import org.gcube.datatransfer.resolver.services.tobackward.BackCatalogueResolver; import org.gcube.smartgears.annotations.ManagedBy; import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature; @Path("uri-resolver") @ManagedBy(UriResolverSmartGearManagerInit.class) @@ -18,6 +19,8 @@ public class UriResolver extends ResourceConfig { // Register all resources present under the package. packages(CatalogueResolver.class.getPackage().getName(), RequestHandler.class.getPackage().getName(), BackCatalogueResolver.class.getPackage().getName()); packages(DataMinerInvocation.class.getPackage().getName()); + register(JspMvcFeature.class); + property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/jsp"); } } diff --git a/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java b/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java index 5e41b19..8318d5f 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java +++ b/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java @@ -35,7 +35,7 @@ public class UriResolverServletContextListener implements ServletContextListener public void contextInitialized(ServletContextEvent event) { servletContext = event.getServletContext(); - log.info("Context Initialized at context path: "+servletContext.getContextPath()); + log.info("Context Initialized at context path: "+servletContext.getContext("/")); } @Override diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java b/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java index d782da0..7df567e 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java @@ -14,6 +14,7 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,7 +39,7 @@ public class DocsGenerator { */ @GET @Path("/{any: .*}") - public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException { + public Viewable toDoc(@Context HttpServletRequest req) throws WebApplicationException { logger.info(DocsGenerator.class.getSimpleName() + " toDoc called"); String pathInfo = req.getPathInfo(); @@ -51,8 +52,10 @@ public class DocsGenerator { logger.info("going to {}", pathInfo); - String realPath = req.getServletContext().getRealPath(pathInfo); - return new FileInputStream(new File(realPath)); + //String realPath = req.getServletContext().getRealPath(pathInfo); + //return new FileInputStream(new File(realPath)); + + return new Viewable(pathInfo); } catch (Exception e) { diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 81abda1..f0ff0d7 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -29,6 +29,7 @@ import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; +import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -131,6 +132,68 @@ public class GeoportalExporter { } + /** + * Resolve geoportal no app def. + * + * @param req the req + * @param vreName the vre name + * @param exportType the export type + * @param ucdID the ucd ID + * @param projectID the project ID + * @return the response + * @throws WebApplicationException the web application exception + */ + @GET + @Path("/export/{type}/view/{usecase_id}/{project_id}") + @Produces({ MediaType.TEXT_HTML }) + public Viewable exportView(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, + @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) + throws WebApplicationException { + + String userAgentName = req.getHeader("User-Agent"); + + LOG.info(this.getClass().getSimpleName() + " export view - GET starts..."); + LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID); + + checkPathParameterNotNull(req, EXPORT_TYPE, export_type); + checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID); + checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID); + + checkExportType(req, export_type); + + try { + + SecretManager cm = SecretManagerProvider.instance.get(); + String context = cm.getContext(); + if (context == null) { + throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), + helpURI); + } + org.gcube.common.authorization.utils.user.User user = cm.getUser(); + LOG.info("Identified caller {} in context {}", user.getUsername(), context); + + Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); + boolean checked = pdfExporter.checkConfig(); + + if (checked) { + LOG.info("Serving request as User-Agent {}", userAgentName); + //String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); +// return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") +// .build(); + return new Viewable("/geoportal_exporter"); + } else { + throw ExceptionManager.notFoundException(req, this.getClass().getSimpleName()+ " not found in the context: "+context, + this.getClass(), helpURI); + } + + } catch (Exception e) { + LOG.error("Error on performing export", e); + throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", + this.getClass(), helpURI); + } + + } + @GET @Path("/export/{type}/healthcheck") @Produces({ MediaType.TEXT_HTML, MediaType.TEXT_PLAIN }) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java index 286bf1a..fcf88f4 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java @@ -16,6 +16,7 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,6 +31,8 @@ import org.slf4j.LoggerFactory; public class UriResolverIndex { private static Logger logger = LoggerFactory.getLogger(UriResolverIndex.class); + + private String indexFile = "/index"; /** * Index. @@ -41,14 +44,15 @@ public class UriResolverIndex { @GET @Produces({ MediaType.TEXT_HTML }) @Path("") - public InputStream index(@Context HttpServletRequest req) throws WebApplicationException { + public Viewable index(@Context HttpServletRequest req) throws WebApplicationException { - String indexFile = "/WEB-INF/jsp/index.jsp"; + //String indexFile = "/WEB-INF/jsp/index.jsp"; try { logger.info(UriResolverIndex.class.getSimpleName() + " called"); - String realPath = req.getServletContext().getRealPath(indexFile); - return new FileInputStream(new File(realPath)); + //String realPath = req.getServletContext().getRealPath(indexFile); + return new Viewable(indexFile); + //return new FileInputStream(new File(realPath)); } catch (Exception e) { if (!(e instanceof WebApplicationException)) { diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverInfo.java b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverInfo.java index d63639a..7c48d01 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverInfo.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverInfo.java @@ -13,6 +13,8 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import org.glassfish.jersey.server.mvc.Viewable; + /** * The UriResolverInfo get index. * @@ -33,7 +35,7 @@ public class UriResolverInfo { @GET @Produces({ MediaType.TEXT_HTML }) @Path("") - public InputStream info(@Context HttpServletRequest req) throws WebApplicationException { + public Viewable info(@Context HttpServletRequest req) throws WebApplicationException { return new UriResolverIndex().index(req); } } diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/WekeoResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/WekeoResolver.java index 92dae4b..66996f1 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/WekeoResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/WekeoResolver.java @@ -32,6 +32,7 @@ import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.NotFoundException; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; +import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -190,14 +191,15 @@ public class WekeoResolver { @GET @Produces({ MediaType.TEXT_HTML }) @Path("") - public InputStream index(@Context HttpServletRequest req) throws WebApplicationException { + public Viewable index(@Context HttpServletRequest req) throws WebApplicationException { String indexFile = "/WEB-INF/jsp/wekeo.jsp"; try { - logger.info(this.getClass().getSimpleName() + " index called"); - String realPath = req.getServletContext().getRealPath(indexFile); - return new FileInputStream(new File(realPath)); +// logger.info(this.getClass().getSimpleName() + " index called"); +// String realPath = req.getServletContext().getRealPath(indexFile); +// return new FileInputStream("/wekeo"); + return new Viewable(indexFile); } catch (Exception e) { if (!(e instanceof WebApplicationException)) { diff --git a/src/main/webapp/WEB-INF/jsp/geoportal_exporter.jsp b/src/main/webapp/WEB-INF/jsp/geoportal_exporter.jsp new file mode 100644 index 0000000..d232f58 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/geoportal_exporter.jsp @@ -0,0 +1,43 @@ + + + + + + +D4Science Geoportal - Action + + + + D4Science Logo +
+
+

Exporting as PDF...

+ D4Science Geoportal Loading...
+
+

The project with 661d2c6f8804530afb90b132

+
+ + \ No newline at end of file From 06f87b79568649ae1a0c16a35fbf6674d8582d85 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 14:58:59 +0200 Subject: [PATCH 14/83] updated GeoportalExporter --- pom.xml | 12 +- .../datatransfer/resolver/UriResolver.java | 5 +- .../UriResolverServletContextListener.java | 2 +- .../resolver/services/DocsGenerator.java | 9 +- .../resolver/services/GeoportalExporter.java | 176 +++++++++++------- .../resolver/services/UriResolverIndex.java | 12 +- .../resolver/services/UriResolverInfo.java | 4 +- .../resolver/services/WekeoResolver.java | 10 +- 8 files changed, 133 insertions(+), 97 deletions(-) diff --git a/pom.xml b/pom.xml index 85a468f..bdf0d71 100644 --- a/pom.xml +++ b/pom.xml @@ -137,12 +137,12 @@ ${jersey.version} compile
- - org.glassfish.jersey.ext - jersey-mvc-jsp - ${jersey.version} - compile - + + + + + + org.glassfish.jersey.core jersey-server diff --git a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java index 9f30229..436d6cf 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java @@ -9,7 +9,6 @@ import org.gcube.datatransfer.resolver.services.CatalogueResolver; import org.gcube.datatransfer.resolver.services.tobackward.BackCatalogueResolver; import org.gcube.smartgears.annotations.ManagedBy; import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.server.mvc.jsp.JspMvcFeature; @Path("uri-resolver") @ManagedBy(UriResolverSmartGearManagerInit.class) @@ -19,8 +18,8 @@ public class UriResolver extends ResourceConfig { // Register all resources present under the package. packages(CatalogueResolver.class.getPackage().getName(), RequestHandler.class.getPackage().getName(), BackCatalogueResolver.class.getPackage().getName()); packages(DataMinerInvocation.class.getPackage().getName()); - register(JspMvcFeature.class); - property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/jsp"); + //register(JspMvcFeature.class); + //property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/jsp"); } } diff --git a/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java b/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java index 8318d5f..5e41b19 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java +++ b/src/main/java/org/gcube/datatransfer/resolver/init/UriResolverServletContextListener.java @@ -35,7 +35,7 @@ public class UriResolverServletContextListener implements ServletContextListener public void contextInitialized(ServletContextEvent event) { servletContext = event.getServletContext(); - log.info("Context Initialized at context path: "+servletContext.getContext("/")); + log.info("Context Initialized at context path: "+servletContext.getContextPath()); } @Override diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java b/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java index 7df567e..d782da0 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/DocsGenerator.java @@ -14,7 +14,6 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; -import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,7 +38,7 @@ public class DocsGenerator { */ @GET @Path("/{any: .*}") - public Viewable toDoc(@Context HttpServletRequest req) throws WebApplicationException { + public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException { logger.info(DocsGenerator.class.getSimpleName() + " toDoc called"); String pathInfo = req.getPathInfo(); @@ -52,10 +51,8 @@ public class DocsGenerator { logger.info("going to {}", pathInfo); - //String realPath = req.getServletContext().getRealPath(pathInfo); - //return new FileInputStream(new File(realPath)); - - return new Viewable(pathInfo); + String realPath = req.getServletContext().getRealPath(pathInfo); + return new FileInputStream(new File(realPath)); } catch (Exception e) { diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index f0ff0d7..ab68b79 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -1,7 +1,6 @@ package org.gcube.datatransfer.resolver.services; import java.io.InputStream; -import java.net.URL; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; @@ -29,10 +28,11 @@ import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; -import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.JsonObject; + /** * The Class GeoportalExporter. * @@ -43,6 +43,8 @@ import org.slf4j.LoggerFactory; @Path("geoportal") public class GeoportalExporter { + private static final String PDF_CODE = "pdfCode"; + public static final String EXPORT_TYPE = "type"; public static final String PATH_PROJECT_ID = GeoportalResolver.PATH_PROJECT_ID; @@ -102,7 +104,9 @@ public class GeoportalExporter { if (checked) { if (userAgentName != null) { LOG.info("Serving request as User-Agent {}", userAgentName); - String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); + String pollingCode = ucdID+"_"+projectID+"_"+System.currentTimeMillis(); + String viewPdfURL = req.getServletContext()+"/view/"+pollingCode; + String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true, viewPdfURL); return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") .build(); } else { @@ -132,67 +136,66 @@ public class GeoportalExporter { } - /** - * Resolve geoportal no app def. - * - * @param req the req - * @param vreName the vre name - * @param exportType the export type - * @param ucdID the ucd ID - * @param projectID the project ID - * @return the response - * @throws WebApplicationException the web application exception - */ - @GET - @Path("/export/{type}/view/{usecase_id}/{project_id}") - @Produces({ MediaType.TEXT_HTML }) - public Viewable exportView(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, - @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) - throws WebApplicationException { - - String userAgentName = req.getHeader("User-Agent"); - - LOG.info(this.getClass().getSimpleName() + " export view - GET starts..."); - LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID); - - checkPathParameterNotNull(req, EXPORT_TYPE, export_type); - checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID); - checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID); - - checkExportType(req, export_type); - - try { - - SecretManager cm = SecretManagerProvider.instance.get(); - String context = cm.getContext(); - if (context == null) { - throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), - helpURI); - } - org.gcube.common.authorization.utils.user.User user = cm.getUser(); - LOG.info("Identified caller {} in context {}", user.getUsername(), context); - - Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); - boolean checked = pdfExporter.checkConfig(); - - if (checked) { - LOG.info("Serving request as User-Agent {}", userAgentName); - //String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); +// /** +// * Resolve geoportal no app def. +// * +// * @param req the req +// * @param vreName the vre name +// * @param exportType the export type +// * @param ucdID the ucd ID +// * @param projectID the project ID +// * @return the response +// * @throws WebApplicationException the web application exception +// */ +// @GET +// @Path("/export/{type}/view/{usecase_id}/{project_id}") +// @Produces({ MediaType.TEXT_HTML }) +// public Response exportView(@Context HttpServletRequest req, @PathParam(EXPORT_TYPE) String export_type, +// @PathParam(PATH_USECASE_ID) String ucdID, @PathParam(PATH_PROJECT_ID) String projectID) +// throws WebApplicationException { +// +// String userAgentName = req.getHeader("User-Agent"); +// +// LOG.info(this.getClass().getSimpleName() + " export view - GET starts..."); +// LOG.debug("params are: exportType: {}, ucdID: {}, projectID: {}", export_type, ucdID, projectID); +// +// checkPathParameterNotNull(req, EXPORT_TYPE, export_type); +// checkPathParameterNotNull(req, PATH_USECASE_ID, ucdID); +// checkPathParameterNotNull(req, PATH_PROJECT_ID, projectID); +// +// checkExportType(req, export_type); +// +// try { +// +// SecretManager cm = SecretManagerProvider.instance.get(); +// String context = cm.getContext(); +// if (context == null) { +// throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), +// helpURI); +// } +// org.gcube.common.authorization.utils.user.User user = cm.getUser(); +// LOG.info("Identified caller {} in context {}", user.getUsername(), context); +// +// Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); +// boolean checked = pdfExporter.checkConfig(); +// +// if (checked) { +// LOG.info("Serving request as User-Agent {}", userAgentName); +// String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true); // return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") // .build(); - return new Viewable("/geoportal_exporter"); - } else { - throw ExceptionManager.notFoundException(req, this.getClass().getSimpleName()+ " not found in the context: "+context, - this.getClass(), helpURI); - } - - } catch (Exception e) { - LOG.error("Error on performing export", e); - throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", - this.getClass(), helpURI); - } - - } +// } else { +// throw ExceptionManager.notFoundException(req, this.getClass().getSimpleName()+ " not found in the context: "+context, +// this.getClass(), helpURI); +// } +// +// } catch (Exception e) { +// LOG.error("Error on performing export", e); +// throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", +// this.getClass(), helpURI); +// } +// +// } @GET @Path("/export/{type}/healthcheck") @@ -238,6 +241,33 @@ public class GeoportalExporter { this.getClass(), helpURI); } } + + @GET + @Path("/view/{pdfCode}") + @Produces({ MediaType.TEXT_PLAIN }) + public Response viewPDF(@Context HttpServletRequest req, @PathParam(PDF_CODE) String pdfCode) + throws WebApplicationException { + + LOG.info(this.getClass().getSimpleName() + " viewPDF - GET starts..."); + LOG.debug("param is: pdfCode: {}", pdfCode); + + checkPathParameterNotNull(req, EXPORT_TYPE, pdfCode); + + try { + + + } catch (Exception e) { + LOG.error("Error on performing healthcheck", e); + throw ExceptionManager.internalErrorException(req, + "Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck", + this.getClass(), helpURI); + } + + JsonObject jsonObject = new JsonObject(); + jsonObject.add("url", null); + String json = jsonObject.toString(); + return Response.ok(json).build(); + } public void checkPathParameterNotNull(HttpServletRequest req, String parameter, String value) throws BadRequestException { @@ -332,7 +362,7 @@ public class GeoportalExporter { * @param waiting the waiting * @return the string */ - protected String entityHTMLMessage(String action, String message, boolean waiting) { + protected String entityHTMLMessage(String action, String message, boolean waiting, String viewPdfURL) { String html = "" + "" + "" + "" - + "D4Science Geoportal - Action" + "" + ""; +// String html = "" + "" + "" +// + "" +// + "D4Science Geoportal - Action" + "" + ""; +// +// html += "\"D4Science
"; +// +// html += "
"; +// html += "

" + action + "

"; +// +// if (waiting) { +// html += "\"D4Science
"; +// } +// +// html += "

" + message + "

"; +// html += "
" +// + "" +// + ""; + + + + String newHTML = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " D4Science Geoportal - Action\n" + + " \n" + + "\n" + + " "; + + newHTML += "\"D4Science
"; - html += "\"D4Science
"; - - html += "
"; - html += "

" + action + "

"; + newHTML += "
"; + newHTML += "

" + action + "

"; if (waiting) { - html += "\"D4Science
"; + newHTML += "\"D4Science
"; } + + newHTML += "

" + message + "

"; + newHTML += "
/body>"; - html += "

" + message + "

"; - html += "
" - + "" - + ""; - - return html; + return newHTML; } } From 1f2baf3ef724ca6990e17312ebea13d7dd24cc71 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 16:10:56 +0200 Subject: [PATCH 17/83] Updated --- .../resolver/geoportal/exporter/FetchPDF.java | 65 +++++++ .../geoportal/exporter/HTML_Page.java | 133 ++++++++++++++ .../resolver/services/GeoportalExporter.java | 172 ++++-------------- 3 files changed, 234 insertions(+), 136 deletions(-) create mode 100644 src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/FetchPDF.java create mode 100644 src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/FetchPDF.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/FetchPDF.java new file mode 100644 index 0000000..227e5ed --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/FetchPDF.java @@ -0,0 +1,65 @@ +package org.gcube.datatransfer.resolver.geoportal.exporter; + +import org.gcube.application.geoportaldatamapper.shared.FileReference; + +public class FetchPDF { + + private final int MAX_RETRY = 10; + private FileReference fileRef; + private String code; + + private int attempt = 0; + + public FetchPDF() { + + } + + public FetchPDF(FileReference fileRef, String code, int attempt) { + super(); + this.fileRef = fileRef; + this.code = code; + this.attempt = attempt; + } + + public int getMAX_RETRY() { + return MAX_RETRY; + } + + public FileReference getFileRef() { + return fileRef; + } + + public String getCode() { + return code; + } + + public int getAttempt() { + return attempt; + } + + public void setFileRef(FileReference fileRef) { + this.fileRef = fileRef; + } + + public synchronized void incrementAttempt() { + attempt++; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("FetchPDF [MAX_RETRY="); + builder.append(MAX_RETRY); + builder.append(", fileRef="); + builder.append(fileRef); + builder.append(", code="); + builder.append(code); + builder.append(", attempt="); + builder.append(attempt); + builder.append("]"); + return builder.toString(); + } + + +} diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java new file mode 100644 index 0000000..c4c958d --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -0,0 +1,133 @@ +package org.gcube.datatransfer.resolver.geoportal.exporter; + +public class HTML_Page { + + + /** + * Sets the HTML message. + * + * @param action the action + * @param message the message + * @param waiting the waiting + * @return the string + */ + public static String entityHTMLMessage(String action, String message, boolean waiting, String viewPdfURL) { + + String newHTML = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " D4Science Geoportal - Action\n" + + " \n" + + "\n" + + " "; + + newHTML += "\"D4Science
"; + + newHTML += "
"; + newHTML += "

" + action + "

"; + + if (waiting) { + newHTML += "\"D4Science
"; + } + + newHTML += "

" + message + "

"; + newHTML += "
/body>"; + + return newHTML; + } + + + /** + * Sets the HTML message. + * + * @param action the action + * @param message the message + * @param waiting the waiting + * @return the string + */ + public static String getErrorPage(String action, String message) { + + String newHTML = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""; + + newHTML += "\"D4Science
"; + + newHTML += "
"; + newHTML += "

" + action + "

"; + newHTML += "

" + message + "

"; + newHTML += "
/body>"; + + return newHTML; + } + + +} diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index f1d4666..737d58c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -1,7 +1,6 @@ package org.gcube.datatransfer.resolver.services; import java.io.InputStream; -import java.util.HashMap; import java.util.LinkedHashMap; import javax.servlet.http.HttpServletRequest; @@ -27,6 +26,8 @@ import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.authorization.utils.user.User; import org.gcube.datatransfer.resolver.ConstantsResolver; +import org.gcube.datatransfer.resolver.geoportal.exporter.FetchPDF; +import org.gcube.datatransfer.resolver.geoportal.exporter.HTML_Page; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; @@ -55,8 +56,8 @@ public class GeoportalExporter { private static final Logger LOG = LoggerFactory.getLogger(GeoportalExporter.class); private static String helpURI = "https://wiki.gcube-system.org/gcube/URI_Resolver#Geoportal_Resolver"; - - private static LinkedHashMap map = new LinkedHashMap(); + + private static LinkedHashMap map = new LinkedHashMap(); public enum ACCEPTED_EXPORT_TYPE { pdf @@ -108,25 +109,32 @@ public class GeoportalExporter { if (checked) { if (userAgentName != null) { LOG.info("Serving request as User-Agent {}", userAgentName); - final String pollingCode = ucdID+"_"+projectID+"_"+System.currentTimeMillis(); - String viewPdfURL = req.getServletPath()+"/view/"+pollingCode; - String entity = entityHTMLMessage("Exporting as PDF...", "The project with " + projectID, true, viewPdfURL); - + final String pollingCode = ucdID + "_" + projectID + "_" + System.currentTimeMillis(); + String viewPdfURL = req.getServletPath() + "/view/" + pollingCode; + + String entity = HTML_Page.entityHTMLMessage("Exporting as PDF...", + "The project with id: " + projectID, true, viewPdfURL); + try { Thread t = new Thread() { @Override public void run() { LOG.info("exportAsPDF called in thread..."); - FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); - map.put(pollingCode, pdfRef); + FileReference pdfRef = null; + FetchPDF fetchPDF = new FetchPDF(pdfRef, pollingCode, 0); + map.put(pollingCode, fetchPDF); + + pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); + fetchPDF.setFileRef(pdfRef); + map.put(pollingCode, fetchPDF); } - + }; t.start(); - }catch (Exception e) { + } catch (Exception e) { // TODO: handle exception } - + return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") .build(); } else { @@ -200,7 +208,7 @@ public class GeoportalExporter { this.getClass(), helpURI); } } - + @GET @Path("/view/{pdfCode}") @Produces({ MediaType.TEXT_PLAIN }) @@ -211,26 +219,33 @@ public class GeoportalExporter { LOG.info("param is: pdfCode: {}", pdfCode); try { - + JsonObject jsonObject = new JsonObject(); - FileReference thePdfURL = map.get(pdfCode); - LOG.info("FileReference at code {} is {}", pdfCode, thePdfURL); + FetchPDF fetchedPDF = map.get(pdfCode); + LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF.getFileRef()); String theURL = null; - if(thePdfURL!=null) - theURL = thePdfURL.getStorageVolatileURL().toString(); - + if (fetchedPDF.getFileRef()==null) { + fetchedPDF.incrementAttempt(); + if(fetchedPDF.getMAX_RETRY()" + "" -// + "" -// + "D4Science Geoportal - Action" + "" + ""; -// -// html += "\"D4Science
"; -// -// html += "
"; -// html += "

" + action + "

"; -// -// if (waiting) { -// html += "\"D4Science
"; -// } -// -// html += "

" + message + "

"; -// html += "
" -// + "" -// + ""; - - - - String newHTML = "\n" - + "\n" - + " \n" - + " \n" - + " \n" - + " \n" - + " D4Science Geoportal - Action\n" - + " \n" - + "\n" - + " "; - - newHTML += "\"D4Science
"; - - newHTML += "
"; - newHTML += "

" + action + "

"; - - if (waiting) { - newHTML += "\"D4Science
"; - } - - newHTML += "

" + message + "

"; - newHTML += "
/body>"; - - return newHTML; - } - } From af05c03cefb02016727d3fcfa44c168d8a05a0ff Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 16:42:17 +0200 Subject: [PATCH 18/83] updated view --- .../resolver/services/GeoportalExporter.java | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 737d58c..0ad14e7 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -31,6 +31,7 @@ import org.gcube.datatransfer.resolver.geoportal.exporter.HTML_Page; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; import org.gcube.datatransfer.resolver.services.exceptions.BadRequestException; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; +import org.gcube.datatransfer.resolver.util.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,10 +111,11 @@ public class GeoportalExporter { if (userAgentName != null) { LOG.info("Serving request as User-Agent {}", userAgentName); final String pollingCode = ucdID + "_" + projectID + "_" + System.currentTimeMillis(); - String viewPdfURL = req.getServletPath() + "/view/" + pollingCode; + String serviceViewPDF_URL = String.format("%s/%s/view/%s", Util.getServerURL(req), + req.getContextPath(), pollingCode); String entity = HTML_Page.entityHTMLMessage("Exporting as PDF...", - "The project with id: " + projectID, true, viewPdfURL); + "The project with id: " + projectID, true, serviceViewPDF_URL); try { Thread t = new Thread() { @@ -123,7 +125,7 @@ public class GeoportalExporter { FileReference pdfRef = null; FetchPDF fetchPDF = new FetchPDF(pdfRef, pollingCode, 0); map.put(pollingCode, fetchPDF); - + pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); fetchPDF.setFileRef(pdfRef); map.put(pollingCode, fetchPDF); @@ -220,22 +222,36 @@ public class GeoportalExporter { try { - JsonObject jsonObject = new JsonObject(); FetchPDF fetchedPDF = map.get(pdfCode); - LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF.getFileRef()); - String theURL = null; - if (fetchedPDF.getFileRef()==null) { - fetchedPDF.incrementAttempt(); - if(fetchedPDF.getMAX_RETRY() Date: Fri, 19 Apr 2024 16:53:21 +0200 Subject: [PATCH 19/83] updated HTML_Pages --- .../geoportal/exporter/HTML_Page.java | 5 ++-- .../resolver/services/GeoportalExporter.java | 26 ++++++++----------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index c4c958d..8bc8042 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -69,7 +69,8 @@ public class HTML_Page { newHTML += "

" + action + "

"; if (waiting) { - newHTML += "\"D4Science
"; + newHTML += "\"D4GNA

"; + newHTML += "\"D4Science
"; } newHTML += "

" + message + "

"; @@ -124,7 +125,7 @@ public class HTML_Page { newHTML += "
"; newHTML += "

" + action + "

"; newHTML += "

" + message + "

"; - newHTML += "
/body>"; + newHTML += ""; return newHTML; } diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 0ad14e7..2418b0b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -190,9 +190,6 @@ public class GeoportalExporter { org.gcube.common.authorization.utils.user.User user = cm.getUser(); LOG.info("Identified caller {} in context {}", user.getUsername(), context); -// Set roles = new HashSet<>(); -// roles.addAll(user.getRoles()); - Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); boolean checked = pdfExporter.checkConfig(); @@ -220,17 +217,16 @@ public class GeoportalExporter { LOG.info(this.getClass().getSimpleName() + " viewPDF - GET starts..."); LOG.info("param is: pdfCode: {}", pdfCode); + FetchPDF fetchedPDF = map.get(pdfCode); + LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); + + if (fetchedPDF == null) { + throw ExceptionManager.notFoundException(req, + GeoportalExporter.class.getSimpleName() + " view with job code " + pdfCode + " not found", + this.getClass(), helpURI); + } + try { - - FetchPDF fetchedPDF = map.get(pdfCode); - LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); - - if (fetchedPDF == null) { - throw ExceptionManager.notFoundException(req, - GeoportalExporter.class.getSimpleName() + " view with task code " + pdfCode + "not found", - this.getClass(), helpURI); - } - String theURL = null; // File PDF is not available @@ -257,9 +253,9 @@ public class GeoportalExporter { return Response.ok(json).build(); } catch (Exception e) { - LOG.error("Error on performing healthcheck", e); + LOG.error("Error on checking job", e); throw ExceptionManager.internalErrorException(req, - "Error when performing " + GeoportalExporter.class.getSimpleName() + " healthcheck", + "Error when checking " + GeoportalExporter.class.getSimpleName() + " job view for " + pdfCode, this.getClass(), helpURI); } From 9071847b482c28ef59f4c14bc6a103dccd7114cf Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 17:02:07 +0200 Subject: [PATCH 20/83] updated HTML_page --- .../resolver/geoportal/exporter/HTML_Page.java | 4 ++-- .../datatransfer/resolver/services/GeoportalExporter.java | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index 8bc8042..7e61d84 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -66,15 +66,15 @@ public class HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; + newHTML += "\"D4GNA

"; newHTML += "

" + action + "

"; if (waiting) { - newHTML += "\"D4GNA

"; newHTML += "\"D4Science
"; } newHTML += "

" + message + "

"; - newHTML += "
/body>"; + newHTML += ""; return newHTML; } diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 2418b0b..17c7815 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -210,7 +210,7 @@ public class GeoportalExporter { @GET @Path("/view/{pdfCode}") - @Produces({ MediaType.TEXT_PLAIN }) + @Produces({ MediaType.TEXT_PLAIN, MediaType.TEXT_HTML}) public Response viewPDF(@Context HttpServletRequest req, @PathParam(PDF_CODE) String pdfCode) throws WebApplicationException { @@ -221,9 +221,8 @@ public class GeoportalExporter { LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); if (fetchedPDF == null) { - throw ExceptionManager.notFoundException(req, - GeoportalExporter.class.getSimpleName() + " view with job code " + pdfCode + " not found", - this.getClass(), helpURI); + return Response.status(Status.NOT_FOUND).entity(HTML_Page.getErrorPage("Job not created", "No job found with id "+pdfCode)) + .type(MediaType.TEXT_HTML).build(); } try { From 8579d6030d98750f2dcda856d7644eda9af86b5b Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 17:11:34 +0200 Subject: [PATCH 21/83] updted HTML_PAGE --- .../resolver/geoportal/exporter/HTML_Page.java | 8 +++++++- .../datatransfer/resolver/services/GeoportalExporter.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index 7e61d84..c681435 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -35,6 +35,12 @@ public class HTML_Page { + " text-align: center;\n" + " }\n" + "\n" + + " #title-geo {\n" + + " font-weight: bold;\n" + + " color: black;\n" + + " font-size: 26px;\n" + + " }\n" + + "\n" + " #message {\n" + " color: gray;\n" + " font-size: 24px;\n" @@ -66,7 +72,7 @@ public class HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; - newHTML += "\"D4GNA

"; + newHTML += "

Geoportal


"; newHTML += "

" + action + "

"; if (waiting) { diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 17c7815..9727b48 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -112,7 +112,7 @@ public class GeoportalExporter { LOG.info("Serving request as User-Agent {}", userAgentName); final String pollingCode = ucdID + "_" + projectID + "_" + System.currentTimeMillis(); String serviceViewPDF_URL = String.format("%s/%s/view/%s", Util.getServerURL(req), - req.getContextPath(), pollingCode); + "geoportal", pollingCode); String entity = HTML_Page.entityHTMLMessage("Exporting as PDF...", "The project with id: " + projectID, true, serviceViewPDF_URL); From 7ee615cedf97a09d0063eb49cb66cbdfe60a7267 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 17:30:08 +0200 Subject: [PATCH 22/83] updated --- .../datatransfer/resolver/geoportal/exporter/HTML_Page.java | 1 + .../gcube/datatransfer/resolver/services/GeoportalExporter.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index c681435..2ed0608 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -55,6 +55,7 @@ public class HTML_Page { + " }\n" + " async function playPDFPoll() {\n" + " const pdf_json = await fetchPDF_URL();\n" + + " console.log(\"response \"+pdf_json);\n" + " if (!(pdf_json.url === null || pdf_json.url === undefined)) {\n" + " window.location.replace(pdf_json.url);\n" + " } else {\n" diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 9727b48..6025a5c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -221,6 +221,7 @@ public class GeoportalExporter { LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); if (fetchedPDF == null) { + LOG.info("returning not found"); return Response.status(Status.NOT_FOUND).entity(HTML_Page.getErrorPage("Job not created", "No job found with id "+pdfCode)) .type(MediaType.TEXT_HTML).build(); } From 69e15b6243bb20d8a3dc53a1889bde68504f7c28 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 19 Apr 2024 17:37:22 +0200 Subject: [PATCH 23/83] updated html page --- .../resolver/geoportal/exporter/HTML_Page.java | 7 +++++++ .../datatransfer/resolver/services/GeoportalExporter.java | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index 2ed0608..074065b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -119,6 +119,12 @@ public class HTML_Page { + " text-align: center;\n" + " }\n" + "\n" + + " #title-geo {\n" + + " font-weight: bold;\n" + + " color: black;\n" + + " font-size: 26px;\n" + + " }\n" + + "\n" + " #message {\n" + " color: gray;\n" + " font-size: 24px;\n" @@ -130,6 +136,7 @@ public class HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; + newHTML += "

Geoportal Exporter


"; newHTML += "

" + action + "

"; newHTML += "

" + message + "

"; newHTML += "
"; diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 6025a5c..3d62c29 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -215,7 +215,7 @@ public class GeoportalExporter { throws WebApplicationException { LOG.info(this.getClass().getSimpleName() + " viewPDF - GET starts..."); - LOG.info("param is: pdfCode: {}", pdfCode); + LOG.info("param "+PDF_CODE+": {}", pdfCode); FetchPDF fetchedPDF = map.get(pdfCode); LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); From e58935d489b323359d0f7ff2b88d8efb5d022d90 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 09:58:40 +0200 Subject: [PATCH 24/83] revisited export method --- .../resolver/services/GeoportalExporter.java | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 3d62c29..b57b739 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -93,30 +93,39 @@ public class GeoportalExporter { checkExportType(req, export_type); + boolean checked = false; + + SecretManager cm = SecretManagerProvider.instance.get(); + final String context = cm.getContext(); + if (context == null) { + throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), + helpURI); + } + + final org.gcube.common.authorization.utils.user.User user = cm.getUser(); + if (user == null) { + throw ExceptionManager.forbiddenException(req, "Cannot determine user", this.getClass(), helpURI); + } + + LOG.info("Identified caller {} in context {}", user.getUsername(), context); + try { - - SecretManager cm = SecretManagerProvider.instance.get(); - String context = cm.getContext(); - if (context == null) { - throw ExceptionManager.forbiddenException(req, "Cannot determine context (the scope)", this.getClass(), - helpURI); - } - org.gcube.common.authorization.utils.user.User user = cm.getUser(); - LOG.info("Identified caller {} in context {}", user.getUsername(), context); - Geoportal_PDF_Exporter pdfExporter = new Geoportal_PDF_Exporter(); - boolean checked = pdfExporter.checkConfig(); + checked = pdfExporter.checkConfig(); + } catch (Exception e) { + LOG.error("Error on performing export", e); + throw ExceptionManager + .internalErrorException(req, + "Error the " + Geoportal_PDF_Exporter.class.getSimpleName() + + " seems to be not configured in the context: " + context, + this.getClass(), helpURI); + } - if (checked) { + if (checked) { + try { if (userAgentName != null) { LOG.info("Serving request as User-Agent {}", userAgentName); final String pollingCode = ucdID + "_" + projectID + "_" + System.currentTimeMillis(); - String serviceViewPDF_URL = String.format("%s/%s/view/%s", Util.getServerURL(req), - "geoportal", pollingCode); - - String entity = HTML_Page.entityHTMLMessage("Exporting as PDF...", - "The project with id: " + projectID, true, serviceViewPDF_URL); - try { Thread t = new Thread() { @Override @@ -127,6 +136,7 @@ public class GeoportalExporter { map.put(pollingCode, fetchPDF); pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); + LOG.info("exportAsPDF setFileRef in thread for code: " + pollingCode); fetchPDF.setFileRef(pdfRef); map.put(pollingCode, fetchPDF); } @@ -134,9 +144,15 @@ public class GeoportalExporter { }; t.start(); } catch (Exception e) { - // TODO: handle exception + LOG.error("Error on performing export in thread", e); } + String serviceViewPDF_URL = String.format("%s/%s/view/%s", Util.getServerURL(req), "geoportal", + pollingCode); + + String entity = HTML_Page.entityHTMLMessage("Exporting as PDF...", + "The project with id: " + projectID, true, serviceViewPDF_URL); + return Response.ok(entity).encoding("UTF-8").header(ConstantsResolver.CONTENT_TYPE, "text/html") .build(); } else { @@ -152,16 +168,16 @@ public class GeoportalExporter { .header("Content-Type", pdfRef.getContentType()); return response.build(); } - } else { - return Response.status(Status.NOT_FOUND) - .entity(GeoportalExporter.class.getSimpleName() + " Config not found in the context " + context) - .type(MediaType.TEXT_PLAIN).build(); + } catch (Exception e) { + LOG.error("Error on performing export", e); + throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", + this.getClass(), helpURI); } - - } catch (Exception e) { - LOG.error("Error on performing export", e); - throw ExceptionManager.internalErrorException(req, "Sorry, error occurred when exporting the project", - this.getClass(), helpURI); + } else { + return Response.status(Status.NOT_FOUND) + .entity(GeoportalExporter.class.getSimpleName() + + "seems to be not configured in the context: " + context) + .type(MediaType.TEXT_PLAIN).build(); } } @@ -210,19 +226,20 @@ public class GeoportalExporter { @GET @Path("/view/{pdfCode}") - @Produces({ MediaType.TEXT_PLAIN, MediaType.TEXT_HTML}) + @Produces({ MediaType.TEXT_PLAIN, MediaType.TEXT_HTML }) public Response viewPDF(@Context HttpServletRequest req, @PathParam(PDF_CODE) String pdfCode) throws WebApplicationException { LOG.info(this.getClass().getSimpleName() + " viewPDF - GET starts..."); - LOG.info("param "+PDF_CODE+": {}", pdfCode); + LOG.info("param " + PDF_CODE + ": {}", pdfCode); FetchPDF fetchedPDF = map.get(pdfCode); LOG.info("FileReference at code {} is {}", pdfCode, fetchedPDF); if (fetchedPDF == null) { LOG.info("returning not found"); - return Response.status(Status.NOT_FOUND).entity(HTML_Page.getErrorPage("Job not created", "No job found with id "+pdfCode)) + return Response.status(Status.NOT_FOUND) + .entity(HTML_Page.getErrorPage("Job not created", "No job found with id " + pdfCode)) .type(MediaType.TEXT_HTML).build(); } From b5ec62be6856a05039efad11ad0b792fb0d48cd0 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 09:59:19 +0200 Subject: [PATCH 25/83] fixed exception --- .../gcube/datatransfer/resolver/services/GeoportalExporter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index b57b739..ad5eab0 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -145,6 +145,7 @@ public class GeoportalExporter { t.start(); } catch (Exception e) { LOG.error("Error on performing export in thread", e); + throw e; } String serviceViewPDF_URL = String.format("%s/%s/view/%s", Util.getServerURL(req), "geoportal", From b35cbb7fd84c07e5cb8d114ceae8a41aaebeb96f Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 10:24:22 +0200 Subject: [PATCH 26/83] moved index called to debug --- .../datatransfer/resolver/requesthandler/RequestHandler.java | 2 +- .../gcube/datatransfer/resolver/services/UriResolverIndex.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java index 21715c1..5cbc07a 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java +++ b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java @@ -204,7 +204,7 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { - log.info(RequestHandler.class.getSimpleName() + " Response called"); + log.debug(RequestHandler.class.getSimpleName() + " Response called"); SecurityTokenProvider.instance.reset(); ScopeProvider.instance.reset(); log.debug("Token and Scope Provider reset called"); diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java index 286bf1a..1d91b9b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverIndex.java @@ -46,7 +46,7 @@ public class UriResolverIndex { String indexFile = "/WEB-INF/jsp/index.jsp"; try { - logger.info(UriResolverIndex.class.getSimpleName() + " called"); + logger.debug(UriResolverIndex.class.getSimpleName() + " called"); String realPath = req.getServletContext().getRealPath(indexFile); return new FileInputStream(new File(realPath)); } catch (Exception e) { From 30a02fe94f04891282b8cdd3b5c334f8da455c2d Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 10:37:14 +0200 Subject: [PATCH 27/83] fixed FetchPDF --- .../datatransfer/resolver/services/GeoportalExporter.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index ad5eab0..e3ac800 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -126,16 +126,14 @@ public class GeoportalExporter { if (userAgentName != null) { LOG.info("Serving request as User-Agent {}", userAgentName); final String pollingCode = ucdID + "_" + projectID + "_" + System.currentTimeMillis(); + final FetchPDF fetchPDF = new FetchPDF(null, pollingCode, 0); + map.put(pollingCode, fetchPDF); try { Thread t = new Thread() { @Override public void run() { LOG.info("exportAsPDF called in thread..."); - FileReference pdfRef = null; - FetchPDF fetchPDF = new FetchPDF(pdfRef, pollingCode, 0); - map.put(pollingCode, fetchPDF); - - pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); + FileReference pdfRef = exportAsPDF(req, ucdID, projectID, null, context, user); LOG.info("exportAsPDF setFileRef in thread for code: " + pollingCode); fetchPDF.setFileRef(pdfRef); map.put(pollingCode, fetchPDF); From 933efabb3fdca5386bf8ffc68ffaa38f99649616 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 10:58:23 +0200 Subject: [PATCH 28/83] updated HTML_Page response --- .../geoportal/exporter/HTML_Page.java | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index 074065b..1bb86d9 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -2,7 +2,6 @@ package org.gcube.datatransfer.resolver.geoportal.exporter; public class HTML_Page { - /** * Sets the HTML message. * @@ -49,21 +48,44 @@ public class HTML_Page { + " \n" + " \n" + " D4Science Geoportal - Action\n" + " \n" @@ -74,6 +96,7 @@ public class HTML_Page { newHTML += "
"; newHTML += "

Geoportal


"; + newHTML += "
"; newHTML += "

" + action + "

"; if (waiting) { @@ -81,7 +104,7 @@ public class HTML_Page { } newHTML += "

" + message + "

"; - newHTML += "
"; + newHTML += "
"; return newHTML; } From 4b0c11136e568dba8077d0d6928e6e2b4c66b2d9 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 11:32:56 +0200 Subject: [PATCH 29/83] fixed html_page --- .../datatransfer/resolver/geoportal/exporter/HTML_Page.java | 4 ++-- .../datatransfer/resolver/requesthandler/RequestHandler.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index 1bb86d9..f9ae4b5 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -50,11 +50,11 @@ public class HTML_Page { + " async function fetchPDF_URL() {\n" + " try {\n" + "\n" - + " const response = await fetch('https://data.dev.d4science.org/geoportal/view/profiledConcessioni_661d2c6f8804530afb90b132_1713774501389');\n" + + " const response = await fetch("+viewPdfURL+");\n" + " console.log(\"polling response\");\n" + " return response.json();\n" + " } catch (error) {\n" - + " cconsole.error(\"polling errro: \" + error);\n" + + " console.error(\"polling errro: \" + error);\n" + " }\n" + " }\n" + " async function playPDFPoll() {\n" diff --git a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java index 5cbc07a..df8aabf 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java +++ b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java @@ -76,7 +76,7 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse */ @Override public void filter(ContainerRequestContext reqContext) throws IOException { - log.info(RequestHandler.class.getSimpleName() + " Request called"); + log.debug(RequestHandler.class.getSimpleName() + " Request called"); setSecretManager(reqContext); if (SecurityTokenProvider.instance.get() == null) @@ -85,7 +85,7 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse if (ScopeProvider.instance.get() == null) ScopeProvider.instance.set(context.getInitParameter(ROOT_SCOPE)); - log.info("Token and Scope Provider set called"); + log.debug("Token and Scope Provider set called"); List listOfPath = UriResolverServices.getInstance().getListOfResourcePath(application.getClasses()); log.debug("The resources are: {}", listOfPath); From e382719f30559feab1d1195e916aa03b82c29ac7 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 22 Apr 2024 12:04:26 +0200 Subject: [PATCH 30/83] fixed entityHTMLMessage --- .../resolver/geoportal/exporter/HTML_Page.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java index f9ae4b5..3aeb464 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/HTML_Page.java @@ -13,7 +13,6 @@ public class HTML_Page { public static String entityHTMLMessage(String action, String message, boolean waiting, String viewPdfURL) { String newHTML = "\n" - + "\n" + " \n" + " \n" + " -D4Science Geoportal - Action - - - - D4Science Logo -
-
-

Exporting as PDF...

- D4Science Geoportal Loading...
-
-

The project with 661d2c6f8804530afb90b132

-
- - \ No newline at end of file diff --git a/src/test/java/gis/RuntimeResourceReader.java b/src/test/java/gis/RuntimeResourceReader.java index 12cf884..ebec3fd 100644 --- a/src/test/java/gis/RuntimeResourceReader.java +++ b/src/test/java/gis/RuntimeResourceReader.java @@ -127,9 +127,9 @@ public class RuntimeResourceReader { // String scope = "/pred4s/preprod/preVRE"; // String scope = "/d4science.research-infrastructures.eu/D4OS/GNA"; -// String scope = "/gcube/devsec/devVRE"; + String scope = "/gcube/devsec/devVRE"; //String scope = "/d4science.research-infrastructures.eu/gCubeApps/Esquiline"; - String scope = "/d4science.research-infrastructures.eu/D4OS/ARIADNEplus_Project"; +// String scope = "/d4science.research-infrastructures.eu/D4OS/ARIADNEplus_Project"; String platformName = "geonetwork"; String category = "Gis"; From 15a18674881d5c53ef8d4fbf243ac979352315ec Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 30 Apr 2024 15:52:01 +0200 Subject: [PATCH 52/83] added gcube-jackson-core to fix `java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/util/JacksonFeature` --- pom.xml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 231c74a..278a7ec 100644 --- a/pom.xml +++ b/pom.xml @@ -137,18 +137,16 @@ ${jersey.version} compile
- - - - - - org.glassfish.jersey.core jersey-server ${jersey.version} compile + + org.gcube.common + gcube-jackson-core + From 5f42473f768a3a5888104248595a306ce70cfda5 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 30 Apr 2024 16:24:51 +0200 Subject: [PATCH 53/83] added profile --- .settings/org.eclipse.wst.common.component | 30 +++++++++++----- pom.xml | 40 ++++++++++++++++++---- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 1d967b7..ec42445 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -27,7 +28,8 @@ - + + @@ -55,7 +57,8 @@ - + + @@ -83,7 +86,8 @@ - + + @@ -111,7 +115,8 @@ - + + @@ -145,7 +150,11 @@ uses - + + uses + + + @@ -173,7 +182,8 @@ - + + @@ -201,7 +211,8 @@ - + + @@ -229,7 +240,8 @@ - + + diff --git a/pom.xml b/pom.xml index 278a7ec..f4e691e 100644 --- a/pom.xml +++ b/pom.xml @@ -19,6 +19,37 @@ https://code-repo.d4science.org/gCubeSystem/${project.artifactId} + + + + + uri-resolver-release-profile + + + Release + + + + 2.4.0 + [2.0.0, 3.0.0-SNAPSHOT) + + + + + uri-resolver-snapshot-profile + + + !Release + + + + 2.5.1-SNAPSHOT + [2.0.0, 3.0.0-SNAPSHOT) + + + + + 2.25.1 1.8 @@ -31,13 +62,14 @@ org.gcube.distribution gcube-smartgears-bom - 2.5.0 + ${gcube-smartgears-bom-version} pom import + @@ -101,7 +133,7 @@ org.gcube.common authorization-utils - [2.0.0, 3.0.0-SNAPSHOT) + ${authorization-utils-range} @@ -143,10 +175,6 @@ ${jersey.version} compile - - org.gcube.common - gcube-jackson-core - From c2ed1583df863be6455f6cca0a3726ee874f3290 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 30 Apr 2024 17:55:36 +0200 Subject: [PATCH 54/83] passed to gcube-jackson --- pom.xml | 7 +++++++ .../gcube/datatransfer/resolver/UriResolverServices.java | 7 ++++--- .../resolver/services/UriResolverResources.java | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f4e691e..4ca2c25 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,7 @@ 2.25.1 + 2.8.8 1.8 1.8 2.14.0 @@ -158,6 +159,12 @@ authorization-client + + + + + + org.gcube.common storagehub-client-library diff --git a/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java b/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java index a4f8051..6ccefae 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java +++ b/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java @@ -11,14 +11,15 @@ import java.util.Set; import javax.ws.rs.Path; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; +import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeFactory; +import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.glassfish.jersey.server.model.Resource; import org.glassfish.jersey.server.model.ResourceMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; + /** diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverResources.java b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverResources.java index 8513ae2..c7749ea 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverResources.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/UriResolverResources.java @@ -14,11 +14,12 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.datatransfer.resolver.UriResolverServices; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; + /** * The UriResolverResources. Show the resources as a JSON From db1018a5c8fb964a6ce32b69532946f7ee886727 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 10:49:52 +0200 Subject: [PATCH 55/83] fixed log --- .../org/gcube/datatransfer/resolver/UriResolverServices.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java b/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java index 6ccefae..6ee7764 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java +++ b/src/main/java/org/gcube/datatransfer/resolver/UriResolverServices.java @@ -193,8 +193,9 @@ public class UriResolverServices { if(listResourcePath.isEmpty()){ log.info("Reference to the List of Resources/Services is empty, creating it..."); readResources(applicationClasses); - log.info("Hard-Coding the resource/s: "+ConstantsResolver.resourcesHardCoded); - listResourcePath.addAll(Arrays.asList(ConstantsResolver.resourcesHardCoded)); + List listHardCodedResources = Arrays.asList(ConstantsResolver.resourcesHardCoded); + log.info("Hard-Coding the resource/s: "+listHardCodedResources); + listResourcePath.addAll(listHardCodedResources); } return listResourcePath; From cb7c78e4913bfa8ababbc41ab74a4c4e4ec55c51 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 11:47:58 +0200 Subject: [PATCH 56/83] fixed code --- .../resolver/geoportal/exporter/Geoportal_HTML_Page.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index bca482f..bdbc715 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -63,7 +63,7 @@ public class Geoportal_HTML_Page { + " try {\n" + " console.log(\"json response \" + response_object);\n" + " if (response_object.state === \"OK\") {\n" - + " if (!(response_object.url === null || response_object.url === undefined)) {\n" + + " if (!(response_object.url === null) && !(response_object.url === undefined)) {\n" + " window.location.replace(response_object.url);\n" + " } else {\n" + " setTimeout(() => {\n" From bc3b6c4c04e313bc280346faf5cce0cbd9a4fd87 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 12:09:23 +0200 Subject: [PATCH 57/83] added "img" as handled path --- .../org/gcube/datatransfer/resolver/ConstantsResolver.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java b/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java index c14b38b..dacc6fb 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java @@ -30,7 +30,8 @@ public class ConstantsResolver { public static final String QUERY_PARAM_CONTENT_TYPE = "contentType"; public static final String QUERY_PARAM_FILE_NAME = "fileName"; - public static final String[] resourcesHardCoded = { "ctlg" }; + //img is the path to refer images from https://data.dev.d4science.org/img/* + public static final String[] resourcesHardCoded = { "ctlg", "img" }; // The default resource candidate to manage the input requests not matching any // resolver services From ebad8120df88c29696262458a7123287aedce228 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 12:35:38 +0200 Subject: [PATCH 58/83] added StaticFileController --- pom.xml | 10 +-- .../resolver/ConstantsResolver.java | 3 +- .../datatransfer/resolver/UriResolver.java | 16 ++--- .../services/StaticFileController.java | 65 ++++++++++++++++++ .../webapp/{img => pub}/loading-gears.gif | Bin 5 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java rename src/main/webapp/{img => pub}/loading-gears.gif (100%) diff --git a/pom.xml b/pom.xml index 4ca2c25..837b09d 100644 --- a/pom.xml +++ b/pom.xml @@ -159,11 +159,11 @@ authorization-client - - - - - + + + + + org.gcube.common diff --git a/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java b/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java index dacc6fb..c14b38b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/ConstantsResolver.java @@ -30,8 +30,7 @@ public class ConstantsResolver { public static final String QUERY_PARAM_CONTENT_TYPE = "contentType"; public static final String QUERY_PARAM_FILE_NAME = "fileName"; - //img is the path to refer images from https://data.dev.d4science.org/img/* - public static final String[] resourcesHardCoded = { "ctlg", "img" }; + public static final String[] resourcesHardCoded = { "ctlg" }; // The default resource candidate to manage the input requests not matching any // resolver services diff --git a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java index 436d6cf..0ed52fa 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/UriResolver.java @@ -14,12 +14,12 @@ import org.glassfish.jersey.server.ResourceConfig; @ManagedBy(UriResolverSmartGearManagerInit.class) public class UriResolver extends ResourceConfig { - public UriResolver() { - // Register all resources present under the package. - packages(CatalogueResolver.class.getPackage().getName(), RequestHandler.class.getPackage().getName(), BackCatalogueResolver.class.getPackage().getName()); - packages(DataMinerInvocation.class.getPackage().getName()); - //register(JspMvcFeature.class); - //property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/jsp"); - } + public UriResolver() { + // Register all resources present under the package. + packages(CatalogueResolver.class.getPackage().getName(), RequestHandler.class.getPackage().getName(), BackCatalogueResolver.class.getPackage().getName()); + packages(DataMinerInvocation.class.getPackage().getName()); +// +// register(JspMvcFeature.class); +// property(JspMvcFeature.TEMPLATE_BASE_PATH, "/WEB-INF/img"); + } } - diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java b/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java new file mode 100644 index 0000000..a4735c2 --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java @@ -0,0 +1,65 @@ +/** + * + */ +package org.gcube.datatransfer.resolver.services; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; + +import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class StaticFileController. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 2, 2024 + */ +@Path("pub") +public class StaticFileController { + + private static Logger logger = LoggerFactory.getLogger(StaticFileController.class); + + /** + * To doc. + * + * @param req the req + * @return the input stream + * @throws WebApplicationException the web application exception + */ + @GET + @Path("/{any: .*}") + public InputStream toFile(@Context HttpServletRequest req) throws WebApplicationException { + logger.info(StaticFileController.class.getSimpleName() + " toFile called"); + + String pathInfo = req.getPathInfo(); + logger.debug("pathInfo {}", pathInfo); + try { + + logger.info("going to {}", pathInfo); + + String realPath = req.getServletContext().getRealPath(pathInfo); + return new FileInputStream(new File(realPath)); + + } catch (Exception e) { + + if (!(e instanceof WebApplicationException)) { + // UNEXPECTED EXCEPTION managing it as WebApplicationException + String error = pathInfo + " not found. Please, contact the support!"; + throw ExceptionManager.internalErrorException(req, error, this.getClass(), null); + } + // ALREADY MANAGED AS WebApplicationException + logger.error("Exception:", e); + throw (WebApplicationException) e; + } + } +} diff --git a/src/main/webapp/img/loading-gears.gif b/src/main/webapp/pub/loading-gears.gif similarity index 100% rename from src/main/webapp/img/loading-gears.gif rename to src/main/webapp/pub/loading-gears.gif From 40f8e239dff9757567ff1f6fa4b1ef3785ca6f82 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 13:53:09 +0200 Subject: [PATCH 59/83] added StaticImageController --- .../services/StaticFileController.java | 65 ---------- .../services/StaticImageController.java | 119 ++++++++++++++++++ .../webapp/{pub => img}/loading-gears.gif | Bin 3 files changed, 119 insertions(+), 65 deletions(-) delete mode 100644 src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java create mode 100644 src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java rename src/main/webapp/{pub => img}/loading-gears.gif (100%) diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java b/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java deleted file mode 100644 index a4735c2..0000000 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StaticFileController.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * - */ -package org.gcube.datatransfer.resolver.services; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.Context; - -import org.gcube.datatransfer.resolver.services.error.ExceptionManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The Class StaticFileController. - * - * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it - * - * May 2, 2024 - */ -@Path("pub") -public class StaticFileController { - - private static Logger logger = LoggerFactory.getLogger(StaticFileController.class); - - /** - * To doc. - * - * @param req the req - * @return the input stream - * @throws WebApplicationException the web application exception - */ - @GET - @Path("/{any: .*}") - public InputStream toFile(@Context HttpServletRequest req) throws WebApplicationException { - logger.info(StaticFileController.class.getSimpleName() + " toFile called"); - - String pathInfo = req.getPathInfo(); - logger.debug("pathInfo {}", pathInfo); - try { - - logger.info("going to {}", pathInfo); - - String realPath = req.getServletContext().getRealPath(pathInfo); - return new FileInputStream(new File(realPath)); - - } catch (Exception e) { - - if (!(e instanceof WebApplicationException)) { - // UNEXPECTED EXCEPTION managing it as WebApplicationException - String error = pathInfo + " not found. Please, contact the support!"; - throw ExceptionManager.internalErrorException(req, error, this.getClass(), null); - } - // ALREADY MANAGED AS WebApplicationException - logger.error("Exception:", e); - throw (WebApplicationException) e; - } - } -} diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java new file mode 100644 index 0000000..9c2e9eb --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java @@ -0,0 +1,119 @@ +/** + * + */ +package org.gcube.datatransfer.resolver.services; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.StreamingOutput; + +import org.apache.commons.io.IOUtils; +import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class StaticImageController. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * May 2, 2024 + */ +@Path("img") +public class StaticImageController { + + private static Logger logger = LoggerFactory.getLogger(StaticImageController.class); + +// /** +// * To doc. +// * +// * @param req the req +// * @return the input stream +// * @throws WebApplicationException the web application exception +// */ +// @GET +// @Path("/{any: .*}") +// @Produces({ "image/png", "image/jpg", "image/gif" }) +// public InputStream toFile(@Context HttpServletRequest req) throws WebApplicationException { +// logger.info(StaticImageController.class.getSimpleName() + " toFile called"); +// +// String pathInfo = req.getPathInfo(); +// logger.debug("pathInfo {}", pathInfo); +// try { +// +// logger.info("going to {}", pathInfo); +// +// String realPath = req.getServletContext().getRealPath(pathInfo); +// return new FileInputStream(new File(realPath)); +// +// } catch (Exception e) { +// +// if (!(e instanceof WebApplicationException)) { +// // UNEXPECTED EXCEPTION managing it as WebApplicationException +// String error = pathInfo + " not found. Please, contact the support!"; +// throw ExceptionManager.internalErrorException(req, error, this.getClass(), null); +// } +// // ALREADY MANAGED AS WebApplicationException +// logger.error("Exception:", e); +// throw (WebApplicationException) e; +// } +// } +// + + /** + * To file out. + * + * @param req the req + * @return the streaming output + * @throws WebApplicationException the web application exception + */ + @GET + @Path("/{any: .*}") + @Produces({ "image/png", "image/jpg", "image/gif" }) + public StreamingOutput toFileOut(@Context HttpServletRequest req) throws WebApplicationException { + logger.info(StaticImageController.class.getSimpleName() + " toFileOut called"); + String pathInfo = req.getPathInfo(); + logger.debug("pathInfo {}", pathInfo); + try { + final String realPath = req.getServletContext().getRealPath(pathInfo); + logger.info("going to {}", pathInfo); + return new StreamingOutput() { + @Override + public void write(OutputStream os) throws IOException, WebApplicationException { + FileInputStream fileIS = null; + try { + fileIS = new FileInputStream(new File(realPath)); + IOUtils.copy(new FileInputStream(new File(realPath)), os); + } catch (Exception e) { + try { + fileIS.close(); + } catch (Exception e2) { + + } + } + } + }; + + } catch (Exception e) { + + if (!(e instanceof WebApplicationException)) { + // UNEXPECTED EXCEPTION managing it as WebApplicationException + String error = pathInfo + " not found. Please, contact the support!"; + throw ExceptionManager.internalErrorException(req, error, this.getClass(), null); + } + // ALREADY MANAGED AS WebApplicationException + logger.error("Exception:", e); + throw (WebApplicationException) e; + } + } +} diff --git a/src/main/webapp/pub/loading-gears.gif b/src/main/webapp/img/loading-gears.gif similarity index 100% rename from src/main/webapp/pub/loading-gears.gif rename to src/main/webapp/img/loading-gears.gif From 756694a0293b2a3de55d2447467b26188185c592 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 14:08:06 +0200 Subject: [PATCH 60/83] added static icons to html page --- .../geoportal/exporter/Geoportal_HTML_Page.java | 3 ++- .../services/StaticImageController.java | 5 +++-- src/main/webapp/img/icon-globe.gif | Bin 0 -> 29035 bytes 3 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/main/webapp/img/icon-globe.gif diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index bdbc715..fba183e 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -95,12 +95,13 @@ public class Geoportal_HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; + newHTML += "\"Geoportal
"; newHTML += "

Geoportal


"; newHTML += "
"; newHTML += "

" + action + "

"; if (waiting) { - newHTML += "\"D4Science
"; + newHTML += "\"D4Science
"; } newHTML += "

" + message + "

"; diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java index 9c2e9eb..90b0297 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java @@ -93,10 +93,11 @@ public class StaticImageController { FileInputStream fileIS = null; try { fileIS = new FileInputStream(new File(realPath)); - IOUtils.copy(new FileInputStream(new File(realPath)), os); + IOUtils.copy(fileIS, os); } catch (Exception e) { try { - fileIS.close(); + if(fileIS!=null) + fileIS.close(); } catch (Exception e2) { } diff --git a/src/main/webapp/img/icon-globe.gif b/src/main/webapp/img/icon-globe.gif new file mode 100644 index 0000000000000000000000000000000000000000..db68dbf981b603cf20400d7630bf78b26517c039 GIT binary patch literal 29035 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 J_8)(k`yVVcaXJ71 literal 0 HcmV?d00001 From f2f3573451e1a6f8555d251ccd32f253beb04327 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:01:40 +0200 Subject: [PATCH 61/83] updated HTML page --- .../geoportal/exporter/Geoportal_HTML_Page.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index fba183e..10595fc 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -61,7 +61,7 @@ public class Geoportal_HTML_Page { + " async function playPDFPoll() {\n" + " const response_object = await fetchPDF_URL();\n" + " try {\n" - + " console.log(\"json response \" + response_object);\n" + + " console.log(\"json response \" + JSON.stringify(error_msg));\n" + " if (response_object.state === \"OK\") {\n" + " if (!(response_object.url === null) && !(response_object.url === undefined)) {\n" + " window.location.replace(response_object.url);\n" @@ -71,7 +71,7 @@ public class Geoportal_HTML_Page { + " }, 1000);\n" + " }\n" + " } else {\n" - + " showError(response_object.messagge);\n" + + " showError(response_object.message);\n" + " }\n" + " } catch (error) {\n" + " console.log(\"no json response \" + response_object);\n" @@ -86,6 +86,10 @@ public class Geoportal_HTML_Page { + " inner_div.innerHTML = error_msg;\n" + " }\n" + "\n" + + " document.onload = function(){\n" + + " document.getElementById('pic1').src= window.location.href + \"img/icon-globe.gif\";\n" + + " document.getElementById('pic2').src= window.location.href + \"img/loading-gears.gif\";\n" + + " }\n" + " \n" + " D4Science Geoportal - Action\n" + " \n" @@ -95,13 +99,13 @@ public class Geoportal_HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; - newHTML += "\"Geoportal
"; + newHTML += "\"Geoportal
"; newHTML += "

Geoportal


"; newHTML += "
"; newHTML += "

" + action + "

"; if (waiting) { - newHTML += "\"D4Science
"; + newHTML += "\"D4Science
"; } newHTML += "

" + message + "

"; From a93e690f0cc4be150d85e7288bf4ffa02b2b7313 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:12:03 +0200 Subject: [PATCH 62/83] updated HTML Page --- .../geoportal/exporter/Geoportal_HTML_Page.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index 10595fc..b3fdb74 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -61,7 +61,7 @@ public class Geoportal_HTML_Page { + " async function playPDFPoll() {\n" + " const response_object = await fetchPDF_URL();\n" + " try {\n" - + " console.log(\"json response \" + JSON.stringify(error_msg));\n" + + " console.log(\"json response \" + error_msg);\n" + " if (response_object.state === \"OK\") {\n" + " if (!(response_object.url === null) && !(response_object.url === undefined)) {\n" + " window.location.replace(response_object.url);\n" @@ -86,15 +86,21 @@ public class Geoportal_HTML_Page { + " inner_div.innerHTML = error_msg;\n" + " }\n" + "\n" - + " document.onload = function(){\n" - + " document.getElementById('pic1').src= window.location.href + \"img/icon-globe.gif\";\n" - + " document.getElementById('pic2').src= window.location.href + \"img/loading-gears.gif\";\n" + + " function setImages() {\n" + + " console.log(\"json setImages \");\n" + + " document.getElementById('pic1').src = window.location.href + \"img/icon-globe.gif\";\n" + + " document.getElementById('pic2').src = window.location.href + \"img/loading-gears.gif\";\n" + + " }\n" + + " \n" + + " function initPage(){\n" + + " playPDFPoll();\n" + + " setImages();\n" + " }\n" + " \n" + " D4Science Geoportal - Action\n" + " \n" + "\n" - + " "; + + " "; newHTML += "\"D4Science
"; From fee9892ff08cc1391040d5412fa8faadde7c820f Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:26:52 +0200 Subject: [PATCH 63/83] updated pom --- pom.xml | 16 +++++++++------- .../resolver/services/GeoportalExporter.java | 1 - .../resolver/services/StaticImageController.java | 1 - 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 837b09d..7f5f2fd 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,8 @@ 2.25.1 - 2.8.8 + + 2.9 1.8 1.8 2.14.0 @@ -159,12 +160,6 @@ authorization-client - - - - - - org.gcube.common storagehub-client-library @@ -183,6 +178,13 @@ compile + + com.fasterxml.jackson.core + jackson-databind + [${jackson.version.eclude},) + provided + + net.bull.javamelody diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 3d0a46d..7e54809 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -1,7 +1,6 @@ package org.gcube.datatransfer.resolver.services; import java.io.InputStream; -import java.net.URISyntaxException; import java.util.LinkedHashMap; import javax.annotation.Nullable; diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java index 90b0297..9418993 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StaticImageController.java @@ -6,7 +6,6 @@ package org.gcube.datatransfer.resolver.services; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import javax.servlet.http.HttpServletRequest; From 3a3ba9b43f0c0681e233e525560252def1ebe567 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:31:26 +0200 Subject: [PATCH 64/83] updated pom --- pom.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 7f5f2fd..6243717 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ 2.25.1 - + 2.8.8 2.9 1.8 1.8 @@ -178,12 +178,12 @@ compile - - com.fasterxml.jackson.core - jackson-databind - [${jackson.version.eclude},) - provided - + + + + + + From d654df3f2f3bcf7e21ec7664d0fdadd5d0922fb5 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:42:50 +0200 Subject: [PATCH 65/83] updated HTML page and pom --- pom.xml | 18 +++++++++++------- .../exporter/Geoportal_HTML_Page.java | 16 +++------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 6243717..380ad4c 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ 2.25.1 2.8.8 - 2.9 + 2.12 1.8 1.8 2.14.0 @@ -178,12 +178,16 @@ compile - - - - - - + + + + com.fasterxml.jackson.core + jackson-databind + [${jackson.version.eclude},) + provided + + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index b3fdb74..38c2f7c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -86,32 +86,22 @@ public class Geoportal_HTML_Page { + " inner_div.innerHTML = error_msg;\n" + " }\n" + "\n" - + " function setImages() {\n" - + " console.log(\"json setImages \");\n" - + " document.getElementById('pic1').src = window.location.href + \"img/icon-globe.gif\";\n" - + " document.getElementById('pic2').src = window.location.href + \"img/loading-gears.gif\";\n" - + " }\n" - + " \n" - + " function initPage(){\n" - + " playPDFPoll();\n" - + " setImages();\n" - + " }\n" + " \n" + " D4Science Geoportal - Action\n" + " \n" + "\n" - + " "; + + " "; newHTML += "\"D4Science
"; newHTML += "
"; - newHTML += "\"Geoportal
"; + newHTML += "\"Geoportal
"; newHTML += "

Geoportal


"; newHTML += "
"; newHTML += "

" + action + "

"; if (waiting) { - newHTML += "\"D4Science
"; + newHTML += "\"D4Science
"; } newHTML += "

" + message + "

"; From 20d17efa3aec738b183e8bb8ad7446d3b67b06aa Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 15:55:59 +0200 Subject: [PATCH 66/83] fixing jackson-databind at 2.8.8 to fix temporary the issue #27377 --- pom.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 380ad4c..4afbea6 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,6 @@ 2.25.1 2.8.8 - 2.12 1.8 1.8 2.14.0 @@ -183,8 +182,7 @@ com.fasterxml.jackson.core jackson-databind - [${jackson.version.eclude},) - provided + ${jackson.version} From 6341a804042e5be1d2de872ffd66d62620f862bf Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 16:08:03 +0200 Subject: [PATCH 67/83] fixed HTML page --- .../resolver/geoportal/exporter/Geoportal_HTML_Page.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index 38c2f7c..26d8b29 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -61,7 +61,7 @@ public class Geoportal_HTML_Page { + " async function playPDFPoll() {\n" + " const response_object = await fetchPDF_URL();\n" + " try {\n" - + " console.log(\"json response \" + error_msg);\n" + + " console.log(\"json response \" + response_object);\n" + " if (response_object.state === \"OK\") {\n" + " if (!(response_object.url === null) && !(response_object.url === undefined)) {\n" + " window.location.replace(response_object.url);\n" From 7fa079901dc4c999628308896e2a906bf8394558 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 16:23:20 +0200 Subject: [PATCH 68/83] updated geoportal logo --- .../resolver/geoportal/exporter/Geoportal_HTML_Page.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index 26d8b29..c51305b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -12,6 +12,7 @@ public class Geoportal_HTML_Page { */ public static String entityHTMLMessage(String action, String message, boolean waiting, String viewPdfURL) { + //NB the images are located at https://data.d4science.net/qLix String newHTML = "\n" + "\n" + " \n" @@ -95,7 +96,7 @@ public class Geoportal_HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; - newHTML += "\"Geoportal
"; + newHTML += "\"Geoportal
"; newHTML += "

Geoportal


"; newHTML += "
"; newHTML += "

" + action + "

"; From cc1baa4ccbe5d524eee1dbca345e9cf5e3a184f4 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 16:27:18 +0200 Subject: [PATCH 69/83] updated HTML page --- .../resolver/geoportal/exporter/Geoportal_HTML_Page.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index c51305b..a2d1e8c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -96,7 +96,6 @@ public class Geoportal_HTML_Page { newHTML += "\"D4Science
"; newHTML += "
"; - newHTML += "\"Geoportal
"; newHTML += "

Geoportal


"; newHTML += "
"; newHTML += "

" + action + "

"; From 0970f1d59fac90f4a4a1f91ea6b55a0e80345d6d Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 2 May 2024 16:45:43 +0200 Subject: [PATCH 70/83] updated gcube-smartgears-bom-version at 2.5.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4afbea6..8d9c51b 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ - 2.4.0 + 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) @@ -43,7 +43,7 @@ - 2.5.1-SNAPSHOT + 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) From 3440ab42d6df419f16ed987f832647e9162ef33d Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 12:45:26 +0200 Subject: [PATCH 71/83] commented explicit dependency for jackson-databind due to #27377 --- .settings/org.eclipse.wst.common.component | 30 +++++++++++++++------- pom.xml | 10 ++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index ec42445..f134373 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -28,7 +29,8 @@ - + + @@ -57,7 +59,8 @@ - + + @@ -86,7 +89,8 @@ - + + @@ -115,7 +119,8 @@ - + + @@ -150,10 +155,14 @@ uses + + uses + uses - + + @@ -182,7 +191,8 @@ - + + @@ -211,7 +221,8 @@ - + + @@ -240,7 +251,8 @@ - + + diff --git a/pom.xml b/pom.xml index 8d9c51b..5462a74 100644 --- a/pom.xml +++ b/pom.xml @@ -179,11 +179,11 @@ - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - + + + + + From eb56afabd6c943db346bbc3e866ac16b3f8a400e Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 15:53:58 +0200 Subject: [PATCH 72/83] fixed typo --- .settings/org.eclipse.wst.common.component | 3 --- .../datatransfer/resolver/services/CatalogueResolver.java | 2 +- .../datatransfer/resolver/services/GeoportalExporter.java | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index f134373..9857039 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -152,9 +152,6 @@ uses - - uses - uses diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java index 06baae6..bb13a60 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java @@ -247,7 +247,7 @@ public class CatalogueResolver { scopeBean = LoadingMapOfScopeCache.get(scopeName); } catch (ExecutionException | InvalidCacheLoadException e) { logger.error( - "Error on getting the fullscope from cache for scopeName {}. Tryng to load it from DetachedRE", + "Error on getting the fullscope from cache for scopeName {}. Trying to load it from DetachedRE", scopeName); boolean isScopeDetached = false; diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java index 7e54809..f29227c 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeoportalExporter.java @@ -337,7 +337,7 @@ public class GeoportalExporter { messagge = "Attempt #" + attempt; } else { state = "ERROR"; - messagge = "Sorry, an error occurred tryng to create the PDF. Max retries reached"; + messagge = "Sorry, an error occurred trying to create the PDF. Max retries reached"; theJson.setState(state); } // updating map status From 4ccfc787910ea4a30dd9180d30ec8164981aa3ab Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 7 May 2024 11:59:06 +0200 Subject: [PATCH 73/83] using javax.ws.rs.core.Response.Status instead of apache.http.HttpStatus --- .settings/org.eclipse.wst.common.component | 30 +++++++++++-------- pom.xml | 6 ++++ .../resolver/services/StorageIDResolver.java | 6 ++-- src/test/java/gis/GeonetworkQueryTest.java | 1 - src/test/java/gis/LayersMatchingGN_CKAN.java | 9 +++--- src/test/java/gis/RuntimeResourceReader.java | 2 +- src/test/java/gis/SE_Harvester_from_IS.java | 10 ++----- src/test/java/rest/TestResolvers.java | 14 +++++---- 8 files changed, 42 insertions(+), 36 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 9857039..8fa0242 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -29,7 +30,8 @@ - + + @@ -59,7 +61,8 @@ - + + @@ -89,7 +92,8 @@ - + + @@ -119,7 +123,8 @@ - + + @@ -149,16 +154,14 @@ - - uses - uses uses - + + @@ -188,7 +191,8 @@ - + + @@ -218,7 +222,8 @@ - + + @@ -248,7 +253,8 @@ - + + diff --git a/pom.xml b/pom.xml index 5462a74..e6aade9 100644 --- a/pom.xml +++ b/pom.xml @@ -295,6 +295,12 @@ compile + + eu.trentorise.opendata + jackan + 0.4.2 + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java index edc1fae..2b57600 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java @@ -14,10 +14,10 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpStatus; import org.gcube.contentmanagement.blobstorage.resource.MyFile; import org.gcube.contentmanagement.blobstorage.service.IClient; import org.gcube.contentmanager.storageclient.wrapper.AccessType; @@ -222,7 +222,7 @@ public class StorageIDResolver { //THIS IS FOR HPROXY CHECK if(hproxycheck){ LOG.trace("returning status 200 for Hproxy check"); - ResponseBuilder response = Response.status(HttpStatus.SC_OK); + ResponseBuilder response = Response.status(Status.OK); return response.build(); } @@ -313,7 +313,7 @@ public class StorageIDResolver { if(c>0){ LOG.info("at least 1 byte read, returning status 200"); IOUtils.closeQuietly(streamToWrite); - response = Response.status(HttpStatus.SC_OK); + response = Response.status(Status.OK); }else throw ExceptionManager.notFoundException(httpRequest, "The file with id: "+storageId+" is missing in the storage", StorageIDResolver.class, help); } diff --git a/src/test/java/gis/GeonetworkQueryTest.java b/src/test/java/gis/GeonetworkQueryTest.java index 08d3dda..6ed577f 100644 --- a/src/test/java/gis/GeonetworkQueryTest.java +++ b/src/test/java/gis/GeonetworkQueryTest.java @@ -12,7 +12,6 @@ import org.gcube.spatial.data.geonetwork.LoginLevel; import org.gcube.spatial.data.geonetwork.configuration.Configuration; import org.gcube.spatial.data.geonetwork.model.Account; import org.gcube.spatial.data.geonetwork.model.Account.Type; -import org.junit.Test; import it.geosolutions.geonetwork.util.GNSearchRequest; import it.geosolutions.geonetwork.util.GNSearchResponse; diff --git a/src/test/java/gis/LayersMatchingGN_CKAN.java b/src/test/java/gis/LayersMatchingGN_CKAN.java index 29b57c3..d97b17b 100644 --- a/src/test/java/gis/LayersMatchingGN_CKAN.java +++ b/src/test/java/gis/LayersMatchingGN_CKAN.java @@ -3,10 +3,6 @@ */ package gis; -import it.geosolutions.geonetwork.util.GNSearchRequest; -import it.geosolutions.geonetwork.util.GNSearchResponse; -import resources.GetAllInfrastructureScopes; - import java.io.BufferedWriter; import java.io.FileWriter; import java.io.PrintWriter; @@ -18,7 +14,10 @@ import org.gcube.common.scope.api.ScopeProvider; import org.gcube.spatial.data.geonetwork.GeoNetwork; import org.gcube.spatial.data.geonetwork.GeoNetworkPublisher; import org.gcube.spatial.data.geonetwork.LoginLevel; -import org.junit.Test; + +import it.geosolutions.geonetwork.util.GNSearchRequest; +import it.geosolutions.geonetwork.util.GNSearchResponse; +import resources.GetAllInfrastructureScopes; /** diff --git a/src/test/java/gis/RuntimeResourceReader.java b/src/test/java/gis/RuntimeResourceReader.java index ebec3fd..9085eef 100644 --- a/src/test/java/gis/RuntimeResourceReader.java +++ b/src/test/java/gis/RuntimeResourceReader.java @@ -7,9 +7,9 @@ import java.util.ArrayList; import java.util.List; import org.gcube.common.encryption.StringEncrypter; -import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; +import org.gcube.common.scope.api.ScopeProvider; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.slf4j.Logger; diff --git a/src/test/java/gis/SE_Harvester_from_IS.java b/src/test/java/gis/SE_Harvester_from_IS.java index 74434d4..99d5476 100644 --- a/src/test/java/gis/SE_Harvester_from_IS.java +++ b/src/test/java/gis/SE_Harvester_from_IS.java @@ -3,10 +3,6 @@ */ package gis; -import it.geosolutions.geonetwork.util.GNSearchRequest; -import it.geosolutions.geonetwork.util.GNSearchResponse; -import resources.GetAllInfrastructureScopes; - import java.io.BufferedWriter; import java.io.FileWriter; import java.io.PrintWriter; @@ -16,11 +12,9 @@ import java.util.List; import java.util.Map; import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint; -import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.spatial.data.geonetwork.GeoNetwork; -import org.gcube.spatial.data.geonetwork.GeoNetworkPublisher; import org.gcube.spatial.data.geonetwork.LoginLevel; -import org.junit.Test; + +import resources.GetAllInfrastructureScopes; /** * diff --git a/src/test/java/rest/TestResolvers.java b/src/test/java/rest/TestResolvers.java index f5a4ac5..77387f9 100644 --- a/src/test/java/rest/TestResolvers.java +++ b/src/test/java/rest/TestResolvers.java @@ -15,11 +15,13 @@ import java.nio.file.StandardCopyOption; import java.util.List; import java.util.Map; +import javax.ws.rs.core.Response.Status; + import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpStatus; import org.gcube.datatransfer.resolver.applicationprofile.ApplicationProfileReader; import org.gcube.datatransfer.resolver.util.HTTPCallsUtils; +import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +61,7 @@ public class TestResolvers { System.out.println("header fields: "+con.getHeaderFields()); String fileName = getFilename(con.getHeaderFields()); System.out.println("Response status is: "+status); - if(status==HttpStatus.SC_OK){ + if(status==Status.OK.getStatusCode()){ Path target = Files.createTempFile(FilenameUtils.getBaseName(fileName), "."+FilenameUtils.getExtension(fileName)); try (InputStream in = con.getInputStream()) { Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); @@ -103,7 +105,7 @@ public class TestResolvers { //printHeaders(con.getHeaderFields()); String fileName = getFilename(con.getHeaderFields()); System.out.println("Response status is: "+status); - if(status==HttpStatus.SC_OK){ + if(status==Status.OK.getStatusCode()){ Path target = Files.createTempFile(FilenameUtils.getBaseName(fileName), "."+FilenameUtils.getExtension(fileName)); try (InputStream in = con.getInputStream()) { Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING); @@ -146,7 +148,7 @@ public class TestResolvers { status = con.getResponseCode(); //printHeaders(con.getHeaderFields()); System.out.println("Response status is: "+status); - if(status==HttpStatus.SC_OK){ + if(status==Status.OK.getStatusCode()){ System.out.println("\nFile to URL: "+url +" is reachable via doHEAD"); System.out.println(IOUtils.toString(con.getInputStream())); }else{ @@ -187,7 +189,7 @@ public class TestResolvers { con.connect(); status = con.getResponseCode(); System.out.println("Response status is: "+status); - if(status==HttpStatus.SC_OK){ + if(status==Status.OK.getStatusCode()){ System.out.println("Response: \n"+getContentReponse(con.getInputStream())); }else{ System.out.println("\nError on resolving the Catalogue URL: "+toURL); @@ -323,7 +325,7 @@ public class TestResolvers { status = con.getResponseCode(); //printHeaders(con.getHeaderFields()); System.out.println("Response status is: "+status); - if(status==HttpStatus.SC_SEE_OTHER){ + if(status==Status.SEE_OTHER.getStatusCode()){ System.out.println("\nResponse to URL: "+url); System.out.println(IOUtils.toString(con.getInputStream())); }else{ From eef40958421341c2b42554a8d6945ed824481991 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 10:36:26 +0200 Subject: [PATCH 74/83] updated the pom --- pom.xml | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pom.xml b/pom.xml index e6aade9..31bd8fe 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,8 @@ 2.25.1 - 2.8.8 + + 2.8.4 1.8 1.8 2.14.0 @@ -177,15 +178,24 @@ compile - + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + - - - - - + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - @@ -234,17 +244,11 @@ compile - - org.projectlombok - lombok - 1.14.8 - - javax.xml.bind jaxb-api - 2.3.0 + provided @@ -252,7 +256,7 @@ org.projectlombok lombok - 1.18.4 + provided From 097a589af512eb6405681c32c86e0ccadb3e7eb3 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 10:55:55 +0200 Subject: [PATCH 75/83] specified jackson.version at 2.8.11 --- pom.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 31bd8fe..7644414 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ + 2.4.0 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) @@ -43,7 +44,8 @@ - 2.5.0 + 2.4.1-SNAPSHOT + 2.5.1-SNAPSHOT [2.0.0, 3.0.0-SNAPSHOT) @@ -53,7 +55,7 @@ 2.25.1 - 2.8.4 + 2.8.11 1.8 1.8 2.14.0 @@ -61,6 +63,13 @@ + + org.gcube.distribution + gcube-bom + ${gcube-bom} + pom + import + org.gcube.distribution gcube-smartgears-bom From acd91be204ff778551b15d007cba698f30bfa4da Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 11:02:09 +0200 Subject: [PATCH 76/83] specified jackson.version at 2.8.4 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7644414..709b494 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ 2.25.1 - 2.8.11 + 2.8.4 1.8 1.8 2.14.0 From 8dcb28b49e44523b6fd5c6364654e56e9d730452 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 11:09:15 +0200 Subject: [PATCH 77/83] commented bom version --- .settings/org.eclipse.wst.common.component | 33 ++++++++++++---------- pom.xml | 20 ++++++------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 8fa0242..22dab16 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -30,7 +31,8 @@ - + + @@ -61,7 +63,8 @@ - + + @@ -92,7 +95,8 @@ - + + @@ -123,7 +127,8 @@ - + + @@ -154,13 +159,8 @@ - - uses - - - uses - - + + @@ -191,7 +191,8 @@ - + + @@ -222,7 +223,8 @@ - + + @@ -253,7 +255,8 @@ - + + diff --git a/pom.xml b/pom.xml index 709b494..bb2b9a9 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ - 2.4.0 + 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) @@ -44,7 +44,7 @@ - 2.4.1-SNAPSHOT + 2.5.1-SNAPSHOT [2.0.0, 3.0.0-SNAPSHOT) @@ -54,7 +54,7 @@ 2.25.1 - + 2.8.4 1.8 1.8 @@ -63,13 +63,13 @@ - - org.gcube.distribution - gcube-bom - ${gcube-bom} - pom - import - + + + + + + + org.gcube.distribution gcube-smartgears-bom From 494e32bac5476103a9af6d5dee8ce002cc8d50c2 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 11:59:16 +0200 Subject: [PATCH 78/83] Migrated to `catalogue-util-library` [#27423] --- .settings/org.eclipse.wst.common.component | 27 ++++++++++++------- CHANGELOG.md | 1 + pom.xml | 25 ++++++++++------- .../CatalogueServiceEndpointReader.java | 2 +- .../CkanCatalogueConfigurationsReader.java | 11 ++++---- .../GatewayCKANCatalogueReference.java | 2 +- .../resolver/services/CatalogueResolver.java | 5 ++-- 7 files changed, 44 insertions(+), 29 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 22dab16..254e1fa 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -31,7 +32,8 @@ - + + @@ -63,7 +65,8 @@ - + + @@ -95,7 +98,8 @@ - + + @@ -127,7 +131,8 @@ - + + @@ -159,7 +164,8 @@ - + + @@ -191,7 +197,8 @@ - + + @@ -223,7 +230,8 @@ - + + @@ -255,7 +263,8 @@ - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 437cf13..476a997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - GeoPortal-Resolver enhancement: implemented share link towards Geoportal Data-Entry facility [#27135] - Added Geoportal Exporter as PDF [#27274] +- Migrated to `catalogue-util-library` [#27423] ## [v2.9.0] diff --git a/pom.xml b/pom.xml index bb2b9a9..2480c66 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ - 2.5.1-SNAPSHOT + 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) @@ -301,18 +301,25 @@ compile + + + + + + + - org.gcube.data-catalogue - ckan-util-library - [2.0.0, 3.0.0-SNAPSHOT) + org.gcube.datacatalogue + catalogue-util-library + [1.0.0, 2.0.0-SNAPSHOT) compile - - eu.trentorise.opendata - jackan - 0.4.2 - + + + + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/endpoint/CatalogueServiceEndpointReader.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/endpoint/CatalogueServiceEndpointReader.java index 9b81eb2..759cbef 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/endpoint/CatalogueServiceEndpointReader.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/endpoint/CatalogueServiceEndpointReader.java @@ -12,7 +12,7 @@ import java.util.Map; import org.gcube.common.resources.gcore.ServiceEndpoint; import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueImpl; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.slf4j.Logger; diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanCatalogueConfigurationsReader.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanCatalogueConfigurationsReader.java index eed1d99..f6930f3 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanCatalogueConfigurationsReader.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanCatalogueConfigurationsReader.java @@ -18,8 +18,11 @@ import javax.xml.parsers.DocumentBuilderFactory; import org.gcube.common.resources.gcore.utils.XPathHelper; import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueImpl; -import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; +import org.gcube.datacatalogue.utillibrary.jackan.CkanClient; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueImpl; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.exceptions.CkanException; import org.gcube.datatransfer.resolver.applicationprofile.ApplicationProfileNotFoundException; import org.gcube.datatransfer.resolver.catalogue.endpoint.CatalogueServiceEndpointReader; import org.gcube.resources.discovery.client.api.DiscoveryClient; @@ -30,10 +33,6 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Node; import org.xml.sax.InputSource; -import eu.trentorise.opendata.jackan.CkanClient; -import eu.trentorise.opendata.jackan.exceptions.CkanException; -import eu.trentorise.opendata.jackan.model.CkanDataset; - /** * The Class CkanCatalogueConfigurationsReader. diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/GatewayCKANCatalogueReference.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/GatewayCKANCatalogueReference.java index 8bc4e8d..37f647a 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/GatewayCKANCatalogueReference.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/GatewayCKANCatalogueReference.java @@ -7,7 +7,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; -import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java index bb13a60..e676900 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/CatalogueResolver.java @@ -22,7 +22,8 @@ import org.apache.commons.codec.binary.Base64; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; -import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; +import org.gcube.datacatalogue.utillibrary.server.DataCatalogueRunningCluster.ACCESS_LEVEL_TO_CATALOGUE_PORTLET; +import org.gcube.datacatalogue.utillibrary.shared.jackan.model.CkanDataset; import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.caches.LoadingMapOfDetachedVRE; import org.gcube.datatransfer.resolver.caches.LoadingMapOfScopeCache; @@ -42,8 +43,6 @@ import org.slf4j.LoggerFactory; import com.google.common.cache.CacheLoader.InvalidCacheLoadException; -import eu.trentorise.opendata.jackan.model.CkanDataset; - /** * The CatalogueResolver is able to get/resolve a link to a "Catalogue Entity" * stored in one of the D4Science Catalogue's instances. A Catalogue Entity is From d7e751928f8ae52524d25550872eb49811d9dfd0 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 17:27:21 +0200 Subject: [PATCH 79/83] Using `gcube-smartgears-bom-version` v2.5.1-SNAPSHOT in DEV Profile --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2480c66..a65f2c2 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ - 2.5.0 + 2.5.1-SNAPSHOT [2.0.0, 3.0.0-SNAPSHOT) @@ -54,7 +54,7 @@ 2.25.1 - + 2.8.4 1.8 1.8 From 4ce40302b659aa0bbbe813653723f939c238d6c1 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 17:38:25 +0200 Subject: [PATCH 80/83] DEV profile reverted gcube-smartgears-bom-version at 2.5.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a65f2c2..7779b6a 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ - 2.5.1-SNAPSHOT + 2.5.0 [2.0.0, 3.0.0-SNAPSHOT) From 213cc24fb6e32a4725827933dbc6bcd42946db95 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 10 May 2024 11:40:20 +0200 Subject: [PATCH 81/83] formatted --- .settings/org.eclipse.wst.common.component | 39 ++++++++++++++----- .../exporter/Geoportal_HTML_Page.java | 1 - 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 254e1fa..4ce2404 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,7 @@ - + + + @@ -32,7 +34,9 @@ - + + + @@ -65,7 +69,9 @@ - + + + @@ -98,7 +104,9 @@ - + + + @@ -131,7 +139,9 @@ - + + + @@ -164,7 +174,12 @@ - + + uses + + + + @@ -197,7 +212,9 @@ - + + + @@ -230,7 +247,9 @@ - + + + @@ -263,7 +282,9 @@ - + + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java index a2d1e8c..909d38f 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java +++ b/src/main/java/org/gcube/datatransfer/resolver/geoportal/exporter/Geoportal_HTML_Page.java @@ -167,6 +167,5 @@ public class Geoportal_HTML_Page { return newHTML; } - } From 523ae7c6408d745f1684c00652d79a85a68ececd Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Thu, 20 Jun 2024 17:51:23 +0200 Subject: [PATCH 82/83] updated typo --- .settings/org.eclipse.wst.common.component | 86 ++++++++++++++++--- .../resolver/services/GeonetworkResolver.java | 2 +- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 4ce2404..7098efc 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,12 @@ - + + + + + + + + @@ -34,7 +41,14 @@ - + + + + + + + + @@ -69,7 +83,14 @@ - + + + + + + + + @@ -104,7 +125,14 @@ - + + + + + + + + @@ -139,7 +167,14 @@ - + + + + + + + + @@ -174,10 +209,20 @@ - + uses - + + uses + + + + + + + + + @@ -212,7 +257,14 @@ - + + + + + + + + @@ -247,7 +299,14 @@ - + + + + + + + + @@ -282,7 +341,14 @@ - + + + + + + + + diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/GeonetworkResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/GeonetworkResolver.java index 6b75e52..8de2991 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/GeonetworkResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/GeonetworkResolver.java @@ -408,7 +408,7 @@ public class GeonetworkResolver { // SPECIFIC HANDLER FOR GEONETWORK REQUEST: /srv/en/mef.export if (remainPath != null && remainPath.compareTo(SRV_EN_MEF_EXPORT) == 0) { - logger.info("In case of mef.export, perfoming a custom handler"); + logger.info("In case of mef.export, performing a custom handler"); gnCSWlURL = geonetworkUrl + SRV_EN_MEF_EXPORT; String[] uuidValues = req.getParameterValues(UUID); if (uuidValues != null) { From 0fe2920c743c8c3bc51ca24be1e0924b9a0027ee Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 28 Jun 2024 15:16:02 +0200 Subject: [PATCH 83/83] removed unused imports --- pom.xml | 13 ------------- src/test/java/gis/RuntimeResourceReader.java | 8 ++++---- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/pom.xml b/pom.xml index 7779b6a..9b448cf 100644 --- a/pom.xml +++ b/pom.xml @@ -301,13 +301,6 @@ compile - - - - - - - org.gcube.datacatalogue catalogue-util-library @@ -315,12 +308,6 @@ compile - - - - - - diff --git a/src/test/java/gis/RuntimeResourceReader.java b/src/test/java/gis/RuntimeResourceReader.java index 9085eef..acdc935 100644 --- a/src/test/java/gis/RuntimeResourceReader.java +++ b/src/test/java/gis/RuntimeResourceReader.java @@ -131,8 +131,8 @@ public class RuntimeResourceReader { //String scope = "/d4science.research-infrastructures.eu/gCubeApps/Esquiline"; // String scope = "/d4science.research-infrastructures.eu/D4OS/ARIADNEplus_Project"; - String platformName = "geonetwork"; - String category = "Gis"; +// String platformName = "geonetwork"; +// String category = "Gis"; // String platformName = "GeoServer"; // String category = "Gis"; @@ -140,8 +140,8 @@ public class RuntimeResourceReader { // String platformName = "postgis"; // String category = "Database"; -// String platformName = "postgresql"; -// String category = "Database"; + String platformName = "postgres"; + String category = "Database"; // String platformName = "mongodb"; // String category = "Database";