package org.gcube.application.cms.sdi.engine; 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 it.geosolutions.geoserver.rest.encoder.datastore.GSPostGISDatastoreEncoder; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.bson.Document; import org.gcube.application.cms.sdi.faults.SDIInteractionException; import org.gcube.application.cms.plugins.requests.BaseExecutionRequest; 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.model.rest.DatabaseConnection; 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.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @Slf4j public class SDIManager { static protected final String EPSG_4326="EPSG:4326"; static 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; @Getter private final String geoserverHostName; @Getter 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); } } 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); } } protected 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; } protected String createStore(GSPostGISDatastoreEncoder encoder, String workspace) throws SDIInteractionException { String storeName=encoder.getName(); try { log.debug("Looking for datastore "+storeName+" under "+workspace); if(currentGeoserver.getReader().getDatastore(workspace,storeName)==null) if(!currentGeoserver.getDataStoreManager().create(workspace, encoder)) throw new SDIInteractionException("Unable to create store "+storeName+" in "+workspace); log.debug("Store "+storeName+" exists under "+workspace); return storeName; } catch (IllegalArgumentException | MalformedURLException e) { throw new SDIInteractionException("Unable to create store "+storeName,e); } } protected String createStoreFromPostgisDB(String workspace, String storeName, DatabaseConnection connection) throws SDIInteractionException{ String connectionUrl=connection.getUrl(); Matcher hostname=HOSTNAME_PATTERN.matcher(connectionUrl); if (!hostname.find()) throw new SDIInteractionException("Unable to get Hostname from "+connection); Matcher port = PORT_PATTERN.matcher(connectionUrl); if (!port.find()) throw new SDIInteractionException("Unable to get PORT from "+connection); Matcher db = DB_NAME_PATTERN.matcher(connectionUrl); if (!db.find()) throw new SDIInteractionException("Unable to get DB from "+connection); GSPostGISDatastoreEncoder encoder=new GSPostGISDatastoreEncoder(storeName); encoder.setHost(hostname.group()); encoder.setPort(Integer.parseInt(port.group())); encoder.setDatabase(db.group()); encoder.setSchema("public"); encoder.setUser(connection.getUser()); encoder.setPassword(connection.getPwd()); encoder.setLooseBBox(true); encoder.setDatabaseType("postgis"); encoder.setEnabled(true); encoder.setFetchSize(1000); encoder.setValidateConnections(true); return createStore(encoder,workspace); } protected String publishStyle(File sldFile, String name) throws SDIInteractionException { try { if(!currentGeoserver.getReader().existsStyle(name)) { log.debug("Registering style "+name); if(!currentGeoserver.getPublisher().publishStyle(sldFile, name)) throw new SDIInteractionException("Unable to register style "+name); }else log.debug("Style "+name+" already existing"); return name; } catch (IllegalArgumentException | MalformedURLException e) { throw new SDIInteractionException("Unable to create style "+name,e); } } }