From 90192d2085346df872b0e202034a927b4665e7b9 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 22 Nov 2023 16:09:03 +0100 Subject: [PATCH 01/28] Integrated the "Export as PDF" facility [#26026] --- .classpath | 4 +- .../com.gwtplugins.gdt.eclipse.core.prefs | 2 +- .settings/org.eclipse.wst.common.component | 95 ++++++++++-- CHANGELOG.md | 4 + pom.xml | 2 +- .../client/GeoportalDataViewer.java | 8 +- .../client/GeoportalDataViewerConstants.java | 19 ++- .../client/GeoportalDataViewerService.java | 5 + .../GeoportalDataViewerServiceAsync.java | 5 + .../client/gis/LightOpenLayerMap.java | 4 +- .../{GNAIcons.java => GeoportalIcons.java} | 4 +- .../{GNAImages.java => GeoportalImages.java} | 4 +- .../client/ui/GeonaDataViewMainPanel.java | 14 +- .../client/ui/cms/project/ProjectViewer.java | 67 ++++++++- .../ui/cms/project/ProjectViewer.ui.xml | 1 + .../relation/TimelineRelationPanel.java | 4 +- .../client/ui/dandd/DragDropLayer.java | 10 +- .../client/ui/map/MapView.java | 4 +- .../client/util/LoaderIcon.java | 4 +- .../GeoportalDataViewerServiceImpl.java | 59 ++++++++ .../server/WatingServerActionServlet.java | 136 ++++++++++++++++++ .../server/util/SessionUtil.java | 12 ++ .../shared/GeoNaSpatialQueryResult.java | 2 +- src/main/webapp/WEB-INF/web.xml | 10 ++ src/main/webapp/img/loading-gears.gif | Bin 0 -> 56511 bytes src/main/webapp/img/loading.gif | Bin 0 -> 2533 bytes 26 files changed, 428 insertions(+), 51 deletions(-) rename src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/{GNAIcons.java => GeoportalIcons.java} (87%) rename src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/{GNAImages.java => GeoportalImages.java} (91%) create mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java create mode 100644 src/main/webapp/img/loading-gears.gif create mode 100644 src/main/webapp/img/loading.gif diff --git a/.classpath b/.classpath index 4217d86..90eb7e4 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,6 @@ - + @@ -30,5 +30,5 @@ - + diff --git a/.settings/com.gwtplugins.gdt.eclipse.core.prefs b/.settings/com.gwtplugins.gdt.eclipse.core.prefs index 2d56c43..8c387a0 100644 --- a/.settings/com.gwtplugins.gdt.eclipse.core.prefs +++ b/.settings/com.gwtplugins.gdt.eclipse.core.prefs @@ -1,4 +1,4 @@ eclipse.preferences.version=1 -lastWarOutDir=/home/francescomangiacrapa/git/geoportal-data-viewer-app/target/geoportal-data-viewer-app-3.6.0 +lastWarOutDir=/home/francescomangiacrapa/git/geoportal-data-viewer-app/target/geoportal-data-viewer-app-3.7.0-SNAPSHOT warSrcDir=src/main/webapp warSrcDirIsOutput=false diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index a9e69fd..5914ecd 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,5 @@ - + @@ -99,8 +99,24 @@ - - + + + + + + + + + + + + + + + + + + @@ -201,7 +217,15 @@ - + + + + + + + + + @@ -302,7 +326,15 @@ - + + + + + + + + + @@ -403,7 +435,15 @@ - + + + + + + + + + @@ -504,7 +544,18 @@ - + + uses + + + + + + + + + + @@ -605,7 +656,15 @@ - + + + + + + + + + @@ -706,7 +765,15 @@ - + + + + + + + + + @@ -807,7 +874,15 @@ - + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index fe0d55f..b0d1b59 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). +## [v3.7.0-SNAPSHOT] + +- Provided the "Export as PDF" facility [#26026] + ## [v3.6.0] - GUI optimization [#25461] diff --git a/pom.xml b/pom.xml index 818ba7b..7911e90 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ org.gcube.portlets.user geoportal-data-viewer-app war - 3.6.0 + 3.7.0-SNAPSHOT GeoPortal Data Viewer App The GeoPortal Data Viewer App is an application to access, discovery and navigate the Geoportal projects/documents by a Web-Map Interface diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewer.java index be10d8a..0b06d57 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewer.java @@ -64,7 +64,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.gis.ExtentWrapped; import org.gcube.portlets.user.geoportaldataviewer.client.gis.MapUtils; import org.gcube.portlets.user.geoportaldataviewer.client.gis.OpenLayerMap; import org.gcube.portlets.user.geoportaldataviewer.client.gis.OpenLayerMap.CQL_FACILITY_ORIGIN; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.GeonaDataViewMainPanel; import org.gcube.portlets.user.geoportaldataviewer.client.ui.cms.project.relation.TimelineManagerStatus; import org.gcube.portlets.user.geoportaldataviewer.client.ui.util.OLGeoJSONUtil; @@ -150,7 +150,7 @@ public class GeoportalDataViewer implements EntryPoint { int attempt = 0; private LoaderIcon loaderApp = new LoaderIcon("Loading application... please wait", - new com.google.gwt.user.client.ui.Image(GNAImages.ICONS.spinnerEarth())); + new com.google.gwt.user.client.ui.Image(GeoportalImages.ICONS.spinnerEarth())); private HTML attributionDiv = new HTML(); @@ -543,7 +543,7 @@ public class GeoportalDataViewer implements EntryPoint { Modal errorModal = new Modal(true, true); errorModal.setCloseVisible(true); errorModal.setTitle("Oops..."); - Image geoportalError = new Image(GNAImages.ICONS.warningError()); + Image geoportalError = new Image(GeoportalImages.ICONS.warningError()); FlowPanel errorPanelMsg = new FlowPanel(); errorPanelMsg.getElement().addClassName("general_warning"); errorPanelMsg.add(geoportalError); @@ -1072,7 +1072,7 @@ public class GeoportalDataViewer implements EntryPoint { * @return the general error panel */ private FlowPanel getGeneralErrorPanel() { - Image geoportalError = new Image(GNAImages.ICONS.geoportaServiceError()); + Image geoportalError = new Image(GeoportalImages.ICONS.geoportaServiceError()); FlowPanel errorPanelMsg = new FlowPanel(); errorPanelMsg.getElement().addClassName("general_error"); errorPanelMsg.add(geoportalError); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index dd114eb..4538a3a 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -3,6 +3,7 @@ package org.gcube.portlets.user.geoportaldataviewer.client; import org.gcube.application.geoportalcommon.ConvertToDataViewModel; import org.gcube.portlets.user.geoportaldataviewer.client.gis.OpenLayersMapParameters; +import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.i18n.client.DateTimeFormat; @@ -14,7 +15,14 @@ import com.google.gwt.i18n.client.DateTimeFormat; * Nov 24, 2020 */ public class GeoportalDataViewerConstants { - + + //WAITING_SERVER_ACTION_SERVLET + public static final String WAITING_PARAMETER = "waiting"; + public static final String ACTION_TITLE_PARAMETER = "action"; + public static final String MESSAGE_PARAMETER = "message"; + public static final String WAITING_SERVER_ACTION_SERVLET = GWT.getModuleBaseURL() + + "geoportaldataviewerwaitingservice"; + public static final int TABLET_WIDTH = 1601; public static final String MAP_DIV = "map"; @@ -40,12 +48,9 @@ public class GeoportalDataViewerConstants { public static final String PROJECT_ID_KEY_FEATURE = "projectid"; public static enum GisToolbarFacilities { - COLLECTION("Collection", "Open the collections"), - MAP("Map", "Select the base Map"), - OVERLAY("Overlay", "Add overlay layers"), - SEARCH("Search", "Search in the collections"), - FILTER("Filter", "Apply spatial filtering"), - LAYERS("Layers", "Layers added to Map"), + COLLECTION("Collection", "Open the collections"), MAP("Map", "Select the base Map"), + OVERLAY("Overlay", "Add overlay layers"), SEARCH("Search", "Search in the collections"), + FILTER("Filter", "Apply spatial filtering"), LAYERS("Layers", "Layers added to Map"), PRESET_LOCATION("Preset Location", "Center the Map to Location"); String name; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java index 1be2b4c..a13f569 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java @@ -229,4 +229,9 @@ public interface GeoportalDataViewerService extends RemoteService { Integer getCountFor(String profileID, String phase, String status); + Boolean checkExportAsPDFConfig(); + + String exportAsPDF(String profileID, String projectID, String profileTitle, + GeoportalItemReferences geoportalItemReferences); + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java index 257385c..37cdb3c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java @@ -93,4 +93,9 @@ public interface GeoportalDataViewerServiceAsync { void getCountFor(String profileID, String phase, String status, AsyncCallback callback); + void checkExportAsPDFConfig(AsyncCallback callback); + + void exportAsPDF(String profileID, String projectID, String profileTitle, + GeoportalItemReferences geoportalItemReferences, AsyncCallback callback); + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/gis/LightOpenLayerMap.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/gis/LightOpenLayerMap.java index 9d8be3b..b7a0014 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/gis/LightOpenLayerMap.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/gis/LightOpenLayerMap.java @@ -8,7 +8,7 @@ import org.gcube.application.geoportalcommon.shared.gis.BoundsMap; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewer; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants.MAP_PROJECTION; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.BaseMapLayer; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.GeoQuery; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.GeoQuery.TYPE; @@ -87,7 +87,7 @@ public class LightOpenLayerMap { private ol.layer.Vector geometryLayer; - private String markerURL = GNAImages.ICONS.mapMarkerIcon().getURL(); + private String markerURL = GeoportalImages.ICONS.mapMarkerIcon().getURL(); private LayerOrder layerOrder = new LayerOrder(); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAIcons.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalIcons.java similarity index 87% rename from src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAIcons.java rename to src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalIcons.java index 32e4c76..e526a83 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAIcons.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalIcons.java @@ -4,7 +4,7 @@ import com.github.gwtbootstrap.client.ui.constants.BaseIconType; import com.google.gwt.core.client.GWT; import com.google.gwt.resources.client.ClientBundle; -public interface GNAIcons extends ClientBundle { +public interface GeoportalIcons extends ClientBundle { /** My custom base icon collection */ public enum CustomIconType implements BaseIconType { @@ -15,7 +15,7 @@ public interface GNAIcons extends ClientBundle { /** Inject the icon's css once at first usage */ static { - GNAImages icons = GWT.create(GNAImages.class); + GeoportalImages icons = GWT.create(GeoportalImages.class); icons.css().ensureInjected(); } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAImages.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalImages.java similarity index 91% rename from src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAImages.java rename to src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalImages.java index 511c501..44dc469 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GNAImages.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/resources/GeoportalImages.java @@ -5,13 +5,13 @@ import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.CssResource; import com.google.gwt.resources.client.ImageResource; -public interface GNAImages extends ClientBundle { +public interface GeoportalImages extends ClientBundle { /** Get access to the css resource during gwt compilation */ @Source("baseIcons.css") CssResource css(); - public static final GNAImages ICONS = GWT.create(GNAImages.class); + public static final GeoportalImages ICONS = GWT.create(GeoportalImages.class); /** * Our sample image icon. Makes the image resource for the gwt-compiler's css diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/GeonaDataViewMainPanel.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/GeonaDataViewMainPanel.java index 167087c..5e39133 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/GeonaDataViewMainPanel.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/GeonaDataViewMainPanel.java @@ -22,8 +22,8 @@ import org.gcube.portlets.user.geoportaldataviewer.client.events.ChangeMapLayerE import org.gcube.portlets.user.geoportaldataviewer.client.events.MapExtentToEvent; import org.gcube.portlets.user.geoportaldataviewer.client.events.collections.OpenCollectionEvent; import org.gcube.portlets.user.geoportaldataviewer.client.gis.OpenLayerMap; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAIcons; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalIcons; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.cms.search.SearchFacilityUI; import org.gcube.portlets.user.geoportaldataviewer.client.ui.crossfiltering.CrossFilteringLayerPanel; import org.gcube.portlets.user.geoportaldataviewer.client.ui.customoverlays.OverlayCustomLayerPanel; @@ -193,19 +193,19 @@ public class GeonaDataViewMainPanel extends Composite { dataBoxSelection.setIcon(IconType.BOOKMARK); removeQuery.setIcon(IconType.REMOVE); - Image italyImg = new Image(GNAImages.ICONS.italyIcon()); + Image italyImg = new Image(GeoportalImages.ICONS.italyIcon()); italyImg.getElement().getStyle().setPaddingLeft(20, Unit.PX); extentToItaly.getElement().appendChild(italyImg.getElement()); extentToItaly.setWidth("140px"); - Image worldImg = new Image(GNAImages.ICONS.worldIcon()); + Image worldImg = new Image(GeoportalImages.ICONS.worldIcon()); worldImg.getElement().getStyle().setPaddingLeft(20, Unit.PX); extentToEarth.getElement().appendChild(worldImg.getElement()); extentToEarth.setWidth("140px"); - // linkMap.setCustomIconStyle(GNAIcons.CustomIconType.MAP.get()); - linkPresetLocation.setCustomIconStyle(GNAIcons.CustomIconType.PRESET_LOCATION.get()); - linkLayers.setCustomIconStyle(GNAIcons.CustomIconType.LAYERS.get()); + // linkMap.setCustomIconStyle(GeoportalIcons.CustomIconType.MAP.get()); + linkPresetLocation.setCustomIconStyle(GeoportalIcons.CustomIconType.PRESET_LOCATION.get()); + linkLayers.setCustomIconStyle(GeoportalIcons.CustomIconType.LAYERS.get()); openCollectionDropDown.setIcon(IconType.COMPASS); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 50041e7..c3b709b 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -20,6 +20,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.Location; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.PLACE; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; +import org.gcube.portlets.user.geoportaldataviewer.client.util.NewBrowserWindow; import com.github.gwtbootstrap.client.ui.Button; import com.github.gwtbootstrap.client.ui.constants.ButtonType; @@ -83,6 +84,9 @@ public class ProjectViewer extends Composite { @UiField Button expandButton; + @UiField + Button exportButton; + @UiField Button relationshipsButton; @@ -136,6 +140,22 @@ public class ProjectViewer extends Composite { this.geoportalItemReferences = geoportalItemRefs; this.applicationBus = applicationBus; + GeoportalDataViewerServiceAsync.Util.getInstance().checkExportAsPDFConfig(new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + // TODO Auto-generated method stub + + } + + @Override + public void onSuccess(Boolean result) { + GWT.log("Export as PDF visible: " + result); + exportButton.setVisible(result); + + } + }); + final String theTitle = projectView.getTheProjectDV().getProfileName() != null ? projectView.getTheProjectDV().getProfileName() : "Project ID: " + projectView.getTheProjectDV().getId(); @@ -183,6 +203,51 @@ public class ProjectViewer extends Composite { } }); + exportButton.setType(ButtonType.LINK); + exportButton.setIcon(IconType.FILE); + exportButton.setTitle("Export as PDF"); + exportButton.setVisible(false); + + exportButton.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + String theProjectName =""; + try { + theProjectName = (String) projectView.getTheProjectDV().getTheDocument().getFirstEntryOfMap().getValue(); + theProjectName = theProjectName!=null?theProjectName: "Project ID: " + projectView.getTheProjectDV().getId(); + }catch (Exception e) { + // TODO: handle exception + } + + StringBuilder builder = new StringBuilder(); + builder.append(GeoportalDataViewerConstants.WAITING_SERVER_ACTION_SERVLET+"?"); + builder.append(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER+"=Export as PDF&"); + builder.append(GeoportalDataViewerConstants.MESSAGE_PARAMETER+"="+theProjectName+"&"); + builder.append(GeoportalDataViewerConstants.WAITING_PARAMETER+"=true"); + + String theWaitingServletRequest = builder.toString(); + final NewBrowserWindow ref = NewBrowserWindow.open(theWaitingServletRequest, "_blank", null); + + GeoportalDataViewerServiceAsync.Util.getInstance().exportAsPDF(projectView.getTheProjectDV().getProfileID(), + projectView.getTheProjectDV().getId(), theTitle, geoportalItemReferences, + new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + // TODO Auto-generated method stub + + } + + @Override + public void onSuccess(String resultURL) { + ref.setUrl(resultURL); + + } + }); + } + }); + relationshipsButton.setType(ButtonType.LINK); relationshipsButton.setIcon(IconType.LINK); relationshipsButton.setTitle("Show Relationships of this Project"); @@ -240,7 +305,7 @@ public class ProjectViewer extends Composite { public void onClick(ClickEvent event) { boolean visible = toc_list_container.isVisible(); setTocContentVisible(!visible); - + // if (visible) { // toc_list_container.setVisible(false); // reduceToc.setIcon(IconType.PLUS_SIGN_ALT); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml index 7e49a4c..f68043b 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml @@ -45,6 +45,7 @@ addStyleNames="functionalities-style"> Share Expand + Export Relationships Add Layers to Map diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/relation/TimelineRelationPanel.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/relation/TimelineRelationPanel.java index e8b2dde..d14804f 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/relation/TimelineRelationPanel.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/relation/TimelineRelationPanel.java @@ -7,7 +7,7 @@ import org.gcube.application.geoportalcommon.shared.geoportal.project.ProjectDV; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerServiceAsync; import org.gcube.portlets.user.geoportaldataviewer.client.events.ShowDetailsEvent; import org.gcube.portlets.user.geoportaldataviewer.client.events.ShowDetailsEvent.EVENT_SOURCE; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.cms.project.ProjectUtil; import org.gcube.portlets.user.geoportaldataviewer.client.util.LoaderIcon; @@ -45,7 +45,7 @@ public class TimelineRelationPanel extends Composite { Anchor timelinePopupCloser; private LoaderIcon loaderData = new LoaderIcon("Loading data... please wait", - new Image(GNAImages.ICONS.spinnerClock())); + new Image(GeoportalImages.ICONS.spinnerClock())); private TimelineRelationPanel instance = this; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/dandd/DragDropLayer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/dandd/DragDropLayer.java index ee965e7..7cea02c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/dandd/DragDropLayer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/dandd/DragDropLayer.java @@ -8,7 +8,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerSer import org.gcube.portlets.user.geoportaldataviewer.client.events.DoActionOnDetailLayersEvent; import org.gcube.portlets.user.geoportaldataviewer.client.events.DoActionOnDetailLayersEvent.DO_LAYER_ACTION; import org.gcube.portlets.user.geoportaldataviewer.client.events.DoActionOnDetailLayersEvent.SwapLayer; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.cms.project.ProjectUtil; import org.gcube.portlets.user.geoportaldataviewer.client.util.LoaderIcon; import org.gcube.portlets.user.geoportaldataviewer.client.util.StringUtil; @@ -50,11 +50,11 @@ public class DragDropLayer extends FlowPanel { private static DragDropLayer draggingTarget = null; final boolean droppable; private Label labelLayerName; - private Image imgLayerVisible = new Image(GNAImages.ICONS.layerVisible()); - private Image imgLayerInvisible = new Image(GNAImages.ICONS.layerInvisible()); + private Image imgLayerVisible = new Image(GeoportalImages.ICONS.layerVisible()); + private Image imgLayerInvisible = new Image(GeoportalImages.ICONS.layerInvisible()); - private Image imgLocate = new Image(GNAImages.ICONS.locate()); - private Image imgLocateNone = new Image(GNAImages.ICONS.locateNone()); + private Image imgLocate = new Image(GeoportalImages.ICONS.locate()); + private Image imgLocateNone = new Image(GeoportalImages.ICONS.locateNone()); private boolean locateEnabled = false; private HTML buttonLocate = new HTML(); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/map/MapView.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/map/MapView.java index 26059cf..e0f741e 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/map/MapView.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/map/MapView.java @@ -9,7 +9,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerCon import org.gcube.portlets.user.geoportaldataviewer.client.gis.ExtentWrapped; import org.gcube.portlets.user.geoportaldataviewer.client.gis.LightOpenLayerMap; import org.gcube.portlets.user.geoportaldataviewer.client.gis.MapUtils; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAIcons; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalIcons; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.Location; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.PLACE; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.BaseMapLayer; @@ -86,7 +86,7 @@ public class MapView extends Composite { theMapPanel.setWidth(internalMapWidth); theMapPanel.setHeight(internalMapHeight); - linkMap.setCustomIconStyle(GNAIcons.CustomIconType.MAP.get()); + linkMap.setCustomIconStyle(GeoportalIcons.CustomIconType.MAP.get()); Scheduler.get().scheduleDeferred(new ScheduledCommand() { diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/util/LoaderIcon.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/util/LoaderIcon.java index 4866699..f97763f 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/util/LoaderIcon.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/util/LoaderIcon.java @@ -3,7 +3,7 @@ */ package org.gcube.portlets.user.geoportaldataviewer.client.util; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GNAImages; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; @@ -18,7 +18,7 @@ import com.google.gwt.user.client.ui.Image; public class LoaderIcon extends HorizontalPanel{ - private Image imgLoading = new Image(GNAImages.ICONS.loading()); + private Image imgLoading = new Image(GeoportalImages.ICONS.loading()); private HTML txtLoading = new HTML(""); /** diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java index 58300e6..873e857 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java @@ -69,6 +69,9 @@ import org.gcube.application.geoportalcommon.util.StringUtil; import org.gcube.application.geoportalcommon.util.URLParserUtil; import org.gcube.application.geoportaldatamapper.GcubeProfilesPerUCDIdCache; import org.gcube.application.geoportaldatamapper.Geoportal_JSON_Mapper; +import org.gcube.application.geoportaldatamapper.exporter.Geoportal_PDF_Exporter; +import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource; +import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerService; import org.gcube.portlets.user.geoportaldataviewer.server.gis.FeatureParser; @@ -1878,4 +1881,60 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme return integer; } + @Override + public Boolean checkExportAsPDFConfig() { + LOG.debug("checkExportAsPDFConfig called"); + Boolean configChecked = null; + try { + new GeoportalServiceIdentityProxy(this.getThreadLocalRequest()); + configChecked = SessionUtil.getCheckConfigForPFDExporter(this.getThreadLocalRequest()); + if(configChecked==null) { + Geoportal_PDF_Exporter gpdfe = new Geoportal_PDF_Exporter(); + configChecked = gpdfe.checkConfig(); + SessionUtil.setCheckConfigForPFDExporter(this.getThreadLocalRequest(), configChecked); + } + + LOG.info("Does the 'Export As PDF' config exists? " + configChecked); + } catch (Exception e) { + LOG.error("Error occurred in checkExportAsPDFConfig", e); + } + return configChecked; + } + + @Override + public String exportAsPDF(String profileID, String projectID, String profileTitle, + GeoportalItemReferences geoportalItemReferences) { + LOG.debug("exportAsPDF for profileID: " + profileID + ", projectID: " + projectID + "called"); + + String pdfURL = null; + try { + + GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(this.getThreadLocalRequest()); + + Geoportal_PDF_Exporter gpdfe = new Geoportal_PDF_Exporter(); + ExporterProjectSource exportSource = new ExporterProjectSource(); + exportSource.setProfileID(profileID); + exportSource.setProfileTitle(profileTitle); + exportSource.setProjectID(projectID); + exportSource.setScope(ScopeProvider.instance.get()); + + GeoportalItemReferences gir = getPublicLinksFor(geoportalItemReferences); + + if (identity.isUser()) { + exportSource.setGisLink(gir.getRestrictedLink().getShortURL()); + GCubeUser user = SessionUtil.getCurrentUser(this.getThreadLocalRequest()); + exportSource.setAccountname(user.getUsername()); + } else { + exportSource.setGisLink(gir.getOpenLink().getShortURL()); + exportSource.setAccountname(null); + } + + pdfURL = gpdfe.createPDFFile(exportSource); + + } catch (Exception e1) { + // silent + } + return pdfURL; + } + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java new file mode 100644 index 0000000..4715575 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java @@ -0,0 +1,136 @@ +/** + * + */ +package org.gcube.portlets.user.geoportaldataviewer.server; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class WatingServerActionServlet. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Nov 22, 2023 + */ +public class WatingServerActionServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -1058074450240555475L; + protected static Logger logger = LoggerFactory.getLogger(WatingServerActionServlet.class); + + /** + * {@inheritDoc} + */ + @Override + public void init() throws ServletException { + super.init(); + logger.trace("Workspace WatingServerActionServlet ready."); + } + + /** + * Do get. + * + * @param req the req + * @param resp the resp + * @throws IOException Signals that an I/O exception has occurred. + */ + /* + * (non-Javadoc) + * + * @see + * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, + * javax.servlet.http.HttpServletResponse) + */ + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String action = req.getParameter(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER); + String message = req.getParameter(GeoportalDataViewerConstants.MESSAGE_PARAMETER); + boolean waiting = req.getParameter(GeoportalDataViewerConstants.WAITING_PARAMETER) == null ? true + : req.getParameter(GeoportalDataViewerConstants.WAITING_PARAMETER).equals("true"); + + logger.debug("Input Params [action: " + action + ", message: "+ message +", waiting: " + waiting + "]"); + + action = action == null || action.isEmpty() ? "Loading" : action; + + message = message == null || message.isEmpty() ? "" : message; + + sendResponse(resp, action, message, waiting); + } + + + /** + * Send response. + * + * @param response the response + * @param action the action + * @param message the message + * @param waiting the waiting + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendResponse(HttpServletResponse response, String action, String message, boolean waiting) throws IOException { + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().write(setHTMLMessage(action, message, waiting)); + response.flushBuffer(); + } + + /** + * Sets the HTML message. + * + * @param action the action + * @param message the message + * @param waiting the waiting + * @return the string + */ + protected String setHTMLMessage(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/portlets/user/geoportaldataviewer/server/util/SessionUtil.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/SessionUtil.java index 6c0fb18..698231f 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/SessionUtil.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/SessionUtil.java @@ -55,6 +55,8 @@ public class SessionUtil { private static final String UCD_COLLECTIONS_SESSION = "THE_UCD_COLLECTIONS"; + private static final String CHECKED_CONFIG_FOR_PDF_EXPORTER = "CHECKED_CONFIG_FOR_PDF_EXPORTER"; + /** * Checks if is into portal. * @@ -345,4 +347,14 @@ public class SessionUtil { return (Map) session.getAttribute(UCD_COLLECTIONS_SESSION); } + public static Boolean getCheckConfigForPFDExporter(HttpServletRequest httpServletRequest) { + HttpSession session = httpServletRequest.getSession(); + return (Boolean) session.getAttribute(CHECKED_CONFIG_FOR_PDF_EXPORTER); + } + + public static void setCheckConfigForPFDExporter(HttpServletRequest httpServletRequest, Boolean configChecked) { + HttpSession session = httpServletRequest.getSession(); + session.setAttribute(CHECKED_CONFIG_FOR_PDF_EXPORTER, configChecked); + } + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/GeoNaSpatialQueryResult.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/GeoNaSpatialQueryResult.java index 7929b7b..a55972d 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/GeoNaSpatialQueryResult.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/GeoNaSpatialQueryResult.java @@ -23,7 +23,7 @@ public class GeoNaSpatialQueryResult implements Serializable { private static final long serialVersionUID = 3513120677727206958L; private List features; private LayerObject sourceLayerObject; - // Map with couple (mongoId concessione, list of uploaded GNAImages for the + // Map with couple (mongoId concessione, list of uploaded GeoportalImages for the // concessione) private Map> mapImages = null; diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index f72daa1..81b416b 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -15,6 +15,11 @@ geoportalDataViewerServlet org.gcube.portlets.user.geoportaldataviewer.server.GeoportalDataViewerServiceImpl + + + geoportalWaitingServerActionServlet + org.gcube.portlets.user.geoportaldataviewer.server.WatingServerActionServlet + mpformbuilderServlet @@ -31,5 +36,10 @@ geoportalDataViewerServlet /GeoportalDataViewer/geoportaldataviewerservice + + + geoportalWaitingServerActionServlet + /GeoportalDataViewer/geoportaldataviewerwaitingservice + 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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 literal 0 HcmV?d00001 -- 2.17.1 From 9713bfb0a898f563a6cf5d31a98e5d60133661c0 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 22 Nov 2023 16:18:14 +0100 Subject: [PATCH 02/28] fixing contentType in the response --- .settings/org.eclipse.wst.common.component | 3 +++ .../geoportaldataviewer/server/WatingServerActionServlet.java | 1 + 2 files changed, 4 insertions(+) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 5914ecd..4375eb8 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -546,6 +546,9 @@ uses + + + uses diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java index 4715575..f6a2309 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java @@ -80,6 +80,7 @@ public class WatingServerActionServlet extends HttpServlet { */ protected void sendResponse(HttpServletResponse response, String action, String message, boolean waiting) throws IOException { response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("text/html"); response.getWriter().write(setHTMLMessage(action, message, waiting)); response.flushBuffer(); } -- 2.17.1 From b266279a9f00808d13e8e8c21fdc810812f12bf0 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 22 Nov 2023 16:20:19 +0100 Subject: [PATCH 03/28] Updated buttons order --- .../client/ui/cms/project/ProjectViewer.ui.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml index f68043b..72432b9 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.ui.xml @@ -44,10 +44,10 @@ Share - Expand Export + Expand Relationships - Add Layers to Map + Add Layers Date: Mon, 27 Nov 2023 10:59:02 +0100 Subject: [PATCH 04/28] Updated label --- .settings/org.eclipse.wst.common.component | 33 ++++++++++--------- .../client/ui/cms/project/ProjectViewer.java | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 4375eb8..67a2a15 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -108,7 +109,8 @@ - + + @@ -217,7 +219,8 @@ - + + @@ -326,7 +329,8 @@ - + + @@ -435,7 +439,8 @@ - + + @@ -544,13 +549,8 @@ - - uses - - - uses - - + + @@ -659,7 +659,8 @@ - + + @@ -768,7 +769,8 @@ - + + @@ -877,7 +879,8 @@ - + + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index c3b709b..283619b 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -222,7 +222,7 @@ public class ProjectViewer extends Composite { StringBuilder builder = new StringBuilder(); builder.append(GeoportalDataViewerConstants.WAITING_SERVER_ACTION_SERVLET+"?"); - builder.append(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER+"=Export as PDF&"); + builder.append(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER+"=Exporting as PDF...&"); builder.append(GeoportalDataViewerConstants.MESSAGE_PARAMETER+"="+theProjectName+"&"); builder.append(GeoportalDataViewerConstants.WAITING_PARAMETER+"=true"); -- 2.17.1 From 9e49f6f281138781870a8d5996d5d4ef9702cb92 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 24 Apr 2024 14:46:34 +0200 Subject: [PATCH 05/28] integrated the GeoportalExporterActionServlet --- .classpath | 5 + .settings/org.eclipse.wst.common.component | 220 +++++++++++++++++- pom.xml | 7 +- .../client/GeoportalDataViewerConstants.java | 16 +- .../client/GeoportalDataViewerService.java | 4 +- .../GeoportalDataViewerServiceAsync.java | 4 +- .../client/ui/cms/project/ProjectViewer.java | 57 ++--- .../GeoportalDataViewerServiceImpl.java | 88 ------- .../GeoportalExporterActionServlet.java | 197 ++++++++++++++++ .../server/WatingServerActionServlet.java | 137 ----------- .../GeoportalServiceIdentityProxy.java | 20 +- .../accessidentity/GcubeIdentity.java | 29 ++- .../accessidentity/IAMClientIdentity.java | 33 ++- .../accessidentity/UserIdentity.java | 23 ++ src/main/webapp/WEB-INF/web.xml | 24 +- .../GeoportalExporterActionServletTest.java | 42 ++++ 16 files changed, 614 insertions(+), 292 deletions(-) create mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java delete mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java create mode 100644 src/test/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalExporterActionServletTest.java diff --git a/.classpath b/.classpath index 90eb7e4..aa74096 100644 --- a/.classpath +++ b/.classpath @@ -30,5 +30,10 @@ + + + + + diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 67a2a15..b83d38d 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,25 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -109,7 +129,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -219,7 +259,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -329,7 +389,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -439,7 +519,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -549,7 +649,49 @@ - + + + + + + + + + + + + + + + + + + uses + + + uses + + + + + + + + + + + + + + + + + + + + + + @@ -659,7 +801,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -769,7 +931,27 @@ - + + + + + + + + + + + + + + + + + + + + + @@ -879,7 +1061,27 @@ - + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 7911e90..9b9b837 100644 --- a/pom.xml +++ b/pom.xml @@ -175,8 +175,13 @@ org.gcube.common keycloak-client - [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + [2.0.0, 3.0.0-SNAPSHOT) + + + + + com.liferay.portal portal-service diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index 4538a3a..25c0436 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -16,12 +16,18 @@ import com.google.gwt.i18n.client.DateTimeFormat; */ public class GeoportalDataViewerConstants { +// //WAITING_SERVER_ACTION_SERVLET +// public static final String WAITING_PARAMETER = "waiting"; +// public static final String ACTION_TITLE_PARAMETER = "action"; +// public static final String MESSAGE_PARAMETER = "message"; +// public static final String WAITING_SERVER_ACTION_SERVLET = GWT.getModuleBaseURL() +// + "geoportaldataviewerwaitingservice"; + //WAITING_SERVER_ACTION_SERVLET - public static final String WAITING_PARAMETER = "waiting"; - public static final String ACTION_TITLE_PARAMETER = "action"; - public static final String MESSAGE_PARAMETER = "message"; - public static final String WAITING_SERVER_ACTION_SERVLET = GWT.getModuleBaseURL() - + "geoportaldataviewerwaitingservice"; + public static final String UCD_ID_PARAMETER = "ucdID"; + public static final String PROIECT_ID_PARAMETER = "projectID"; + public static final String GEOPORTAL_EXPORT_ACTION_SERVLET = GWT.getModuleBaseURL() + + "geoportalexporterservice"; public static final int TABLET_WIDTH = 1601; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java index a13f569..2f036cf 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java @@ -231,7 +231,7 @@ public interface GeoportalDataViewerService extends RemoteService { Boolean checkExportAsPDFConfig(); - String exportAsPDF(String profileID, String projectID, String profileTitle, - GeoportalItemReferences geoportalItemReferences); +// String exportAsPDF(String profileID, String projectID, String profileTitle, +// GeoportalItemReferences geoportalItemReferences); } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java index 37cdb3c..0db918c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java @@ -95,7 +95,7 @@ public interface GeoportalDataViewerServiceAsync { void checkExportAsPDFConfig(AsyncCallback callback); - void exportAsPDF(String profileID, String projectID, String profileTitle, - GeoportalItemReferences geoportalItemReferences, AsyncCallback callback); +// void exportAsPDF(String profileID, String projectID, String profileTitle, +// GeoportalItemReferences geoportalItemReferences, AsyncCallback callback); } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 283619b..04c8aaa 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -212,39 +212,42 @@ public class ProjectViewer extends Composite { @Override public void onClick(ClickEvent event) { - String theProjectName =""; + String theProjectName = ""; try { - theProjectName = (String) projectView.getTheProjectDV().getTheDocument().getFirstEntryOfMap().getValue(); - theProjectName = theProjectName!=null?theProjectName: "Project ID: " + projectView.getTheProjectDV().getId(); - }catch (Exception e) { + theProjectName = (String) projectView.getTheProjectDV().getTheDocument().getFirstEntryOfMap() + .getValue(); + theProjectName = theProjectName != null ? theProjectName + : "Project ID: " + projectView.getTheProjectDV().getId(); + } catch (Exception e) { // TODO: handle exception } - + StringBuilder builder = new StringBuilder(); - builder.append(GeoportalDataViewerConstants.WAITING_SERVER_ACTION_SERVLET+"?"); - builder.append(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER+"=Exporting as PDF...&"); - builder.append(GeoportalDataViewerConstants.MESSAGE_PARAMETER+"="+theProjectName+"&"); - builder.append(GeoportalDataViewerConstants.WAITING_PARAMETER+"=true"); + builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + "?"); + builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" + + projectView.getTheProjectDV().getProfileID() + "&"); + builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" + + projectView.getTheProjectDV().getId()); - String theWaitingServletRequest = builder.toString(); - final NewBrowserWindow ref = NewBrowserWindow.open(theWaitingServletRequest, "_blank", null); - - GeoportalDataViewerServiceAsync.Util.getInstance().exportAsPDF(projectView.getTheProjectDV().getProfileID(), - projectView.getTheProjectDV().getId(), theTitle, geoportalItemReferences, - new AsyncCallback() { + String geoportalExportActionServlet = builder.toString(); + final NewBrowserWindow ref = NewBrowserWindow.open(geoportalExportActionServlet, "_blank", null); - @Override - public void onFailure(Throwable caught) { - // TODO Auto-generated method stub - - } - - @Override - public void onSuccess(String resultURL) { - ref.setUrl(resultURL); - - } - }); +// GeoportalDataViewerServiceAsync.Util.getInstance().exportAsPDF( +// projectView.getTheProjectDV().getProfileID(), projectView.getTheProjectDV().getId(), theTitle, +// geoportalItemReferences, new AsyncCallback() { +// +// @Override +// public void onFailure(Throwable caught) { +// // TODO Auto-generated method stub +// +// } +// +// @Override +// public void onSuccess(String resultURL) { +// ref.setUrl(resultURL); +// +// } +// }); } }); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java index 873e857..3377c89 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java @@ -70,8 +70,6 @@ import org.gcube.application.geoportalcommon.util.URLParserUtil; import org.gcube.application.geoportaldatamapper.GcubeProfilesPerUCDIdCache; import org.gcube.application.geoportaldatamapper.Geoportal_JSON_Mapper; import org.gcube.application.geoportaldatamapper.exporter.Geoportal_PDF_Exporter; -import org.gcube.application.geoportaldatamapper.shared.ExporterProjectSource; -import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerService; import org.gcube.portlets.user.geoportaldataviewer.server.gis.FeatureParser; @@ -620,56 +618,6 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme } -// public Map> getAvaiableCrossFilteringLayers() { -// -// Map> mapProfileIDOvelayLayers = new LinkedHashMap<>(); -// -// // Reading UCDs Collections from the session -// Map ucdCollections = SessionUtil.getAvailableCollections(getThreadLocalRequest()); -// -// for (String profileId : ucdCollections.keySet()) { -// -// UseCaseDescriptor u = ucdCollections.get(profileId); -// -// // Loading geoportal_grouped_overlay_layers if exists -// GEOPORTAL_DATA_HANDLER theHandler = GEOPORTAL_DATA_HANDLER.geoportal_grouped_cross_filtering; -// List handlers = u.getHandlersByType(theHandler.getType()); -// -// if (handlers != null && handlers.size() > 0) { -// // Loading Handler gcube_profiles -// HandlerDeclaration handler = handlers.get(0); -// List listGroupedCustomLayers = null; -// try { -// -// HandlerDeclarationDV handlerDV = ConvertToDataValueObjectModel.toHandlerDeclarationDV(handler, u, -// GEOPORTAL_CONFIGURATION_TYPE.grouped_overlay_layers); -// -// if (handler != null) { -// ConfigurationDV config = handlerDV.getConfiguration(); -// switch (config.getConfigurationType()) { -// case grouped_overlay_layers: -// listGroupedCustomLayers = (List) config.getConfiguration(); -// break; -// default: -// break; -// } -// } -// } catch (Exception e) { -// LOG.error("Error on loading {} config for ucd Id {}. Returning null", -// GEOPORTAL_CONFIGURATION_TYPE.grouped_overlay_layers, u.getId()); -// } -// -// mapProfileIDOvelayLayers.put(profileId, listGroupedCustomLayers); -// } else { -// LOG.warn("No handler " + theHandler + "found into UCD " + u.getId() + ", continue..."); -// mapProfileIDOvelayLayers.put(profileId, null); -// } -// } -// -// return mapProfileIDOvelayLayers; -// -// } - /** * Gets the layer index. * @@ -1901,40 +1849,4 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme return configChecked; } - @Override - public String exportAsPDF(String profileID, String projectID, String profileTitle, - GeoportalItemReferences geoportalItemReferences) { - LOG.debug("exportAsPDF for profileID: " + profileID + ", projectID: " + projectID + "called"); - - String pdfURL = null; - try { - - GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(this.getThreadLocalRequest()); - - Geoportal_PDF_Exporter gpdfe = new Geoportal_PDF_Exporter(); - ExporterProjectSource exportSource = new ExporterProjectSource(); - exportSource.setProfileID(profileID); - exportSource.setProfileTitle(profileTitle); - exportSource.setProjectID(projectID); - exportSource.setScope(ScopeProvider.instance.get()); - - GeoportalItemReferences gir = getPublicLinksFor(geoportalItemReferences); - - if (identity.isUser()) { - exportSource.setGisLink(gir.getRestrictedLink().getShortURL()); - GCubeUser user = SessionUtil.getCurrentUser(this.getThreadLocalRequest()); - exportSource.setAccountname(user.getUsername()); - } else { - exportSource.setGisLink(gir.getOpenLink().getShortURL()); - exportSource.setAccountname(null); - } - - pdfURL = gpdfe.createPDFFile(exportSource); - - } catch (Exception e1) { - // silent - } - return pdfURL; - } - } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java new file mode 100644 index 0000000..5b7a5cc --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -0,0 +1,197 @@ +/** + * + */ +package org.gcube.portlets.user.geoportaldataviewer.server; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Enumeration; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.http.client.methods.HttpGet; +import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; +import org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.GeoportalServiceIdentityProxy; +import org.gcube.portlets.user.uriresolvermanager.geoportal.GeoportalExporterAPI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Class GeoportalExporterActionServlet. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 23, 2024 + */ +public class GeoportalExporterActionServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 6037090280489238565L; + protected static Logger logger = LoggerFactory.getLogger(GeoportalExporterActionServlet.class); + + /** + * {@inheritDoc} + */ + @Override + public void init() throws ServletException { + super.init(); + logger.trace(GeoportalExporterActionServlet.class.getSimpleName() + " ready."); + } + + /** + * Do get. + * + * @param req the req + * @param resp the resp + * @throws IOException Signals that an I/O exception has occurred. + * @throws ServletException the servlet exception + */ + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { +// setSecretManager(); + String projectID = req.getParameter(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER); + String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); + + logger.info("doGet called with Input Params [projectID: " + projectID + ", ucdID: " + ucdID + "]"); + + try { + + GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(req); + String theToken = identity.getToken(); + String theIdentity = identity.getIdentity(); + + GeoportalExporterAPI geoportalExporterAPI = new GeoportalExporterAPI(); + URL urlRequest = geoportalExporterAPI.exportProject("pdf", ucdID, projectID, false); + String urlToRedirect = urlRequest.toString(); + logger.info("Performing request to {} with identity {}", urlToRedirect, identity.getDescription()); + logger.info("Token is {}", theToken.substring(0, 20) + "_MASKED_TOKEN"); + + InputStream is = performHttpRequestToSGService(urlToRedirect, theIdentity, theToken); + IOUtils.copy(is, resp.getOutputStream()); + resp.flushBuffer(); + + } catch (Exception e) { + logger.error("Error occurred when exporting the Project with id: " + projectID, e); + sendError(resp, "Error occurred when exporting the Project. Error is: " + e.getMessage()); + return; + } + + } + + public static InputStream performHttpRequestToSGService(String urlToService, String identity, String token) + throws IOException { + logger.debug("performHttpRequestToSGService called"); + try { + + URL url = new URL(urlToService); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + // timeout at 60sec + conn.setConnectTimeout(6000); + conn.setDoOutput(true); + + if (token.length() > 50) { + // is JWT TOKEN + conn.setRequestProperty("Authorization", "Bearer " + token); + } else { + // is legacy Token + conn.setRequestProperty("gcube-token", token); + } + + conn.setRequestProperty("Content-Type", "text/html"); + conn.setRequestMethod("GET"); + logger.debug("performHttpRequestToSGService done, returning"); + return conn.getInputStream(); + } catch (IOException e) { + logger.error("Error on performing request to url " + urlToService, e); + throw e; + } + } + + /** + * Sets the headers to target. + * + * @param httpSource the http source + * @param response the response + * @return the http servlet response + */ + public static HttpServletResponse setHeadersToTarget(HttpServletRequest httpSource, HttpServletResponse response) { + + Enumeration headersNames = httpSource.getHeaderNames(); + while (headersNames.hasMoreElements()) { + String headerName = (String) headersNames.nextElement(); + Enumeration values = httpSource.getHeaders(headerName); + while (values.hasMoreElements()) { + String value = values.nextElement(); + logger.info("Copying header {} with value {}", headerName, value); + response.addHeader(headerName, value); + } + } + return response; + } + + /** + * Sets the headers to target. + * + * @param httpSource the http source + * @param httpTarget the http target + * @return the http get + */ + public static HttpGet setHeadersToTarget(HttpServletRequest httpSource, HttpGet httpTarget) { + + Enumeration headersNames = httpSource.getHeaderNames(); + while (headersNames.hasMoreElements()) { + String headerName = (String) headersNames.nextElement(); + Enumeration values = httpSource.getHeaders(headerName); + while (values.hasMoreElements()) { + String value = values.nextElement(); + logger.info("Copying header {} with value {}", headerName, value); + httpTarget.addHeader(headerName, value); + } + } + return httpTarget; + } + + /** + * Sets the headers to response. + * + * @param httpSource the http source + * @param httpTarget the http target + * @return the http get + */ + public static HttpGet setHeadersToResponse(HttpServletRequest httpSource, HttpGet httpTarget) { + + Enumeration headersNames = httpSource.getHeaderNames(); + while (headersNames.hasMoreElements()) { + String headerName = (String) headersNames.nextElement(); + Enumeration values = httpSource.getHeaders(headerName); + while (values.hasMoreElements()) { + String value = values.nextElement(); + logger.info("Copying header {} with value {}", headerName, value); + httpTarget.addHeader(headerName, value); + } + } + return httpTarget; + } + + /** + * Send response. + * + * @param response the response + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendError(HttpServletResponse response, String message) throws IOException { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + response.setContentType("text/html"); + response.getWriter().write("Error" + message + ""); + response.flushBuffer(); + } + +} diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java deleted file mode 100644 index f6a2309..0000000 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/WatingServerActionServlet.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * - */ -package org.gcube.portlets.user.geoportaldataviewer.server; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The Class WatingServerActionServlet. - * - * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it - * - * Nov 22, 2023 - */ -public class WatingServerActionServlet extends HttpServlet { - - /** - * - */ - private static final long serialVersionUID = -1058074450240555475L; - protected static Logger logger = LoggerFactory.getLogger(WatingServerActionServlet.class); - - /** - * {@inheritDoc} - */ - @Override - public void init() throws ServletException { - super.init(); - logger.trace("Workspace WatingServerActionServlet ready."); - } - - /** - * Do get. - * - * @param req the req - * @param resp the resp - * @throws IOException Signals that an I/O exception has occurred. - */ - /* - * (non-Javadoc) - * - * @see - * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, - * javax.servlet.http.HttpServletResponse) - */ - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - - String action = req.getParameter(GeoportalDataViewerConstants.ACTION_TITLE_PARAMETER); - String message = req.getParameter(GeoportalDataViewerConstants.MESSAGE_PARAMETER); - boolean waiting = req.getParameter(GeoportalDataViewerConstants.WAITING_PARAMETER) == null ? true - : req.getParameter(GeoportalDataViewerConstants.WAITING_PARAMETER).equals("true"); - - logger.debug("Input Params [action: " + action + ", message: "+ message +", waiting: " + waiting + "]"); - - action = action == null || action.isEmpty() ? "Loading" : action; - - message = message == null || message.isEmpty() ? "" : message; - - sendResponse(resp, action, message, waiting); - } - - - /** - * Send response. - * - * @param response the response - * @param action the action - * @param message the message - * @param waiting the waiting - * @throws IOException Signals that an I/O exception has occurred. - */ - protected void sendResponse(HttpServletResponse response, String action, String message, boolean waiting) throws IOException { - response.setStatus(HttpServletResponse.SC_OK); - response.setContentType("text/html"); - response.getWriter().write(setHTMLMessage(action, message, waiting)); - response.flushBuffer(); - } - - /** - * Sets the HTML message. - * - * @param action the action - * @param message the message - * @param waiting the waiting - * @return the string - */ - protected String setHTMLMessage(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/portlets/user/geoportaldataviewer/server/mongoservice/GeoportalServiceIdentityProxy.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/GeoportalServiceIdentityProxy.java index 33d9ebb..b955e51 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/GeoportalServiceIdentityProxy.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/GeoportalServiceIdentityProxy.java @@ -22,9 +22,9 @@ public class GeoportalServiceIdentityProxy { private static final Logger LOG = LoggerFactory.getLogger(GeoportalServiceIdentityProxy.class); private GcubeIdentity gCubeIdentity; - + private boolean isUser = false; - + private boolean isIAMClient = false; /** @@ -57,12 +57,24 @@ public class GeoportalServiceIdentityProxy { gCubeIdentity.setIdentity(request); } - + public boolean isUser() { return isUser; } - + public boolean isIAMClient() { return isIAMClient; } + + public String getDescription() { + return gCubeIdentity.getIdentityDescription(); + } + + public String getToken() { + return gCubeIdentity.getToken(); + } + + public String getIdentity() { + return gCubeIdentity.getIdentity(); + } } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/GcubeIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/GcubeIdentity.java index ad1e4e4..15e4f8c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/GcubeIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/GcubeIdentity.java @@ -2,16 +2,15 @@ package org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.accessid import javax.servlet.http.HttpServletRequest; - /** * The Interface GcubeIdentity. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * - * Sep 23, 2021 + * Sep 23, 2021 */ public interface GcubeIdentity { - + /** * Sets the identity. * @@ -19,10 +18,32 @@ public interface GcubeIdentity { * @throws Exception the exception */ public void setIdentity(HttpServletRequest httpRequest) throws Exception; - + /** * Reset identity. */ public void resetIdentity(); + /** + * Gets the identity description. + * + * @return the identity description + */ + public String getIdentityDescription(); + + + /** + * Gets the identity. + * + * @return the identity + */ + public String getIdentity(); + + /** + * Gets the token. + * + * @return the token + */ + public String getToken(); + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java index 45dbc63..ca51ff2 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java @@ -16,18 +16,22 @@ public class IAMClientIdentity implements GcubeIdentity { private static final Logger LOG = LoggerFactory.getLogger(IAMClientIdentity.class); private String previousUMAToken = null; + + private String currentUMAToken = null; + private String clientId = null; + private static final String IAM_CLIENT_CREDENTIALS = "IAM_CLIENT_CREDENTIALS"; @Override public void setIdentity(HttpServletRequest httpRequest) throws Exception { LOG.info("setIdentity called"); String currentScope = SessionUtil.getCurrentContext(httpRequest, true); - IAMClientCredentials credentials = sessionGetIAMClientCredentials(httpRequest); + IAMClientCredentials credentials = sessionGetIAMClientCredentials(httpRequest); try { - if(credentials==null) { + if (credentials == null) { credentials = IAMClientCredentialsReader.getCredentials(); - sessionSetIAMClientCredentials(httpRequest,credentials); + sessionSetIAMClientCredentials(httpRequest, credentials); } } catch (Exception e) { LOG.error("Error on discovering IAM Client credentials", e); @@ -36,7 +40,7 @@ public class IAMClientIdentity implements GcubeIdentity { LOG.trace("Read credentials: " + credentials); String umaAcessToken = null; - String clientId = credentials.getClientId(); + clientId = credentials.getClientId(); String clientSecret = credentials.getClientSecret(); try { @@ -46,6 +50,7 @@ public class IAMClientIdentity implements GcubeIdentity { umaAcessToken = tr.getAccessToken(); if (umaAcessToken != null && !umaAcessToken.isEmpty()) { LOG.info("UMA Access Token read correctly"); + currentUMAToken = umaAcessToken; } else { LOG.error("UMA Access Token NOT RETRIEVED!!!"); throw new Exception("UMA Access Token is null or empty"); @@ -75,6 +80,11 @@ public class IAMClientIdentity implements GcubeIdentity { } + @Override + public String getToken() { + return currentUMAToken; + } + @Override public void resetIdentity() { LOG.info("resetIdentity called"); @@ -82,7 +92,7 @@ public class IAMClientIdentity implements GcubeIdentity { LOG.info("resetIdentity to previous AccessToken"); } - + /** * Gets the IAM client credentials. * @@ -103,7 +113,7 @@ public class IAMClientIdentity implements GcubeIdentity { * Sets the IAM client credentials. * * @param httpRequest the http request - * @param iamCC the iam CC + * @param iamCC the iam CC */ public static void sessionSetIAMClientCredentials(HttpServletRequest httpRequest, IAMClientCredentials iamCC) { HttpSession session = httpRequest.getSession(); @@ -114,4 +124,15 @@ public class IAMClientIdentity implements GcubeIdentity { } } + @Override + public String getIdentityDescription() { + return "ClientId: "+ clientId; + + } + + @Override + public String getIdentity() { + return clientId; + } + } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java index f2ee8f9..3a6f79f 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java @@ -3,6 +3,7 @@ package org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.accessid import javax.servlet.http.HttpServletRequest; import org.gcube.portlets.user.geoportaldataviewer.server.util.SessionUtil; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,13 +11,19 @@ public class UserIdentity implements GcubeIdentity { private static final Logger LOG = LoggerFactory.getLogger(UserIdentity.class); + private HttpServletRequest httpRequest; + + private GCubeUser user; + public UserIdentity() { } @Override public void setIdentity(HttpServletRequest httpRequest) throws Exception { LOG.info("setIdentity called"); + this.httpRequest = httpRequest; SessionUtil.getCurrentToken(httpRequest, true); + user = SessionUtil.getCurrentUser(httpRequest); } @@ -25,4 +32,20 @@ public class UserIdentity implements GcubeIdentity { LOG.info("resetIdentity called, doing nothing"); // doing nothing } + + @Override + public String getToken() { + return SessionUtil.getCurrentToken(httpRequest, true); + } + + @Override + public String getIdentityDescription() { + return user != null ? "user: " + user.getUsername() : "null"; + } + + @Override + public String getIdentity() { + return user.getUsername(); + } + } diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 81b416b..70095f1 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -16,11 +16,16 @@ org.gcube.portlets.user.geoportaldataviewer.server.GeoportalDataViewerServiceImpl
- - geoportalWaitingServerActionServlet - org.gcube.portlets.user.geoportaldataviewer.server.WatingServerActionServlet + + + + + + + geoportalExporterServerActionServlet + org.gcube.portlets.user.geoportaldataviewer.server.GeoportalExporterActionServlet - + mpformbuilderServlet org.gcube.portlets.widgets.mpformbuilder.server.MetadataProfileFormBuilderServiceImpl @@ -37,9 +42,14 @@ /GeoportalDataViewer/geoportaldataviewerservice - - geoportalWaitingServerActionServlet - /GeoportalDataViewer/geoportaldataviewerwaitingservice + + + + + + + geoportalExporterServerActionServlet + /GeoportalDataViewer/geoportalexporterservice diff --git a/src/test/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalExporterActionServletTest.java b/src/test/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalExporterActionServletTest.java new file mode 100644 index 0000000..0c8fd1b --- /dev/null +++ b/src/test/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalExporterActionServletTest.java @@ -0,0 +1,42 @@ +/** + * + */ +package org.gcube.portlets.user.geoportaldataviewer; + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.gcube.portlets.user.geoportaldataviewer.server.GeoportalExporterActionServlet; + +/** + * The Class GeoportalExporterActionServletTest. + * + * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it + * + * Apr 24, 2024 + */ +public class GeoportalExporterActionServletTest { + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + String url = "https://data.dev.d4science.org/geoportal/export/pdf/profiledConcessioni/661d2c6f8804530afb90b132"; + String identity = "francesco.mangiacrapa"; + String token = ""; + System.out.println("Start"); + InputStream response; + try { + response = GeoportalExporterActionServlet.performHttpRequestToSGService(url, identity, token); + System.out.println(IOUtils.toString(response)); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("End"); + } + +} -- 2.17.1 From 1f5db2eb16fdd86cafad8f789001e4de1c388268 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 24 Apr 2024 15:20:36 +0200 Subject: [PATCH 06/28] added log --- CHANGELOG.md | 1 + .../server/GeoportalExporterActionServlet.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0d1b59..b879504 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v3.7.0-SNAPSHOT] - Provided the "Export as PDF" facility [#26026] +- Integrated the GeoportalExporter as service [#27321] ## [v3.6.0] diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 5b7a5cc..adbcb55 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -18,6 +18,7 @@ import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.HttpGet; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.GeoportalServiceIdentityProxy; +import org.gcube.portlets.user.geoportaldataviewer.server.util.SessionUtil; import org.gcube.portlets.user.uriresolvermanager.geoportal.GeoportalExporterAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +63,8 @@ public class GeoportalExporterActionServlet extends HttpServlet { logger.info("doGet called with Input Params [projectID: " + projectID + ", ucdID: " + ucdID + "]"); try { - + String scope = SessionUtil.getCurrentContext(req, true); + logger.info("the scope is: "+scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(req); String theToken = identity.getToken(); String theIdentity = identity.getIdentity(); -- 2.17.1 From 50fac5143d57926add729f32fe5bc0220778adc5 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 14:30:01 +0200 Subject: [PATCH 07/28] removed unused code --- .../GeoportalDataViewer.gwt.xml | 3 +++ .../client/ui/cms/project/ProjectViewer.java | 19 +------------------ .../GeoportalDataViewer.gwt.xml | 3 +++ 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml index 71a67d1..1072670 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml @@ -21,6 +21,9 @@ + + () { -// -// @Override -// public void onFailure(Throwable caught) { -// // TODO Auto-generated method stub -// -// } -// -// @Override -// public void onSuccess(String resultURL) { -// ref.setUrl(resultURL); -// -// } -// }); + NewBrowserWindow.open(geoportalExportActionServlet, "_blank", null); } }); diff --git a/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml b/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml index 71a67d1..1072670 100644 --- a/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml +++ b/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml @@ -21,6 +21,9 @@ + + Date: Mon, 29 Apr 2024 15:02:34 +0200 Subject: [PATCH 08/28] Added GCubeClientContext in gwt.xml and used before call the GeoportalExporterAction Servlet --- .../GeoportalDataViewer.gwt.xml | 5 ++++- .../client/GeoportalDataViewerConstants.java | 1 + .../client/ui/cms/project/ProjectViewer.java | 6 +++++- .../GeoportalExporterActionServlet.java | 21 +++++++++++++------ .../GeoportalDataViewer.gwt.xml | 5 ++++- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml index 1072670..85fba01 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml @@ -17,11 +17,14 @@ + + - + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index 25c0436..1d1ca6c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -26,6 +26,7 @@ public class GeoportalDataViewerConstants { //WAITING_SERVER_ACTION_SERVLET public static final String UCD_ID_PARAMETER = "ucdID"; public static final String PROIECT_ID_PARAMETER = "projectID"; + public static final String CONTEXT_ID_PARAMETER = "contextID"; public static final String GEOPORTAL_EXPORT_ACTION_SERVLET = GWT.getModuleBaseURL() + "geoportalexporterservice"; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 33fd6c7..c7217f9 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -7,6 +7,7 @@ import org.gcube.application.geoportalcommon.shared.geoportal.geojson.GeoJSON; import org.gcube.application.geoportalcommon.shared.geoportal.project.RelationshipDV; import org.gcube.application.geoportalcommon.shared.geoportal.view.ProjectView; import org.gcube.application.geoportalcommon.shared.geoportal.view.SectionView; +import org.gcube.portal.clientcontext.client.GCubeClientContext; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants.MAP_PROJECTION; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerServiceAsync; @@ -222,12 +223,15 @@ public class ProjectViewer extends Composite { // TODO: handle exception } + String currentContextId = GCubeClientContext.getCurrentContextId(); + StringBuilder builder = new StringBuilder(); builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + "?"); builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" + projectView.getTheProjectDV().getProfileID() + "&"); builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" - + projectView.getTheProjectDV().getId()); + + projectView.getTheProjectDV().getId() + "&"); + builder.append(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER + "=" + currentContextId); String geoportalExportActionServlet = builder.toString(); NewBrowserWindow.open(geoportalExportActionServlet, "_blank", null); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index adbcb55..a1705f0 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -16,10 +16,12 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.http.client.methods.HttpGet; +import org.gcube.common.portal.PortalContext; +import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.GeoportalServiceIdentityProxy; -import org.gcube.portlets.user.geoportaldataviewer.server.util.SessionUtil; import org.gcube.portlets.user.uriresolvermanager.geoportal.GeoportalExporterAPI; +import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,12 +61,19 @@ public class GeoportalExporterActionServlet extends HttpServlet { // setSecretManager(); String projectID = req.getParameter(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER); String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); - - logger.info("doGet called with Input Params [projectID: " + projectID + ", ucdID: " + ucdID + "]"); - + String contextID = req.getParameter(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER); + logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + "]"); + + if(contextID==null || contextID.isEmpty()) + sendError(resp, "Bad Request. No context found!"); + + PortalContext pContext = PortalContext.getConfiguration(); + GCubeUser gcubeUser = pContext.getCurrentUser(req); + String scope = pContext.getCurrentScope(contextID); + logger.info("User caller fullname is {}, scope {}", gcubeUser.getFullname(), scope); + try { - String scope = SessionUtil.getCurrentContext(req, true); - logger.info("the scope is: "+scope); + ScopeProvider.instance.set(scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(req); String theToken = identity.getToken(); String theIdentity = identity.getIdentity(); diff --git a/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml b/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml index 1072670..85fba01 100644 --- a/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml +++ b/src/main/resources/org/gcube/portlets/user/geoportaldataviewer/GeoportalDataViewer.gwt.xml @@ -17,11 +17,14 @@ + + - + -- 2.17.1 From 2fae3ee31ade5d439e489171267a5bbc6efb5436 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 15:11:57 +0200 Subject: [PATCH 09/28] updated code --- .../server/GeoportalExporterActionServlet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index a1705f0..85623e5 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -68,16 +68,16 @@ public class GeoportalExporterActionServlet extends HttpServlet { sendError(resp, "Bad Request. No context found!"); PortalContext pContext = PortalContext.getConfiguration(); - GCubeUser gcubeUser = pContext.getCurrentUser(req); String scope = pContext.getCurrentScope(contextID); - logger.info("User caller fullname is {}, scope {}", gcubeUser.getFullname(), scope); + logger.info("The scope is {}", scope); try { ScopeProvider.instance.set(scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(req); String theToken = identity.getToken(); String theIdentity = identity.getIdentity(); - + logger.info("The identity is {}", theIdentity); + GeoportalExporterAPI geoportalExporterAPI = new GeoportalExporterAPI(); URL urlRequest = geoportalExporterAPI.exportProject("pdf", ucdID, projectID, false); String urlToRedirect = urlRequest.toString(); -- 2.17.1 From 7d4e363c9ffd10f48861def6357433f292c46bbb Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 16:18:25 +0200 Subject: [PATCH 10/28] trying to set CONTEXT_ID_PARAMETER --- .../client/GeoportalDataViewerConstants.java | 12 +--- .../client/ui/cms/project/ProjectViewer.java | 61 ++++++++++++++++++- .../client/ui/util/NewBrowserWindow.java | 31 ++++++++++ .../GeoportalExporterActionServlet.java | 21 ++++--- .../server/MutableHttpServletRequest.java | 53 ++++++++++++++++ 5 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java create mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/MutableHttpServletRequest.java diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index 1d1ca6c..d50a288 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -16,17 +16,11 @@ import com.google.gwt.i18n.client.DateTimeFormat; */ public class GeoportalDataViewerConstants { -// //WAITING_SERVER_ACTION_SERVLET -// public static final String WAITING_PARAMETER = "waiting"; -// public static final String ACTION_TITLE_PARAMETER = "action"; -// public static final String MESSAGE_PARAMETER = "message"; -// public static final String WAITING_SERVER_ACTION_SERVLET = GWT.getModuleBaseURL() -// + "geoportaldataviewerwaitingservice"; - - //WAITING_SERVER_ACTION_SERVLET + //Geoportal_Exporter_ACTION_SERVLET public static final String UCD_ID_PARAMETER = "ucdID"; public static final String PROIECT_ID_PARAMETER = "projectID"; - public static final String CONTEXT_ID_PARAMETER = "contextID"; + public static final String CONTEXT_ID_PARAMETER = "contex_id"; + public static final String USER_ID_PARAMETER = "user_id"; public static final String GEOPORTAL_EXPORT_ACTION_SERVLET = GWT.getModuleBaseURL() + "geoportalexporterservice"; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index c7217f9..12e8304 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -15,6 +15,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.events.AddLayerToMapEv import org.gcube.portlets.user.geoportaldataviewer.client.events.TimelineProjectRelationsEvent; import org.gcube.portlets.user.geoportaldataviewer.client.events.TimelineProjectRelationsEvent.EVENT_TYPE; import org.gcube.portlets.user.geoportaldataviewer.client.gis.MapUtils; +import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.ModalWindow; import org.gcube.portlets.user.geoportaldataviewer.client.ui.dialogs.DialogShareableLink; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil; @@ -24,6 +25,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; import org.gcube.portlets.user.geoportaldataviewer.client.util.NewBrowserWindow; import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.Modal; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.google.gwt.core.client.GWT; @@ -31,14 +33,22 @@ import com.google.gwt.dom.client.UListElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.http.client.Request; +import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.http.client.RequestBuilder.Method; +import com.google.gwt.http.client.RequestCallback; +import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.Response; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; import ol.Coordinate; @@ -223,18 +233,63 @@ public class ProjectViewer extends Composite { // TODO: handle exception } + // Reading contextId and userId from GCubeClientContext String currentContextId = GCubeClientContext.getCurrentContextId(); + String currentUserId = GCubeClientContext.getCurrentUserId(); StringBuilder builder = new StringBuilder(); builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + "?"); builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" - + projectView.getTheProjectDV().getProfileID() + "&"); + + projectView.getTheProjectDV().getProfileID()); + builder.append("&"); builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" - + projectView.getTheProjectDV().getId() + "&"); + + projectView.getTheProjectDV().getId()); + builder.append("&"); builder.append(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER + "=" + currentContextId); + builder.append("&"); + builder.append(GeoportalDataViewerConstants.USER_ID_PARAMETER + "=" + currentUserId); String geoportalExportActionServlet = builder.toString(); - NewBrowserWindow.open(geoportalExportActionServlet, "_blank", null); + +// Method httpMethod = RequestBuilder.GET; +// RequestBuilder requestBuilder = new RequestBuilder(httpMethod, geoportalExportActionServlet); + + NewBrowserWindow.open(geoportalExportActionServlet, "_blank", ""); + +// try { +// requestBuilder.sendRequest("", new RequestCallback() { +// +// @Override +// public void onResponseReceived(Request request, Response response) { +// newBrowserWindow.setUrl(geoportalExportActionServlet); +// +// } +// +// @Override +// public void onError(Request request, Throwable exception) { +// newBrowserWindow.close(); +// Modal errorModal = new Modal(true, true); +// errorModal.setCloseVisible(true); +// errorModal.setTitle("Oops..."); +// Image geoportalError = new Image(GeoportalImages.ICONS.warningError()); +// FlowPanel errorPanelMsg = new FlowPanel(); +// errorPanelMsg.getElement().addClassName("general_warning"); +// errorPanelMsg.add(geoportalError); +// errorPanelMsg.add(new HTML("D4S GeoPortal")); +// HTML erroMessage = new HTML( +// "Oops something went wrong, error occurred when exporting the project. Error is: " +// + exception.getMessage()); +// errorPanelMsg.add(erroMessage); +// errorModal.add(errorPanelMsg); +// errorModal.show(); +// +// } +// +// }); +// } catch (RequestException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } } }); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java new file mode 100644 index 0000000..86ba370 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java @@ -0,0 +1,31 @@ +package org.gcube.portlets.user.geoportaldataviewer.client.ui.util; + +import com.google.gwt.core.client.JavaScriptObject; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa{@literal @}isti.cnr.it + * Sep 4, 2013 + * + */ +public final class NewBrowserWindow extends JavaScriptObject { + // All types that extend JavaScriptObject must have a protected, + // no-args constructor. + protected NewBrowserWindow() { + } + + public static native NewBrowserWindow open(String url, String target, + String options) /*-{ + return $wnd.open(url, target, options); + }-*/; + + public native void close() /*-{ + this.close(); + }-*/; + + public native void setUrl(String url) /*-{ + if (this.location) { + this.location = url; + } + }-*/; +} + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 85623e5..de4f014 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -21,7 +21,6 @@ import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.GeoportalServiceIdentityProxy; import org.gcube.portlets.user.uriresolvermanager.geoportal.GeoportalExporterAPI; -import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,22 +61,28 @@ public class GeoportalExporterActionServlet extends HttpServlet { String projectID = req.getParameter(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER); String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); String contextID = req.getParameter(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER); - logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + "]"); - - if(contextID==null || contextID.isEmpty()) + String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); + logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + + ", userID: " + userID + "]"); + + if (contextID == null || contextID.isEmpty()) sendError(resp, "Bad Request. No context found!"); - + PortalContext pContext = PortalContext.getConfiguration(); String scope = pContext.getCurrentScope(contextID); logger.info("The scope is {}", scope); - + try { + //Setting header required to {@PortalContext} + MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); + mutableRequest.putHeader(PortalContext.VRE_ID_ATTR_NAME, contextID); + // mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, contextID); ScopeProvider.instance.set(scope); - GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(req); + GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(mutableRequest); String theToken = identity.getToken(); String theIdentity = identity.getIdentity(); logger.info("The identity is {}", theIdentity); - + GeoportalExporterAPI geoportalExporterAPI = new GeoportalExporterAPI(); URL urlRequest = geoportalExporterAPI.exportProject("pdf", ucdID, projectID, false); String urlToRedirect = urlRequest.toString(); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/MutableHttpServletRequest.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/MutableHttpServletRequest.java new file mode 100644 index 0000000..15dde93 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/MutableHttpServletRequest.java @@ -0,0 +1,53 @@ +package org.gcube.portlets.user.geoportaldataviewer.server; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +final class MutableHttpServletRequest extends HttpServletRequestWrapper { + // holds custom header and value mapping + private final Map customHeaders; + + public MutableHttpServletRequest(HttpServletRequest request){ + super(request); + this.customHeaders = new HashMap(); + } + + public void putHeader(String name, String value){ + this.customHeaders.put(name, value); + } + + public String getHeader(String name) { + // check the custom headers first + String headerValue = customHeaders.get(name); + + if (headerValue != null){ + return headerValue; + } + // else return from into the original wrapped object + return ((HttpServletRequest) getRequest()).getHeader(name); + } + + public Enumeration getHeaderNames() { + // create a set of the custom header names + Set set = new HashSet(customHeaders.keySet()); + + // now add the headers from the wrapped request object + @SuppressWarnings("unchecked") + Enumeration e = ((HttpServletRequest) getRequest()).getHeaderNames(); + while (e.hasMoreElements()) { + // add the names of the request headers into the list + String n = e.nextElement(); + set.add(n); + } + + // create an enumeration from the set and return + return Collections.enumeration(set); + } +} \ No newline at end of file -- 2.17.1 From 528c82cae5edd2a5ed9501f3114f82c340649635 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 16:43:34 +0200 Subject: [PATCH 11/28] setting USER_ID_ATTR_NAME --- .../server/GeoportalExporterActionServlet.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index de4f014..633ea00 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -64,6 +64,9 @@ public class GeoportalExporterActionServlet extends HttpServlet { String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + ", userID: " + userID + "]"); + + System.out.println("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + + ", userID: " + userID + "]"); if (contextID == null || contextID.isEmpty()) sendError(resp, "Bad Request. No context found!"); @@ -76,7 +79,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { //Setting header required to {@PortalContext} MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); mutableRequest.putHeader(PortalContext.VRE_ID_ATTR_NAME, contextID); - // mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, contextID); + mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); ScopeProvider.instance.set(scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(mutableRequest); String theToken = identity.getToken(); -- 2.17.1 From 63f168dcf911b87abf2507110a525974e39f24ac Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 16:53:42 +0200 Subject: [PATCH 12/28] updated content-type --- .../client/ui/util/NewBrowserWindow.java | 31 ------------------- .../GeoportalExporterActionServlet.java | 4 +-- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java deleted file mode 100644 index 86ba370..0000000 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/util/NewBrowserWindow.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.gcube.portlets.user.geoportaldataviewer.client.ui.util; - -import com.google.gwt.core.client.JavaScriptObject; - -/** - * @author Francesco Mangiacrapa francesco.mangiacrapa{@literal @}isti.cnr.it - * Sep 4, 2013 - * - */ -public final class NewBrowserWindow extends JavaScriptObject { - // All types that extend JavaScriptObject must have a protected, - // no-args constructor. - protected NewBrowserWindow() { - } - - public static native NewBrowserWindow open(String url, String target, - String options) /*-{ - return $wnd.open(url, target, options); - }-*/; - - public native void close() /*-{ - this.close(); - }-*/; - - public native void setUrl(String url) /*-{ - if (this.location) { - this.location = url; - } - }-*/; -} - diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 633ea00..c6420ca 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -64,9 +64,6 @@ public class GeoportalExporterActionServlet extends HttpServlet { String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + ", userID: " + userID + "]"); - - System.out.println("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID - + ", userID: " + userID + "]"); if (contextID == null || contextID.isEmpty()) sendError(resp, "Bad Request. No context found!"); @@ -93,6 +90,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { logger.info("Token is {}", theToken.substring(0, 20) + "_MASKED_TOKEN"); InputStream is = performHttpRequestToSGService(urlToRedirect, theIdentity, theToken); + resp.setContentType("text/html; charset=utf-8"); IOUtils.copy(is, resp.getOutputStream()); resp.flushBuffer(); -- 2.17.1 From 48111e65258b849eb95fa577ecf57956e79a8ccc Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 29 Apr 2024 17:15:23 +0200 Subject: [PATCH 13/28] updated maven-portal-bom at 3.8.0-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9b9b837..78594a2 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ org.gcube.distribution maven-portal-bom - 3.7.0 + 3.8.0-SNAPSHOT pom import -- 2.17.1 From 473d93ea7b498254863e6e3c8d7e96d9d8ade77f Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 30 Apr 2024 11:09:39 +0200 Subject: [PATCH 14/28] removed unused classes. Refactored class --- .../client/GeoportalDataViewerService.java | 6 +++--- .../client/GeoportalDataViewerServiceAsync.java | 6 +++--- .../geoportaldataviewer/client/LayerManager.java | 14 +++++++------- .../server/GeoportalDataViewerServiceImpl.java | 14 +++++++------- .../server/util/TemporalComparatorUtil.java | 6 +++--- ...ult.java => GeoportalSpatialQueryResult.java} | 12 ++++++------ .../shared/gis/DisplayCategory.java | 16 ---------------- .../shared/gis/OverlayWMSLayer.java | 13 ------------- 8 files changed, 29 insertions(+), 58 deletions(-) rename src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/{GeoNaSpatialQueryResult.java => GeoportalSpatialQueryResult.java} (87%) delete mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/DisplayCategory.java delete mode 100644 src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/OverlayWMSLayer.java diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java index 2f036cf..a6c1a00 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java @@ -14,7 +14,7 @@ import org.gcube.application.geoportalcommon.shared.geoportal.materialization.GC import org.gcube.application.geoportalcommon.shared.geoportal.ucd.GEOPORTAL_DATA_HANDLER; import org.gcube.application.geoportalcommon.shared.geoportal.view.ProjectView; import org.gcube.application.geoportalcommon.shared.gis.BoundsMap; -import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResult; +import org.gcube.portlets.user.geoportaldataviewer.shared.GeoportalSpatialQueryResult; import org.gcube.portlets.user.geoportaldataviewer.shared.ItemFieldsResponse; import org.gcube.portlets.user.geoportaldataviewer.shared.ResultSetPaginatedDataIDs; import org.gcube.portlets.user.geoportaldataviewer.shared.ViewerConfiguration; @@ -57,7 +57,7 @@ public interface GeoportalDataViewerService extends RemoteService { * @return the data result * @throws Exception the exception */ - List getDataResult(List layerObjects, String mapSrsName, BoundsMap mapBBOX, + List getDataResult(List layerObjects, String mapSrsName, BoundsMap mapBBOX, int maxWFSFeature, double zoomLevel) throws Exception; /** @@ -104,7 +104,7 @@ public interface GeoportalDataViewerService extends RemoteService { * @param zoomLevel the zoom level * @return the WFS features */ - List getWFSFeatures(List layerObjects, String mapSrsName, + List getWFSFeatures(List layerObjects, String mapSrsName, BoundsMap selectBBOX, int maxWFSFeature, double zoomLevel); /** diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java index 0db918c..9de222c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java @@ -14,7 +14,7 @@ import org.gcube.application.geoportalcommon.shared.geoportal.materialization.GC import org.gcube.application.geoportalcommon.shared.geoportal.ucd.GEOPORTAL_DATA_HANDLER; import org.gcube.application.geoportalcommon.shared.geoportal.view.ProjectView; import org.gcube.application.geoportalcommon.shared.gis.BoundsMap; -import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResult; +import org.gcube.portlets.user.geoportaldataviewer.shared.GeoportalSpatialQueryResult; import org.gcube.portlets.user.geoportaldataviewer.shared.ItemFieldsResponse; import org.gcube.portlets.user.geoportaldataviewer.shared.ResultSetPaginatedDataIDs; import org.gcube.portlets.user.geoportaldataviewer.shared.ViewerConfiguration; @@ -48,7 +48,7 @@ public interface GeoportalDataViewerServiceAsync { void parseWmsRequest(String wmsRequest, String layerName, AsyncCallback callback); void getDataResult(List layerObjects, String mapSrsName, BoundsMap mapBBOX, int maxWFSFeature, - double zoomLevel, AsyncCallback> callback); + double zoomLevel, AsyncCallback> callback); void getMyLogin(AsyncCallback callback); @@ -60,7 +60,7 @@ public interface GeoportalDataViewerServiceAsync { AsyncCallback> asyncCallback); void getWFSFeatures(List layerObjects, String mapSrsName, BoundsMap selectBBOX, int maxWFSFeature, - double zoomLevel, AsyncCallback> callback); + double zoomLevel, AsyncCallback> callback); void getListBaseLayers(AsyncCallback> callback); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/LayerManager.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/LayerManager.java index e1b02ac..803200e 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/LayerManager.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/LayerManager.java @@ -40,7 +40,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.ModalWindow; import org.gcube.portlets.user.geoportaldataviewer.client.ui.cms.project.ProjectUtil; import org.gcube.portlets.user.geoportaldataviewer.client.util.StringUtil; import org.gcube.portlets.user.geoportaldataviewer.client.util.URLUtil; -import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResult; +import org.gcube.portlets.user.geoportaldataviewer.shared.GeoportalSpatialQueryResult; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.GeoQuery; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.LayerItem; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.LayerObject; @@ -190,7 +190,7 @@ public class LayerManager { GeoportalDataViewerServiceAsync.Util.getInstance().getDataResult(listLO, olMap.getProjectionCode(), mapBBOX, GeoportalDataViewerConstants.MAX_WFS_FEATURES, olMap.getCurrentZoomLevel(), - new AsyncCallback>() { + new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -199,7 +199,7 @@ public class LayerManager { } @Override - public void onSuccess(List listGeonaDataObjects) { + public void onSuccess(List listGeonaDataObjects) { if (listGeonaDataObjects == null) return; @@ -221,7 +221,7 @@ public class LayerManager { List theFeatures = null; // TODO SWTCH FOR EARCH ITEM TYPE - for (final GeoNaSpatialQueryResult geoNaDataObject : listGeonaDataObjects) { + for (final GeoportalSpatialQueryResult geoNaDataObject : listGeonaDataObjects) { GWT.log("GeoNaDataObject: " + geoNaDataObject); List features = geoNaDataObject.getFeatures(); LayerItem layerItem = geoNaDataObject.getSourceLayerObject().getLayerItem(); @@ -709,7 +709,7 @@ public class LayerManager { * @param listGeoNaDataObject the list geo na data object * @param queryClick the query click */ - public void showPopupInfoForLayer(List listGeoNaDataObject, ExtentWrapped queryClick) { + public void showPopupInfoForLayer(List listGeoNaDataObject, ExtentWrapped queryClick) { GWT.log("showPopupInfoForLayer called for " + listGeoNaDataObject); ScrollPanel scrollPanel = new ScrollPanel(); @@ -767,7 +767,7 @@ public class LayerManager { // } String prevProjectId = ""; - for (GeoNaSpatialQueryResult geoNaSpatialQueryResult : listGeoNaDataObject) { + for (GeoportalSpatialQueryResult geoNaSpatialQueryResult : listGeoNaDataObject) { try { Set indexLayers = mapIndexLayerObjects.keySet(); @@ -1123,7 +1123,7 @@ public class LayerManager { * @param feature the feature * @param onFailureCenterTo the on failure center to */ - public void showPopupInfoForCentroidLayer(GeoNaSpatialQueryResult geoNaDataObject, FeatureRow feature, + public void showPopupInfoForCentroidLayer(GeoportalSpatialQueryResult geoNaDataObject, FeatureRow feature, Coordinate onFailureCenterTo) { GWT.log("showPopupInfoForCentroidLayer showing feature: " + feature); GWT.log("showPopupInfoForCentroidLayer showing layerObject: " + geoNaDataObject.getSourceLayerObject()); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java index 3377c89..fb0b08c 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalDataViewerServiceImpl.java @@ -81,7 +81,7 @@ import org.gcube.portlets.user.geoportaldataviewer.server.util.HTTPRequestUtil; import org.gcube.portlets.user.geoportaldataviewer.server.util.SessionUtil; import org.gcube.portlets.user.geoportaldataviewer.server.util.TemporalComparatorUtil; import org.gcube.portlets.user.geoportaldataviewer.shared.GCubeCollection; -import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResult; +import org.gcube.portlets.user.geoportaldataviewer.shared.GeoportalSpatialQueryResult; import org.gcube.portlets.user.geoportaldataviewer.shared.ItemFieldsResponse; import org.gcube.portlets.user.geoportaldataviewer.shared.ResultSetPaginatedDataIDs; import org.gcube.portlets.user.geoportaldataviewer.shared.ViewerConfiguration; @@ -414,14 +414,14 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme * @return the WFS features */ @Override - public List getWFSFeatures(List layerObjects, String mapSrsName, + public List getWFSFeatures(List layerObjects, String mapSrsName, BoundsMap selectBBOX, int maxWFSFeature, double zoomLevel) { LOG.info("getWFSFeatures called"); - List listDAO = new ArrayList(layerObjects.size()); + List listDAO = new ArrayList(layerObjects.size()); for (LayerObject layerObject : layerObjects) { - GeoNaSpatialQueryResult geoDAO = new GeoNaSpatialQueryResult(); + GeoportalSpatialQueryResult geoDAO = new GeoportalSpatialQueryResult(); List features = FeatureParser.getWFSFeatures(layerObject.getLayerItem(), mapSrsName, selectBBOX, maxWFSFeature); LOG.debug("For layer name: " + layerObject.getLayerItem().getName() + " got features: " + features); @@ -1199,7 +1199,7 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme * @throws Exception the exception */ @Override - public List getDataResult(List layerObjects, String mapSrsName, + public List getDataResult(List layerObjects, String mapSrsName, BoundsMap selectBBOX, int maxWFSFeature, double zoomLevel) throws Exception { LOG.info("getDataResult called"); @@ -1214,13 +1214,13 @@ public class GeoportalDataViewerServiceImpl extends RemoteServiceServlet impleme + ", zoomLevel: " + zoomLevel); } - List listDAO = new ArrayList(layerObjects.size()); + List listDAO = new ArrayList(layerObjects.size()); try { new GeoportalServiceIdentityProxy(this.getThreadLocalRequest()); for (LayerObject layerObject : layerObjects) { - GeoNaSpatialQueryResult geoDAO = new GeoNaSpatialQueryResult(); + GeoportalSpatialQueryResult geoDAO = new GeoportalSpatialQueryResult(); List features = FeatureParser.getWFSFeatures(layerObject.getLayerItem(), mapSrsName, selectBBOX, maxWFSFeature); LOG.debug("For layer name: " + layerObject.getLayerItem().getName() + " got features: " + features); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/TemporalComparatorUtil.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/TemporalComparatorUtil.java index d4ccad0..e0c29dd 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/TemporalComparatorUtil.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/util/TemporalComparatorUtil.java @@ -3,7 +3,7 @@ package org.gcube.portlets.user.geoportaldataviewer.server.util; import java.util.Comparator; import org.gcube.application.geoportalcommon.shared.geoportal.project.ProjectDV; -import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResult; +import org.gcube.portlets.user.geoportaldataviewer.shared.GeoportalSpatialQueryResult; /** * The Class TemporalComparatorUtil. @@ -12,7 +12,7 @@ import org.gcube.portlets.user.geoportaldataviewer.shared.GeoNaSpatialQueryResul * * Nov 18, 2022 */ -public class TemporalComparatorUtil implements Comparator { +public class TemporalComparatorUtil implements Comparator { /** * Compare. @@ -22,7 +22,7 @@ public class TemporalComparatorUtil implements Comparator features; private LayerObject sourceLayerObject; - // Map with couple (mongoId concessione, list of uploaded GeoportalImages for the - // concessione) + // Map with couple (mongoId project, list of uploaded GeoportalImages for the + // project) private Map> mapImages = null; /** * Instantiates a new geo na data object. */ - public GeoNaSpatialQueryResult() { + public GeoportalSpatialQueryResult() { } @@ -91,7 +91,7 @@ public class GeoNaSpatialQueryResult implements Serializable { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("GeoNaSpatialQueryResult [features="); + builder.append("GeoportalSpatialQueryResult [features="); builder.append(features); builder.append(", sourceLayerObject="); builder.append(sourceLayerObject); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/DisplayCategory.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/DisplayCategory.java deleted file mode 100644 index 030ab3f..0000000 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/DisplayCategory.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.gcube.portlets.user.geoportaldataviewer.shared.gis; - -import java.io.Serializable; - -import lombok.Data; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@Data -public class DisplayCategory implements Serializable { - - - String title; - String description; - -} diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/OverlayWMSLayer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/OverlayWMSLayer.java deleted file mode 100644 index 6707121..0000000 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/OverlayWMSLayer.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.gcube.portlets.user.geoportaldataviewer.shared.gis; - -import java.util.Map; - -public class OverlayWMSLayer { - - private String title; - private String name; - private String wmsServiceBaseURL; - private boolean display; - private Map mapProperties; - -} -- 2.17.1 From aa8a9c931fc370bb785d911cc7db22f5e2f2c3c4 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 30 Apr 2024 11:45:16 +0200 Subject: [PATCH 15/28] updated parameters --- .../client/GeoportalDataViewerConstants.java | 4 ++-- .../client/ui/cms/project/ProjectViewer.java | 14 ++------------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index d50a288..5393d96 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -19,8 +19,8 @@ public class GeoportalDataViewerConstants { //Geoportal_Exporter_ACTION_SERVLET public static final String UCD_ID_PARAMETER = "ucdID"; public static final String PROIECT_ID_PARAMETER = "projectID"; - public static final String CONTEXT_ID_PARAMETER = "contex_id"; - public static final String USER_ID_PARAMETER = "user_id"; + public static final String CONTEXT_ID_PARAMETER = "c_id"; + public static final String USER_ID_PARAMETER = "u_id"; public static final String GEOPORTAL_EXPORT_ACTION_SERVLET = GWT.getModuleBaseURL() + "geoportalexporterservice"; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 12e8304..c582248 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -15,7 +15,6 @@ import org.gcube.portlets.user.geoportaldataviewer.client.events.AddLayerToMapEv import org.gcube.portlets.user.geoportaldataviewer.client.events.TimelineProjectRelationsEvent; import org.gcube.portlets.user.geoportaldataviewer.client.events.TimelineProjectRelationsEvent.EVENT_TYPE; import org.gcube.portlets.user.geoportaldataviewer.client.gis.MapUtils; -import org.gcube.portlets.user.geoportaldataviewer.client.resources.GeoportalImages; import org.gcube.portlets.user.geoportaldataviewer.client.ui.ModalWindow; import org.gcube.portlets.user.geoportaldataviewer.client.ui.dialogs.DialogShareableLink; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil; @@ -25,7 +24,6 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; import org.gcube.portlets.user.geoportaldataviewer.client.util.NewBrowserWindow; import com.github.gwtbootstrap.client.ui.Button; -import com.github.gwtbootstrap.client.ui.Modal; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.google.gwt.core.client.GWT; @@ -33,22 +31,14 @@ import com.google.gwt.dom.client.UListElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.shared.HandlerManager; -import com.google.gwt.http.client.Request; -import com.google.gwt.http.client.RequestBuilder; -import com.google.gwt.http.client.RequestBuilder.Method; -import com.google.gwt.http.client.RequestCallback; -import com.google.gwt.http.client.RequestException; -import com.google.gwt.http.client.Response; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; -import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; import ol.Coordinate; @@ -162,7 +152,7 @@ public class ProjectViewer extends Composite { @Override public void onSuccess(Boolean result) { GWT.log("Export as PDF visible: " + result); - exportButton.setVisible(result); + exportButton.setEnabled(result); } }); @@ -217,7 +207,7 @@ public class ProjectViewer extends Composite { exportButton.setType(ButtonType.LINK); exportButton.setIcon(IconType.FILE); exportButton.setTitle("Export as PDF"); - exportButton.setVisible(false); + exportButton.setEnabled(false); exportButton.addClickHandler(new ClickHandler() { -- 2.17.1 From 269592914feccd24f94d05bc180d409d13d2bab9 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 11:41:34 +0200 Subject: [PATCH 16/28] added setVisible to Export button --- .settings/org.eclipse.wst.common.component | 46 +++++++++++++++---- .../client/ui/cms/project/ProjectViewer.java | 44 ++---------------- 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index b83d38d..07d3f48 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,7 @@ - + + + @@ -129,7 +131,9 @@ - + + + @@ -259,7 +263,9 @@ - + + + @@ -389,7 +395,9 @@ - + + + @@ -519,7 +527,9 @@ - + + + @@ -649,7 +659,9 @@ - + + + @@ -668,10 +680,18 @@ uses + + uses + + + uses + uses - + + + @@ -801,7 +821,9 @@ - + + + @@ -931,7 +953,9 @@ - + + + @@ -1061,7 +1085,9 @@ - + + + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index c582248..0ecf7e1 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -152,7 +152,7 @@ public class ProjectViewer extends Composite { @Override public void onSuccess(Boolean result) { GWT.log("Export as PDF visible: " + result); - exportButton.setEnabled(result); + exportButton.setVisible(result); } }); @@ -207,7 +207,7 @@ public class ProjectViewer extends Composite { exportButton.setType(ButtonType.LINK); exportButton.setIcon(IconType.FILE); exportButton.setTitle("Export as PDF"); - exportButton.setEnabled(false); + exportButton.setVisible(false); exportButton.addClickHandler(new ClickHandler() { @@ -240,46 +240,8 @@ public class ProjectViewer extends Composite { builder.append(GeoportalDataViewerConstants.USER_ID_PARAMETER + "=" + currentUserId); String geoportalExportActionServlet = builder.toString(); - -// Method httpMethod = RequestBuilder.GET; -// RequestBuilder requestBuilder = new RequestBuilder(httpMethod, geoportalExportActionServlet); - + NewBrowserWindow.open(geoportalExportActionServlet, "_blank", ""); - -// try { -// requestBuilder.sendRequest("", new RequestCallback() { -// -// @Override -// public void onResponseReceived(Request request, Response response) { -// newBrowserWindow.setUrl(geoportalExportActionServlet); -// -// } -// -// @Override -// public void onError(Request request, Throwable exception) { -// newBrowserWindow.close(); -// Modal errorModal = new Modal(true, true); -// errorModal.setCloseVisible(true); -// errorModal.setTitle("Oops..."); -// Image geoportalError = new Image(GeoportalImages.ICONS.warningError()); -// FlowPanel errorPanelMsg = new FlowPanel(); -// errorPanelMsg.getElement().addClassName("general_warning"); -// errorPanelMsg.add(geoportalError); -// errorPanelMsg.add(new HTML("D4S GeoPortal")); -// HTML erroMessage = new HTML( -// "Oops something went wrong, error occurred when exporting the project. Error is: " -// + exception.getMessage()); -// errorPanelMsg.add(erroMessage); -// errorModal.add(errorPanelMsg); -// errorModal.show(); -// -// } -// -// }); -// } catch (RequestException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } } }); -- 2.17.1 From 7d3e9544f55b6eaf4a61c40dda2bb8faf6a94d30 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 11:45:18 +0200 Subject: [PATCH 17/28] added log --- .../mongoservice/accessidentity/IAMClientIdentity.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java index ca51ff2..2239279 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java @@ -18,7 +18,7 @@ public class IAMClientIdentity implements GcubeIdentity { private String previousUMAToken = null; private String currentUMAToken = null; - + private String clientId = null; private static final String IAM_CLIENT_CREDENTIALS = "IAM_CLIENT_CREDENTIALS"; @@ -27,6 +27,7 @@ public class IAMClientIdentity implements GcubeIdentity { public void setIdentity(HttpServletRequest httpRequest) throws Exception { LOG.info("setIdentity called"); String currentScope = SessionUtil.getCurrentContext(httpRequest, true); + LOG.info("the scope is {}", currentScope); IAMClientCredentials credentials = sessionGetIAMClientCredentials(httpRequest); try { if (credentials == null) { @@ -126,8 +127,8 @@ public class IAMClientIdentity implements GcubeIdentity { @Override public String getIdentityDescription() { - return "ClientId: "+ clientId; - + return "ClientId: " + clientId; + } @Override -- 2.17.1 From ee4524139ec15514b569b96abf0d8176547f6b29 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 15:43:10 +0200 Subject: [PATCH 18/28] Passed to the new KC-client [#27398] --- .settings/org.eclipse.wst.common.component | 3 --- CHANGELOG.md | 1 + .../GeoportalExporterActionServlet.java | 25 ++++++++++++++++--- .../accessidentity/IAMClientIdentity.java | 3 ++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 07d3f48..70af32e 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -677,9 +677,6 @@ - - uses - uses diff --git a/CHANGELOG.md b/CHANGELOG.md index b879504..75381e7 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 - Provided the "Export as PDF" facility [#26026] - Integrated the GeoportalExporter as service [#27321] +- Passed to the new KC-client [#27398] ## [v3.6.0] diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index c6420ca..7a94346 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -57,6 +57,17 @@ public class GeoportalExporterActionServlet extends HttpServlet { * @throws ServletException the servlet exception */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + serveRequest(req, resp); + } + + /** + * Serve request. + * + * @param req the req + * @param resp the resp + * @throws IOException Signals that an I/O exception has occurred. + */ + public void serveRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException { // setSecretManager(); String projectID = req.getParameter(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER); String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); @@ -73,7 +84,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { logger.info("The scope is {}", scope); try { - //Setting header required to {@PortalContext} + // Setting header required to {@PortalContext} MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); mutableRequest.putHeader(PortalContext.VRE_ID_ATTR_NAME, contextID); mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); @@ -86,7 +97,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { GeoportalExporterAPI geoportalExporterAPI = new GeoportalExporterAPI(); URL urlRequest = geoportalExporterAPI.exportProject("pdf", ucdID, projectID, false); String urlToRedirect = urlRequest.toString(); - logger.info("Performing request to {} with identity {}", urlToRedirect, identity.getDescription()); + logger.info("Performing request to {} with identity description {}", urlToRedirect, identity.getDescription()); logger.info("Token is {}", theToken.substring(0, 20) + "_MASKED_TOKEN"); InputStream is = performHttpRequestToSGService(urlToRedirect, theIdentity, theToken); @@ -99,9 +110,17 @@ public class GeoportalExporterActionServlet extends HttpServlet { sendError(resp, "Error occurred when exporting the Project. Error is: " + e.getMessage()); return; } - } + /** + * Perform http request to SG service. + * + * @param urlToService the url to service + * @param identity the identity + * @param token the token + * @return the input stream + * @throws IOException Signals that an I/O exception has occurred. + */ public static InputStream performHttpRequestToSGService(String urlToService, String identity, String token) throws IOException { logger.debug("performHttpRequestToSGService called"); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java index 2239279..39b577b 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java @@ -46,8 +46,9 @@ public class IAMClientIdentity implements GcubeIdentity { try { LOG.info("Querying KeycloakClientFactory to get UMA token.."); - TokenResponse tr = KeycloakClientFactory.newInstance().queryUMAToken(clientId, clientSecret, currentScope, + TokenResponse tr = KeycloakClientFactory.newInstance().queryUMAToken(currentScope, clientId, clientSecret, currentScope, null); + umaAcessToken = tr.getAccessToken(); if (umaAcessToken != null && !umaAcessToken.isEmpty()) { LOG.info("UMA Access Token read correctly"); -- 2.17.1 From 0224f787c1bd9c8990dc33c9b68301cf2cf0cb29 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 3 May 2024 17:03:26 +0200 Subject: [PATCH 19/28] Moved to doPost method --- .../client/ui/cms/project/ProjectViewer.java | 69 +++++++++++++++---- .../GeoportalExporterActionServlet.java | 29 +++++--- 2 files changed, 73 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 0ecf7e1..f3ac8ec 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -4,6 +4,7 @@ import java.util.List; import org.gcube.application.geoportalcommon.shared.GeoportalItemReferences; import org.gcube.application.geoportalcommon.shared.geoportal.geojson.GeoJSON; +import org.gcube.application.geoportalcommon.shared.geoportal.project.ProjectDV; import org.gcube.application.geoportalcommon.shared.geoportal.project.RelationshipDV; import org.gcube.application.geoportalcommon.shared.geoportal.view.ProjectView; import org.gcube.application.geoportalcommon.shared.geoportal.view.SectionView; @@ -37,8 +38,14 @@ import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Hidden; +import com.google.gwt.user.client.ui.RootPanel; +import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import ol.Coordinate; @@ -227,21 +234,55 @@ public class ProjectViewer extends Composite { String currentContextId = GCubeClientContext.getCurrentContextId(); String currentUserId = GCubeClientContext.getCurrentUserId(); - StringBuilder builder = new StringBuilder(); - builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + "?"); - builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" - + projectView.getTheProjectDV().getProfileID()); - builder.append("&"); - builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" - + projectView.getTheProjectDV().getId()); - builder.append("&"); - builder.append(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER + "=" + currentContextId); - builder.append("&"); - builder.append(GeoportalDataViewerConstants.USER_ID_PARAMETER + "=" + currentUserId); + /* + * USE TO GET REQUEST StringBuilder builder = new StringBuilder(); + * builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + + * "?"); builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" + + * projectView.getTheProjectDV().getProfileID()); builder.append("&"); + * builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" + + * projectView.getTheProjectDV().getId()); builder.append("&"); + * builder.append(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER + "=" + + * currentContextId); builder.append("&"); + * builder.append(GeoportalDataViewerConstants.USER_ID_PARAMETER + "=" + + * currentUserId); + * + * String geoportalExportActionServlet = builder.toString(); + * + * NewBrowserWindow.open(geoportalExportActionServlet, "_blank", ""); + */ + + ProjectDV thePDV = projectView.getTheProjectDV(); + + final String targetWindow = "target_window_" + Random.nextInt() + "_" + Random.nextInt(); + + final FormPanel form = new FormPanel(targetWindow); + RootPanel.get().add(form); + VerticalPanel panel = new VerticalPanel(); + form.setWidget(panel); + form.setAction(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET); + form.setEncoding(FormPanel.ENCODING_URLENCODED); + form.setMethod(FormPanel.METHOD_POST); + panel.add(new Hidden(GeoportalDataViewerConstants.UCD_ID_PARAMETER, thePDV.getProfileID())); + panel.add(new Hidden(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER, thePDV.getId())); + panel.add(new Hidden(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER, currentContextId)); + panel.add(new Hidden(GeoportalDataViewerConstants.USER_ID_PARAMETER, currentUserId)); + + // Add an event handler to the form. + form.addSubmitHandler(new FormPanel.SubmitHandler() { + public void onSubmit(SubmitEvent event) { + GWT.log("onSubmit done"); + NewBrowserWindow.open("", targetWindow, null); + } + }); + form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { + public void onSubmitComplete(SubmitCompleteEvent event) { + GWT.log("onSubmitComplete done"); + + } + }); + + form.submit(); - String geoportalExportActionServlet = builder.toString(); - - NewBrowserWindow.open(geoportalExportActionServlet, "_blank", ""); } }); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 7a94346..24fb61a 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -47,19 +47,26 @@ public class GeoportalExporterActionServlet extends HttpServlet { super.init(); logger.trace(GeoportalExporterActionServlet.class.getSimpleName() + " ready."); } - - /** - * Do get. - * - * @param req the req - * @param resp the resp - * @throws IOException Signals that an I/O exception has occurred. - * @throws ServletException the servlet exception - */ - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + logger.info("doPost Called"); serveRequest(req, resp); } +// /** +// * Do get. +// * +// * @param req the req +// * @param resp the resp +// * @throws IOException Signals that an I/O exception has occurred. +// * @throws ServletException the servlet exception +// */ +// public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { +// logger.info("doGet Called"); +// serveRequest(req, resp); +// } + /** * Serve request. * @@ -73,7 +80,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); String contextID = req.getParameter(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER); String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); - logger.info("doGet called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID + ", userID: " + userID + "]"); if (contextID == null || contextID.isEmpty()) -- 2.17.1 From 7c1f0ad8290fa7d9b1fa6bf5901d158c2716ce07 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 6 May 2024 11:41:28 +0200 Subject: [PATCH 20/28] updated Export facility --- .../client/GeoportalDataViewerService.java | 7 ++---- .../GeoportalDataViewerServiceAsync.java | 3 --- .../client/ui/cms/project/ProjectViewer.java | 16 +++++++++++-- .../GeoportalExporterActionServlet.java | 24 +++++++++---------- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java index a6c1a00..b15ff1a 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerService.java @@ -57,8 +57,8 @@ public interface GeoportalDataViewerService extends RemoteService { * @return the data result * @throws Exception the exception */ - List getDataResult(List layerObjects, String mapSrsName, BoundsMap mapBBOX, - int maxWFSFeature, double zoomLevel) throws Exception; + List getDataResult(List layerObjects, String mapSrsName, + BoundsMap mapBBOX, int maxWFSFeature, double zoomLevel) throws Exception; /** * Gets the my login. @@ -231,7 +231,4 @@ public interface GeoportalDataViewerService extends RemoteService { Boolean checkExportAsPDFConfig(); -// String exportAsPDF(String profileID, String projectID, String profileTitle, -// GeoportalItemReferences geoportalItemReferences); - } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java index 9de222c..a6efc52 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerServiceAsync.java @@ -95,7 +95,4 @@ public interface GeoportalDataViewerServiceAsync { void checkExportAsPDFConfig(AsyncCallback callback); -// void exportAsPDF(String profileID, String projectID, String profileTitle, -// GeoportalItemReferences geoportalItemReferences, AsyncCallback callback); - } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index f3ac8ec..fa571f4 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -25,6 +25,7 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; import org.gcube.portlets.user.geoportaldataviewer.client.util.NewBrowserWindow; import com.github.gwtbootstrap.client.ui.Button; +import com.github.gwtbootstrap.client.ui.Modal; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.google.gwt.core.client.GWT; @@ -38,6 +39,7 @@ import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; @@ -266,16 +268,26 @@ public class ProjectViewer extends Composite { panel.add(new Hidden(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER, thePDV.getId())); panel.add(new Hidden(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER, currentContextId)); panel.add(new Hidden(GeoportalDataViewerConstants.USER_ID_PARAMETER, currentUserId)); - + + final Modal contactinServiceModal = new Modal(true, true); + contactinServiceModal.setCloseVisible(false); + contactinServiceModal.setTitle("Export"); + FlowPanel panelMsg = new FlowPanel(); + panelMsg.add(new HTML("Contacting the service...")); + contactinServiceModal.add(panelMsg); + contactinServiceModal.show(); + // Add an event handler to the form. form.addSubmitHandler(new FormPanel.SubmitHandler() { public void onSubmit(SubmitEvent event) { GWT.log("onSubmit done"); - NewBrowserWindow.open("", targetWindow, null); + contactinServiceModal.hide(); } }); form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { public void onSubmitComplete(SubmitCompleteEvent event) { + contactinServiceModal.hide(); + NewBrowserWindow.open("", targetWindow, null); GWT.log("onSubmitComplete done"); } diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 24fb61a..964380e 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -54,18 +54,18 @@ public class GeoportalExporterActionServlet extends HttpServlet { serveRequest(req, resp); } -// /** -// * Do get. -// * -// * @param req the req -// * @param resp the resp -// * @throws IOException Signals that an I/O exception has occurred. -// * @throws ServletException the servlet exception -// */ -// public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { -// logger.info("doGet Called"); -// serveRequest(req, resp); -// } + /** + * Do get. + * + * @param req the req + * @param resp the resp + * @throws IOException Signals that an I/O exception has occurred. + * @throws ServletException the servlet exception + */ + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + logger.info("doGet Called"); + sendError(resp, "The request cannot be served (via http GET). Please retry by using the Export facility provided by Data-Viewer UI"); + } /** * Serve request. -- 2.17.1 From 13c271ca3709b865a79f630bc738d98abd314bc3 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 6 May 2024 12:03:41 +0200 Subject: [PATCH 21/28] updated logs --- .../accessidentity/IAMClientIdentity.java | 11 +++++------ .../mongoservice/accessidentity/UserIdentity.java | 6 +++--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java index 39b577b..498e8dc 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/IAMClientIdentity.java @@ -40,7 +40,6 @@ public class IAMClientIdentity implements GcubeIdentity { } LOG.trace("Read credentials: " + credentials); - String umaAcessToken = null; clientId = credentials.getClientId(); String clientSecret = credentials.getClientSecret(); try { @@ -49,10 +48,9 @@ public class IAMClientIdentity implements GcubeIdentity { TokenResponse tr = KeycloakClientFactory.newInstance().queryUMAToken(currentScope, clientId, clientSecret, currentScope, null); - umaAcessToken = tr.getAccessToken(); - if (umaAcessToken != null && !umaAcessToken.isEmpty()) { + currentUMAToken = tr.getAccessToken(); + if (currentUMAToken != null && !currentUMAToken.isEmpty()) { LOG.info("UMA Access Token read correctly"); - currentUMAToken = umaAcessToken; } else { LOG.error("UMA Access Token NOT RETRIEVED!!!"); throw new Exception("UMA Access Token is null or empty"); @@ -63,6 +61,8 @@ public class IAMClientIdentity implements GcubeIdentity { try { + LOG.debug("JWT token: " + currentUMAToken.substring(0, 20) + "_MASKED_TOKEN_"); + try { // Here the previousUMAToken should be null previousUMAToken = AccessTokenProvider.instance.get(); @@ -71,10 +71,9 @@ public class IAMClientIdentity implements GcubeIdentity { // silent } - LOG.debug("JWT token: " + umaAcessToken.substring(0, 20) + "_MASKED_TOKEN_"); LOG.info("Setting clientId '" + clientId + "' identity by JWT token in the " + AccessTokenProvider.class.getSimpleName()); - AccessTokenProvider.instance.set(umaAcessToken); + AccessTokenProvider.instance.set(currentUMAToken); } catch (Exception e) { LOG.error(e.getMessage(), e); throw new Exception(e.getMessage()); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java index 3a6f79f..1b73b53 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/mongoservice/accessidentity/UserIdentity.java @@ -22,8 +22,8 @@ public class UserIdentity implements GcubeIdentity { public void setIdentity(HttpServletRequest httpRequest) throws Exception { LOG.info("setIdentity called"); this.httpRequest = httpRequest; - SessionUtil.getCurrentToken(httpRequest, true); - user = SessionUtil.getCurrentUser(httpRequest); + SessionUtil.getCurrentToken(this.httpRequest, true); + user = SessionUtil.getCurrentUser(this.httpRequest); } @@ -35,7 +35,7 @@ public class UserIdentity implements GcubeIdentity { @Override public String getToken() { - return SessionUtil.getCurrentToken(httpRequest, true); + return SessionUtil.getCurrentToken(this.httpRequest, true); } @Override -- 2.17.1 From 9ec3696203354d91a8f4d0a2a118300a0087ff38 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 6 May 2024 12:31:13 +0200 Subject: [PATCH 22/28] no putting user header in Production mode --- .../GeoportalExporterActionServlet.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 964380e..19ff71e 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -20,6 +20,7 @@ import org.gcube.common.portal.PortalContext; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants; import org.gcube.portlets.user.geoportaldataviewer.server.mongoservice.GeoportalServiceIdentityProxy; +import org.gcube.portlets.user.geoportaldataviewer.server.util.SessionUtil; import org.gcube.portlets.user.uriresolvermanager.geoportal.GeoportalExporterAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +48,7 @@ public class GeoportalExporterActionServlet extends HttpServlet { super.init(); logger.trace(GeoportalExporterActionServlet.class.getSimpleName() + " ready."); } - + @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { logger.info("doPost Called"); @@ -64,7 +65,8 @@ public class GeoportalExporterActionServlet extends HttpServlet { */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { logger.info("doGet Called"); - sendError(resp, "The request cannot be served (via http GET). Please retry by using the Export facility provided by Data-Viewer UI"); + sendError(resp, + "The request cannot be served (via http GET). Please retry by using the Export facility provided by Data-Viewer UI"); } /** @@ -80,8 +82,9 @@ public class GeoportalExporterActionServlet extends HttpServlet { String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); String contextID = req.getParameter(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER); String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); - logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID - + ", userID: " + userID + "]"); +// logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID+"]"); + logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + + contextID + ", userID: " + userID + "]"); if (contextID == null || contextID.isEmpty()) sendError(resp, "Bad Request. No context found!"); @@ -94,7 +97,10 @@ public class GeoportalExporterActionServlet extends HttpServlet { // Setting header required to {@PortalContext} MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); mutableRequest.putHeader(PortalContext.VRE_ID_ATTR_NAME, contextID); - mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); + if (!SessionUtil.isIntoPortal()) { + logger.info("DEBUG MODE, putting header "+PortalContext.USER_ID_ATTR_NAME); + mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); + } ScopeProvider.instance.set(scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(mutableRequest); String theToken = identity.getToken(); @@ -104,7 +110,8 @@ public class GeoportalExporterActionServlet extends HttpServlet { GeoportalExporterAPI geoportalExporterAPI = new GeoportalExporterAPI(); URL urlRequest = geoportalExporterAPI.exportProject("pdf", ucdID, projectID, false); String urlToRedirect = urlRequest.toString(); - logger.info("Performing request to {} with identity description {}", urlToRedirect, identity.getDescription()); + logger.info("Performing request to {} with identity description {}", urlToRedirect, + identity.getDescription()); logger.info("Token is {}", theToken.substring(0, 20) + "_MASKED_TOKEN"); InputStream is = performHttpRequestToSGService(urlToRedirect, theIdentity, theToken); -- 2.17.1 From 3aa7f6462f5b7f4cbad768f6b05fa9020e2f7e3e Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Mon, 6 May 2024 14:41:58 +0200 Subject: [PATCH 23/28] updated form submit --- .../client/ui/cms/project/ProjectViewer.java | 36 ++++++------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index fa571f4..e1d67f2 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -22,13 +22,13 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.Location; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.PLACE; import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; -import org.gcube.portlets.user.geoportaldataviewer.client.util.NewBrowserWindow; import com.github.gwtbootstrap.client.ui.Button; import com.github.gwtbootstrap.client.ui.Modal; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.FormElement; import com.google.gwt.dom.client.UListElement; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; @@ -42,7 +42,9 @@ import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; +import com.google.gwt.user.client.ui.FormPanel.SubmitHandler; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Hidden; @@ -236,28 +238,13 @@ public class ProjectViewer extends Composite { String currentContextId = GCubeClientContext.getCurrentContextId(); String currentUserId = GCubeClientContext.getCurrentUserId(); - /* - * USE TO GET REQUEST StringBuilder builder = new StringBuilder(); - * builder.append(GeoportalDataViewerConstants.GEOPORTAL_EXPORT_ACTION_SERVLET + - * "?"); builder.append(GeoportalDataViewerConstants.UCD_ID_PARAMETER + "=" + - * projectView.getTheProjectDV().getProfileID()); builder.append("&"); - * builder.append(GeoportalDataViewerConstants.PROIECT_ID_PARAMETER + "=" + - * projectView.getTheProjectDV().getId()); builder.append("&"); - * builder.append(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER + "=" + - * currentContextId); builder.append("&"); - * builder.append(GeoportalDataViewerConstants.USER_ID_PARAMETER + "=" + - * currentUserId); - * - * String geoportalExportActionServlet = builder.toString(); - * - * NewBrowserWindow.open(geoportalExportActionServlet, "_blank", ""); - */ - ProjectDV thePDV = projectView.getTheProjectDV(); final String targetWindow = "target_window_" + Random.nextInt() + "_" + Random.nextInt(); - final FormPanel form = new FormPanel(targetWindow); + final FormPanel form = new FormPanel(); + final FormElement fe = form.getElement().cast(); + //NewBrowserWindow theNewTabWindow = NewBrowserWindow.open("", "", null); RootPanel.get().add(form); VerticalPanel panel = new VerticalPanel(); form.setWidget(panel); @@ -278,18 +265,17 @@ public class ProjectViewer extends Composite { contactinServiceModal.show(); // Add an event handler to the form. - form.addSubmitHandler(new FormPanel.SubmitHandler() { + form.addSubmitHandler(new SubmitHandler() { public void onSubmit(SubmitEvent event) { GWT.log("onSubmit done"); - contactinServiceModal.hide(); + fe.setTarget(targetWindow); } }); - form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() { + + form.addSubmitCompleteHandler(new SubmitCompleteHandler() { public void onSubmitComplete(SubmitCompleteEvent event) { - contactinServiceModal.hide(); - NewBrowserWindow.open("", targetWindow, null); GWT.log("onSubmitComplete done"); - + contactinServiceModal.hide(); } }); -- 2.17.1 From 3e568b58b411090790a1a4da3ec8a3b5224a5d5d Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 7 May 2024 12:45:29 +0200 Subject: [PATCH 24/28] Managed USERNAME parameter to perform the request to exporter service on behalf of the user. --- .settings/org.eclipse.wst.common.component | 33 +++++++++++-------- .../client/GeoportalDataViewerConstants.java | 1 + .../client/ui/cms/project/ProjectViewer.java | 12 +++---- .../GeoportalExporterActionServlet.java | 14 ++++++-- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 70af32e..cb65c69 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -131,7 +132,8 @@ - + + @@ -263,7 +265,8 @@ - + + @@ -395,7 +398,8 @@ - + + @@ -527,7 +531,8 @@ - + + @@ -659,7 +664,8 @@ - + + @@ -683,10 +689,8 @@ uses - - uses - - + + @@ -818,7 +822,8 @@ - + + @@ -950,7 +955,8 @@ - + + @@ -1082,7 +1088,8 @@ - + + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java index 5393d96..1930735 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/GeoportalDataViewerConstants.java @@ -21,6 +21,7 @@ public class GeoportalDataViewerConstants { public static final String PROIECT_ID_PARAMETER = "projectID"; public static final String CONTEXT_ID_PARAMETER = "c_id"; public static final String USER_ID_PARAMETER = "u_id"; + public static final String USERNAME_PARAMETER = "usn"; public static final String GEOPORTAL_EXPORT_ACTION_SERVLET = GWT.getModuleBaseURL() + "geoportalexporterservice"; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index e1d67f2..d4bcb2a 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -256,6 +256,10 @@ public class ProjectViewer extends Composite { panel.add(new Hidden(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER, currentContextId)); panel.add(new Hidden(GeoportalDataViewerConstants.USER_ID_PARAMETER, currentUserId)); + if(myLogin!=null) { + panel.add(new Hidden(GeoportalDataViewerConstants.USERNAME_PARAMETER, myLogin)); + } + final Modal contactinServiceModal = new Modal(true, true); contactinServiceModal.setCloseVisible(false); contactinServiceModal.setTitle("Export"); @@ -341,14 +345,6 @@ public class ProjectViewer extends Composite { public void onClick(ClickEvent event) { boolean visible = toc_list_container.isVisible(); setTocContentVisible(!visible); - -// if (visible) { -// toc_list_container.setVisible(false); -// reduceToc.setIcon(IconType.PLUS_SIGN_ALT); -// } else { -// toc_list_container.setVisible(true); -// reduceToc.setIcon(IconType.MINUS_SIGN_ALT); -// } } }); diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java index 19ff71e..4f183db 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/server/GeoportalExporterActionServlet.java @@ -82,9 +82,10 @@ public class GeoportalExporterActionServlet extends HttpServlet { String ucdID = req.getParameter(GeoportalDataViewerConstants.UCD_ID_PARAMETER); String contextID = req.getParameter(GeoportalDataViewerConstants.CONTEXT_ID_PARAMETER); String userID = req.getParameter(GeoportalDataViewerConstants.USER_ID_PARAMETER); + String username = req.getParameter(GeoportalDataViewerConstants.USERNAME_PARAMETER); // logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " + contextID+"]"); logger.info("serveRequest called with [projectID: " + projectID + ", ucdID: " + ucdID + ", contextID: " - + contextID + ", userID: " + userID + "]"); + + contextID + ", userID: " + userID + ", username: " + username + "]"); if (contextID == null || contextID.isEmpty()) sendError(resp, "Bad Request. No context found!"); @@ -97,10 +98,19 @@ public class GeoportalExporterActionServlet extends HttpServlet { // Setting header required to {@PortalContext} MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(req); mutableRequest.putHeader(PortalContext.VRE_ID_ATTR_NAME, contextID); + // DEV MODE if (!SessionUtil.isIntoPortal()) { - logger.info("DEBUG MODE, putting header "+PortalContext.USER_ID_ATTR_NAME); + logger.info("DEBUG MODE, putting header " + PortalContext.USER_ID_ATTR_NAME); mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); } + + // IF USERNAME exists, add the userID to request. So performing the request to + // exporter service on behalf of the user. + if (username != null) { + logger.info("Username found, putting header " + PortalContext.USER_ID_ATTR_NAME); + mutableRequest.putHeader(PortalContext.USER_ID_ATTR_NAME, userID); + } + ScopeProvider.instance.set(scope); GeoportalServiceIdentityProxy identity = new GeoportalServiceIdentityProxy(mutableRequest); String theToken = identity.getToken(); -- 2.17.1 From 8bcda493daf5ceaa1bf8c40b6563c8a2ee7c41e7 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Wed, 8 May 2024 12:10:32 +0200 Subject: [PATCH 25/28] commented modal on Export facility --- .settings/org.eclipse.wst.common.component | 36 ++++++++++--------- .../client/ui/cms/project/ProjectViewer.java | 16 ++++----- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index cb65c69..27ca07b 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,6 @@ - + + @@ -132,7 +133,8 @@ - + + @@ -265,7 +267,8 @@ - + + @@ -398,7 +401,8 @@ - + + @@ -531,7 +535,8 @@ - + + @@ -664,7 +669,8 @@ - + + @@ -683,13 +689,8 @@ - - uses - - - uses - - + + @@ -822,7 +823,8 @@ - + + @@ -955,7 +957,8 @@ - + + @@ -1088,7 +1091,8 @@ - + + diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index d4bcb2a..2866439 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -260,13 +260,13 @@ public class ProjectViewer extends Composite { panel.add(new Hidden(GeoportalDataViewerConstants.USERNAME_PARAMETER, myLogin)); } - final Modal contactinServiceModal = new Modal(true, true); - contactinServiceModal.setCloseVisible(false); - contactinServiceModal.setTitle("Export"); - FlowPanel panelMsg = new FlowPanel(); - panelMsg.add(new HTML("Contacting the service...")); - contactinServiceModal.add(panelMsg); - contactinServiceModal.show(); +// final Modal contactinServiceModal = new Modal(true, true); +// contactinServiceModal.setCloseVisible(false); +// contactinServiceModal.setTitle("Export"); +// FlowPanel panelMsg = new FlowPanel(); +// panelMsg.add(new HTML("Contacting the service...")); +// contactinServiceModal.add(panelMsg); +// contactinServiceModal.show(); // Add an event handler to the form. form.addSubmitHandler(new SubmitHandler() { @@ -279,7 +279,7 @@ public class ProjectViewer extends Composite { form.addSubmitCompleteHandler(new SubmitCompleteHandler() { public void onSubmitComplete(SubmitCompleteEvent event) { GWT.log("onSubmitComplete done"); - contactinServiceModal.hide(); + //contactinServiceModal.hide(); } }); -- 2.17.1 From 6176bb20d94ac834f1a9c77130384208a5173285 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Fri, 10 May 2024 16:54:41 +0200 Subject: [PATCH 26/28] removed unused code. Moved to gwt-ol.8.5 --- .settings/org.eclipse.wst.common.component | 43 +++++++-- pom.xml | 2 +- .../client/ui/cms/project/ProjectViewer.java | 2 - .../shared/gis/LayerItem.java | 91 ------------------- 4 files changed, 34 insertions(+), 104 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 27ca07b..2fc949e 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,7 @@ - + + + @@ -133,7 +135,9 @@ - + + + @@ -267,7 +271,9 @@ - + + + @@ -401,7 +407,9 @@ - + + + @@ -535,7 +543,9 @@ - + + + @@ -669,7 +679,9 @@ - + + + @@ -689,7 +701,12 @@ - + + uses + + + + @@ -823,7 +840,9 @@ - + + + @@ -957,7 +976,9 @@ - + + + @@ -1091,7 +1112,9 @@ - + + + diff --git a/pom.xml b/pom.xml index 78594a2..6c4cc68 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 2.10.0 PRETTY 2.6.2 - 8.4.1 + 8.5.0 ${project.build.directory}/${project.build.finalName} 1.8 diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java index 2866439..94894ae 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/client/ui/cms/project/ProjectViewer.java @@ -24,7 +24,6 @@ import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.ExtentMapUtil.P import org.gcube.portlets.user.geoportaldataviewer.client.ui.map.MapView; import com.github.gwtbootstrap.client.ui.Button; -import com.github.gwtbootstrap.client.ui.Modal; import com.github.gwtbootstrap.client.ui.constants.ButtonType; import com.github.gwtbootstrap.client.ui.constants.IconType; import com.google.gwt.core.client.GWT; @@ -39,7 +38,6 @@ import com.google.gwt.user.client.Random; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent; import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler; diff --git a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/LayerItem.java b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/LayerItem.java index befdc6c..89a77cf 100644 --- a/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/LayerItem.java +++ b/src/main/java/org/gcube/portlets/user/geoportaldataviewer/shared/gis/LayerItem.java @@ -2,18 +2,13 @@ package org.gcube.portlets.user.geoportaldataviewer.shared.gis; import java.io.Serializable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import org.gcube.application.geoportalcommon.shared.gis.BoundsMap; -import org.gcube.portlets.user.geoportaldataviewer.client.GeoportalDataViewerConstants.LayerType; -import org.gcube.portlets.user.geoportaldataviewer.client.util.URLUtil; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.wms.Property; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.wms.ZAxis; -import com.google.gwt.core.client.GWT; - /** * The Class LayerItem. * @@ -953,90 +948,4 @@ public class LayerItem implements Serializable, Cloneable { return builder.toString(); } - /** - * To layer item. - * - * @param layerType the layer type - * @param layerTitle the layer title - * @param layerName the layer name - * @param layerURL the layer URL - * @param mapServerHost the map server host - * @param isExternal the is external - * @param isBase the is base - * @param displayInLayerSwitcher the display in layer switcher - * @param styles the styles - * @param wmsLink the wms link - * @param onTop the on top - * @param wmsNotStandardParams the wms not standard params - * @param isNcWms the is nc wms - * @param UUID the uuid - * @param zAxis the z axis - * @param minResolution the min resolution - * @param maxResolution the max resolution - * @return the layer item - */ - - // TODO Constructor from IndexLayerDV, GCUBESDILAeryDV or direct info - private LayerItem toLayerItem(LayerType layerType, String layerTitle, String layerName, String layerURL, - String mapServerHost, boolean isExternal, boolean isBase, boolean displayInLayerSwitcher, - ArrayList styles, String wmsLink, boolean onTop, HashMap wmsNotStandardParams, - boolean isNcWms, String UUID, ZAxis zAxis, Double minResolution, Double maxResolution) { - -// GWT.log("Add addLayerByWms 1"); - LayerItem layerItem = new LayerItem(); - layerItem.setBaseLayer(isBase); - layerItem.setTitle(layerTitle); - layerItem.setName(layerName); - layerItem.setUrl(layerURL); - layerItem.setMapServerHost(mapServerHost); - // l.setExternal(isExternal); - layerItem.setOpacity(1d); - layerItem.setBuffer(2); - layerItem.setWmsLink(wmsLink); - layerItem.setWmsNotStandardParams(wmsNotStandardParams); - layerItem.setNcWms(isNcWms); - layerItem.setUUID(UUID); - layerItem.setZAxis(zAxis); - layerItem.setMinResolution(minResolution); - layerItem.setMaxResolution(maxResolution); - - switch (layerType) { - - // TODO IMPLEMENT THIS CASE - case RASTER_BASELAYER: - -// l.setHasLegend(false); - layerItem.setBaseLayer(true); - layerItem.setTrasparent(false); - layerItem.setClickData(false); - break; - - case FEATURE_TYPE: - - // CASE FEATURE TYPE - layerItem.setBaseLayer(false); - layerItem.setClickData(true); - layerItem.setTrasparent(true); - break; - - } - - GWT.log("styles " + styles); - - if (styles != null && styles.size() > 0) { - layerItem.setHasLegend(true); - layerItem.setDefaultStyle(styles.get(0)); - layerItem.setStyle(styles.get(0)); - layerItem.setStyles(styles); - } else { - String style = URLUtil.getValueOfParameter("styles", wmsLink); - if (style != null) { // CASE OF STYLE =""; - // TENTATIVE TO GET LEGEND - layerItem.setHasLegend(true); - } - } - GWT.log("Built layer: " + layerItem); - return layerItem; - } - } -- 2.17.1 From 935a00685aad06967e0e56313ba3f2744bf9586a Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 21 May 2024 10:33:52 +0200 Subject: [PATCH 27/28] updated README --- .settings/org.eclipse.wst.common.component | 55 +++++++++++++++++----- README.md | 2 +- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index 2fc949e..72a9536 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -1,5 +1,8 @@ - + + + + @@ -135,7 +138,10 @@ - + + + + @@ -271,7 +277,10 @@ - + + + + @@ -407,7 +416,10 @@ - + + + + @@ -543,7 +555,10 @@ - + + + + @@ -679,7 +694,10 @@ - + + + + @@ -701,10 +719,16 @@ - + uses - + + uses + + + + + @@ -840,7 +864,10 @@ - + + + + @@ -976,7 +1003,10 @@ - + + + + @@ -1112,7 +1142,10 @@ - + + + + diff --git a/README.md b/README.md index 65112cd..73cea38 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The "Geoportal data-viewer" technology allows users to access and search for spa * GWT v.2.9.0. [GWT](http://www.gwtproject.org) is licensed under [Apache License 2.0](http://www.gwtproject.org/terms.html) * GWT-Bootstrap v.2.3.2.0. [GWT-Bootstrap](https://github.com/gwtbootstrap) is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) -* GWT-OpenLayers 3+ v.8.1.0-gwt2_9. [GWT-OL3](https://github.com/TDesjardins/gwt-ol) +* GWT-OpenLayers 3+ v.8.5.0-gwt2_9. [GWT-OL3](https://github.com/TDesjardins/gwt-ol) * OpenLayers v.6.x [OpenLayers](https://openlayers.org/) is licensed under [BSD 2-Clause "Simplified"](https://github.com/openlayers/openlayers/blob/main/LICENSE.md) * NanoGallery v2.X [NanoGallery2](https://github.com/nanostudio-org/nanogallery2) is licensed under [GNU General Public License "gplv3"](https://www.gnu.org/licenses/gpl-3.0.html) * Vis-Timeline v7.x [VisTimeline](https://github.com/visjs/vis-timeline) is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) and MIT -- 2.17.1 From 60b8eedc79cb14953bb93083a154b897bde86a95 Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 21 May 2024 10:37:40 +0200 Subject: [PATCH 28/28] Updated README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73cea38..5570d69 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The "Geoportal data-viewer" technology allows users to access and search for spa **Uses** -* GWT v.2.9.0. [GWT](http://www.gwtproject.org) is licensed under [Apache License 2.0](http://www.gwtproject.org/terms.html) +* GWT v.2.10.0. [GWT](http://www.gwtproject.org) is licensed under [Apache License 2.0](http://www.gwtproject.org/terms.html) * GWT-Bootstrap v.2.3.2.0. [GWT-Bootstrap](https://github.com/gwtbootstrap) is licensed under [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0) * GWT-OpenLayers 3+ v.8.5.0-gwt2_9. [GWT-OL3](https://github.com/TDesjardins/gwt-ol) * OpenLayers v.6.x [OpenLayers](https://openlayers.org/) is licensed under [BSD 2-Clause "Simplified"](https://github.com/openlayers/openlayers/blob/main/LICENSE.md) -- 2.17.1