2022-02-14 12:23:13 +01:00
|
|
|
|
package org.gcube.application.cms.concessioni.sdi;
|
|
|
|
|
|
|
|
|
|
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
|
|
|
|
|
import it.geosolutions.geoserver.rest.GeoServerRESTReader;
|
|
|
|
|
import it.geosolutions.geoserver.rest.decoder.RESTFeatureType;
|
|
|
|
|
import it.geosolutions.geoserver.rest.decoder.RESTLayer;
|
|
|
|
|
import lombok.Getter;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.bson.Document;
|
|
|
|
|
import org.gcube.application.cms.concessioni.sdi.faults.SDIInteractionException;
|
2022-02-17 11:07:03 +01:00
|
|
|
|
import org.gcube.application.cms.plugins.requests.BaseExecutionRequest;
|
2022-02-14 12:23:13 +01:00
|
|
|
|
import org.gcube.application.cms.serialization.Serialization;
|
|
|
|
|
import org.gcube.application.geoportal.common.model.document.filesets.GCubeSDILayer;
|
|
|
|
|
|
|
|
|
|
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFile;
|
|
|
|
|
import org.gcube.application.geoportal.common.model.document.filesets.RegisteredFileSet;
|
|
|
|
|
|
|
|
|
|
import org.gcube.application.geoportal.common.utils.Files;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import org.gcube.data.transfer.library.DataTransferClient;
|
|
|
|
|
import org.gcube.data.transfer.library.TransferResult;
|
|
|
|
|
import org.gcube.data.transfer.model.Destination;
|
|
|
|
|
import org.gcube.data.transfer.model.DestinationClashPolicy;
|
|
|
|
|
import org.gcube.spatial.data.gis.GISInterface;
|
|
|
|
|
import org.gcube.spatial.data.gis.is.AbstractGeoServerDescriptor;
|
|
|
|
|
|
|
|
|
|
import java.net.MalformedURLException;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class SDIManager {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static private final String EPSG_4326="EPSG:4326";
|
|
|
|
|
static private final String WGS84_FULL="GEOGCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]],"+
|
|
|
|
|
"AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\", 0.017453292519943295],"+
|
|
|
|
|
"AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH], AUTHORITY[\"EPSG\",\"4326\"]]";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static final Pattern HOSTNAME_PATTERN=Pattern.compile("(?<=\\:\\/\\/)[^\\:]*");
|
|
|
|
|
public static final Pattern PORT_PATTERN=Pattern.compile("(?<=\\:)[\\d]+");
|
|
|
|
|
public static final Pattern DB_NAME_PATTERN=Pattern.compile("(?<=\\/)[^\\/]*(?=$)");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final GISInterface gis;
|
|
|
|
|
@Getter
|
|
|
|
|
private final DataTransferClient dtGeoServer;
|
2022-02-16 18:36:42 +01:00
|
|
|
|
@Getter
|
2022-02-14 12:23:13 +01:00
|
|
|
|
private final String geoserverHostName;
|
2022-02-16 18:36:42 +01:00
|
|
|
|
@Getter
|
2022-02-14 12:23:13 +01:00
|
|
|
|
private final AbstractGeoServerDescriptor currentGeoserver;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public SDIManager() throws SDIInteractionException {
|
|
|
|
|
try{
|
|
|
|
|
log.debug("Initializing GIS Interface..");
|
|
|
|
|
gis=GISInterface.get();
|
|
|
|
|
currentGeoserver=gis.getCurrentGeoServer();
|
|
|
|
|
if(currentGeoserver==null)
|
|
|
|
|
throw new Exception("Unable to contact data transfer for geoserver ");
|
|
|
|
|
|
|
|
|
|
log.debug("Found geoserver descriptor "+currentGeoserver);
|
|
|
|
|
geoserverHostName=new URL(currentGeoserver.getUrl()).getHost();
|
|
|
|
|
|
|
|
|
|
log.debug("Contacting Data Transfer from geoserver {} ",geoserverHostName);
|
|
|
|
|
dtGeoServer=DataTransferClient.getInstanceByEndpoint("https://"+geoserverHostName);
|
|
|
|
|
if(!currentGeoserver.getReader().existGeoserver())
|
|
|
|
|
throw new Exception("Geoserver not reachable");
|
|
|
|
|
}catch(Exception e) {
|
|
|
|
|
throw new SDIInteractionException("Unable to initialize SDI Manager",e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Expected paramters :
|
|
|
|
|
* - "workspace"
|
|
|
|
|
* - "layerTitle"
|
|
|
|
|
* - "documentID"
|
|
|
|
|
* - "basePersistencePath" (profile specific, e.g. "GNA")
|
|
|
|
|
*
|
|
|
|
|
* @param fileSet
|
|
|
|
|
* @param params
|
|
|
|
|
* @return
|
|
|
|
|
* @throws SDIInteractionException
|
|
|
|
|
*/
|
|
|
|
|
public RegisteredFileSet materializeLayer(RegisteredFileSet fileSet, Document params) throws SDIInteractionException{
|
|
|
|
|
try {
|
|
|
|
|
log.debug("Materializing FS {} on {} ", fileSet, geoserverHostName);
|
|
|
|
|
|
|
|
|
|
// validate parameters
|
2022-02-17 11:07:03 +01:00
|
|
|
|
String workspace = BaseExecutionRequest.getMandatory("workspace", params);
|
|
|
|
|
String documentID = BaseExecutionRequest.getMandatory("documentID", params);
|
|
|
|
|
String basePersistencePAth = BaseExecutionRequest.getMandatory("basePersistencePath", params);
|
2022-02-14 12:23:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check if empty
|
|
|
|
|
if (fileSet.getPayloads().isEmpty()) throw new SDIInteractionException("No payload to materialize");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Document geoserverInfo = new Document();
|
|
|
|
|
geoserverInfo.put("_type", "Geoserver");
|
|
|
|
|
geoserverInfo.put("workspace", workspace);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Evaluate Layer Name
|
|
|
|
|
String baseName = getToUseBaseLayerName(fileSet);
|
|
|
|
|
log.debug("Base layer name is {}, checking conflicts.. ");
|
|
|
|
|
String toSetLayerName = baseName;
|
|
|
|
|
//Check if layer already exists
|
|
|
|
|
int count = 0;
|
|
|
|
|
GeoServerRESTReader gsReader = currentGeoserver.getReader();
|
|
|
|
|
while (gsReader.getLayer(workspace, toSetLayerName) != null) {
|
|
|
|
|
count++;
|
|
|
|
|
toSetLayerName = baseName + "_" + count;
|
|
|
|
|
log.debug("layer for " + baseName + " already existing, trying " + toSetLayerName);
|
|
|
|
|
}
|
|
|
|
|
geoserverInfo.put("layerName", toSetLayerName);
|
|
|
|
|
log.debug("Layer name will be {} ", toSetLayerName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String folderRelativePath = basePersistencePAth + "/" + documentID + "/" + fileSet.getUUID() + "/" + toSetLayerName;
|
|
|
|
|
log.debug("GS Relative destination path is {} ", folderRelativePath);
|
|
|
|
|
geoserverInfo.put("persistencePath", folderRelativePath);
|
|
|
|
|
|
|
|
|
|
List<String> filenames = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
String absolutePath = null;
|
|
|
|
|
|
|
|
|
|
for (Object o : fileSet.getPayloads()) {
|
|
|
|
|
RegisteredFile file = Serialization.convert(o, RegisteredFile.class);
|
|
|
|
|
log.info("Sending {} to GS {} at {} ", file, geoserverHostName, folderRelativePath);
|
|
|
|
|
String completeFilename = Files.fixFilename(file.getName());
|
|
|
|
|
completeFilename = completeFilename.replaceAll(baseName, toSetLayerName);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Destination destination = new Destination(completeFilename);
|
|
|
|
|
destination.setCreateSubfolders(true);
|
|
|
|
|
destination.setOnExistingFileName(DestinationClashPolicy.REWRITE);
|
|
|
|
|
destination.setOnExistingSubFolder(DestinationClashPolicy.APPEND);
|
|
|
|
|
|
|
|
|
|
destination.setPersistenceId("geoserver");
|
|
|
|
|
destination.setSubFolder(folderRelativePath);
|
|
|
|
|
|
|
|
|
|
log.debug("Sending {} to {}", file, destination);
|
|
|
|
|
TransferResult result = getDtGeoServer().httpSource(new URL(file.getLink()), destination);
|
|
|
|
|
log.debug("Transferred " + result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
filenames.add(completeFilename);
|
|
|
|
|
// NB Clash con subfolder is APPEND, thus FOLDER is expected to be the one specified by caller
|
|
|
|
|
//geoserverInfo.put(""result.getRemotePath().substring(0, result.getRemotePath().lastIndexOf("/")));
|
|
|
|
|
absolutePath = result.getRemotePath().substring(0, result.getRemotePath().lastIndexOf("/"));
|
|
|
|
|
}
|
|
|
|
|
geoserverInfo.put("files", filenames);
|
|
|
|
|
|
|
|
|
|
// Publishing layer in GS
|
|
|
|
|
String storeName = toSetLayerName + "_store";
|
|
|
|
|
geoserverInfo.put("storeName", storeName);
|
|
|
|
|
|
|
|
|
|
GeoServerRESTPublisher publisher = currentGeoserver.getPublisher();
|
|
|
|
|
log.debug("Trying to create remote workspace : " + workspace);
|
|
|
|
|
createWorkspace(workspace);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.debug("Publishing remote folder " + absolutePath);
|
|
|
|
|
|
|
|
|
|
URL directoryPath = new URL("file:" + absolutePath + "/" + toSetLayerName + ".shp");
|
|
|
|
|
|
|
|
|
|
//TODO Evaluate SRS
|
|
|
|
|
|
|
|
|
|
boolean published = publisher.publishShp(
|
|
|
|
|
workspace,
|
|
|
|
|
storeName,
|
|
|
|
|
null,
|
|
|
|
|
toSetLayerName,
|
|
|
|
|
// UploadMethod.FILE, // neeeds zip
|
|
|
|
|
GeoServerRESTPublisher.UploadMethod.EXTERNAL, // needs shp
|
|
|
|
|
directoryPath.toURI(),
|
|
|
|
|
EPSG_4326, //SRS
|
|
|
|
|
""); // default style
|
|
|
|
|
|
|
|
|
|
if (!published) {
|
|
|
|
|
throw new SDIInteractionException("Unable to publish layer " + toSetLayerName + " under " + workspace + ". Unknown Geoserver fault.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RESTLayer l = gsReader.getLayer(workspace, toSetLayerName);
|
|
|
|
|
RESTFeatureType f = gsReader.getFeatureType(l);
|
|
|
|
|
/*https://geoserver1.dev.d4science.org/geoserver/gna_conc_18/wms?
|
|
|
|
|
service=WMS&version=1.1.0&request=GetMap&layers=gna_conc_18:pos&
|
|
|
|
|
styles=&bbox=8.62091913167495,40.62975046683799,8.621178639172953,40.630257904721645&
|
|
|
|
|
width=392&height=768&srs=EPSG:4326&format=application/openlayers */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<Document> ogcLinks = new ArrayList<>();
|
|
|
|
|
|
|
|
|
|
Document wmsLink = new Document();
|
|
|
|
|
wmsLink.put("wms", String.format("https://%1$s/geoserver/%2$s/wms?"
|
|
|
|
|
+ "service=WMS&version=1.1.0&request=GetMap&layers=%2$s:%3$s&"
|
|
|
|
|
+ "styles=&bbox=%4$f,%5$f,%6$f,%7$f&srs=%8$s&format=application/openlayers&width=%9$d&height=%10$d",
|
|
|
|
|
geoserverHostName,
|
|
|
|
|
workspace,
|
|
|
|
|
toSetLayerName,
|
|
|
|
|
f.getMinX(),
|
|
|
|
|
f.getMinY(),
|
|
|
|
|
f.getMaxX(),
|
|
|
|
|
f.getMaxY(),
|
|
|
|
|
EPSG_4326,
|
|
|
|
|
400,
|
|
|
|
|
400));
|
|
|
|
|
ogcLinks.add(wmsLink);
|
|
|
|
|
|
|
|
|
|
List<Document> platformInfo = new ArrayList<>();
|
|
|
|
|
platformInfo.add(geoserverInfo);
|
|
|
|
|
// TODO Metadata
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Materialization object
|
|
|
|
|
GCubeSDILayer materialization = new GCubeSDILayer();
|
|
|
|
|
materialization.put(GCubeSDILayer.OGC_LINKS, ogcLinks);
|
|
|
|
|
materialization.put(GCubeSDILayer.B_BOX, new GCubeSDILayer.BBOX(f.getMaxX(), f.getMaxY(), f.getMinX(), f.getMinY()));
|
|
|
|
|
materialization.put(GCubeSDILayer.PLATFORM_INFO, platformInfo);
|
|
|
|
|
|
|
|
|
|
log.info("Generated Materialization {}", materialization);
|
|
|
|
|
|
|
|
|
|
//Add Materialization to registered file set
|
|
|
|
|
List materializations = fileSet.getMaterializations();
|
|
|
|
|
if (materializations == null) materializations = new ArrayList();
|
|
|
|
|
materializations.add(materialization);
|
|
|
|
|
fileSet.put(RegisteredFileSet.MATERIALIZATIONS, materializations);
|
|
|
|
|
|
|
|
|
|
return fileSet;
|
|
|
|
|
}catch(SDIInteractionException e){
|
|
|
|
|
throw e;
|
|
|
|
|
}catch (Throwable t){
|
|
|
|
|
throw new SDIInteractionException("Unexpected exception while trying to materialize File Set "+t.getMessage(),t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String createWorkspace(String toCreate) throws SDIInteractionException {
|
|
|
|
|
try {
|
|
|
|
|
if(!currentGeoserver.getReader().getWorkspaceNames().contains(toCreate)) {
|
|
|
|
|
log.debug("Creating workspace : "+toCreate);
|
|
|
|
|
if(!currentGeoserver.getPublisher().createWorkspace(toCreate))
|
|
|
|
|
throw new SDIInteractionException("Unable to create workspace "+toCreate);
|
|
|
|
|
}else log.debug("Workspace "+toCreate+" exists.");
|
|
|
|
|
return toCreate;
|
|
|
|
|
} catch (IllegalArgumentException | MalformedURLException e) {
|
|
|
|
|
throw new SDIInteractionException("Unable to create workspace "+toCreate,e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String getToUseBaseLayerName(RegisteredFileSet fileset){
|
|
|
|
|
// ******** IDENTIFY LAYER NAME correct layer name
|
|
|
|
|
// Must be unique under same WS
|
|
|
|
|
// equal to shp base name
|
|
|
|
|
|
|
|
|
|
String baseName= "";
|
|
|
|
|
|
|
|
|
|
// Chose layer name first identifying filename
|
|
|
|
|
for(Object p:fileset.getPayloads()){
|
|
|
|
|
RegisteredFile f = Serialization.convert(p,RegisteredFile.class);
|
|
|
|
|
String name=f.getName();
|
|
|
|
|
if(name.endsWith(".shp")) {
|
|
|
|
|
log.debug("SHP is {}",name);
|
|
|
|
|
baseName= Files.fixFilename(name.substring(0,name.lastIndexOf('.')));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return baseName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-02-17 11:07:03 +01:00
|
|
|
|
|
2022-02-14 12:23:13 +01:00
|
|
|
|
|
|
|
|
|
}
|