From 3e4744f651fb5cbd69d437d00cc4ee2e62802c98 Mon Sep 17 00:00:00 2001 From: Fabio Sinibaldi Date: Wed, 5 Jul 2017 16:42:04 +0000 Subject: [PATCH] git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/spatial-data/sdi-service@150825 82a268e6-3cf1-43bd-a215-b396298e98cf --- distro/changelog.xml | 1 + pom.xml | 78 ++----- .../org/gcube/spatial/data/sdi/Constants.java | 12 - .../spatial/data/sdi/LocalConfiguration.java | 1 + .../gcube/spatial/data/sdi/SDIService.java | 3 +- .../spatial/data/sdi/SDIServiceManager.java | 33 +++ .../sdi/engine/MetadataTemplateManager.java | 18 ++ .../impl/metadata/CommonMetadataPieces.java | 11 + .../engine/impl/metadata/MetadataHandler.java | 73 ++++++ .../metadata/MetadataTemplateManagerImpl.java | 151 ++++++++++++ .../engine/impl/metadata/MetadataUtils.java | 126 ++++++++++ .../metadata/templates/AbstractTemplate.java | 33 ++- .../InvalidTemplateInvocationException.java | 36 +++ .../templates/ThreddsOnlineTemplate.java | 51 ++++ .../spatial/data/sdi/rest/GeoNetwork.java | 4 +- .../spatial/data/sdi/rest/GeoServer.java | 93 ++++++++ .../gcube/spatial/data/sdi/rest/Metadata.java | 57 +++++ .../org/gcube/spatial/data/sdi/rest/SDI.java | 6 +- src/main/webapp/WEB-INF/README | 2 +- src/main/webapp/WEB-INF/changelog.xml | 1 + src/main/webapp/WEB-INF/config.properties | 4 +- src/main/webapp/WEB-INF/gcube-app.xml | 2 +- .../ThreddsOnlineResources.ftlx | 220 ++++++++++++++++++ src/main/webapp/WEB-INF/profile.xml | 4 +- .../data/sdi/test/ConfigurationTest.java | 25 ++ .../gcube/spatial/data/sdi/test/MainTest.java | 10 +- .../spatial/data/sdi/test/TestCommon.java | 2 +- 27 files changed, 966 insertions(+), 91 deletions(-) delete mode 100644 src/main/java/org/gcube/spatial/data/sdi/Constants.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/SDIServiceManager.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/MetadataTemplateManager.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataHandler.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataTemplateManagerImpl.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataUtils.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/InvalidTemplateInvocationException.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/ThreddsOnlineTemplate.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/rest/GeoServer.java create mode 100644 src/main/java/org/gcube/spatial/data/sdi/rest/Metadata.java create mode 100644 src/main/webapp/WEB-INF/metadataTemplates/ThreddsOnlineResources.ftlx create mode 100644 src/test/java/org/gcube/spatial/data/sdi/test/ConfigurationTest.java diff --git a/distro/changelog.xml b/distro/changelog.xml index 393e4ec..14e216e 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -4,5 +4,6 @@ Added GeoServer interface + Added Metadata interface \ No newline at end of file diff --git a/pom.xml b/pom.xml index 031ef7b..daa1837 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.gcube.spatial.data sdi-service - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT SDI Service REST Interface towards SDI facilities war @@ -46,7 +46,12 @@ - + + + org.gcube.spatial.data + sdi-interface + [1.0.0-SNAPSHOT,2.0.0-SNAPSHOT) + @@ -211,67 +216,14 @@ ${project.artifactId} - - - maven-compiler-plugin - 2.3.2 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-war-plugin - 2.4 - - ${project.artifactId} - false - - - - org.apache.maven.plugins - maven-resources-plugin - 2.6 - - - copy-profile - - copy-resources - - process-resources - - ${webappDirectory} - - - ${distroDirectory} - true - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.2 - - - ${distroDirectory}/descriptor.xml - - - - - servicearchive - install - - single - - - - - + + + src/test/resources + + + src/main/webapps + + \ No newline at end of file diff --git a/src/main/java/org/gcube/spatial/data/sdi/Constants.java b/src/main/java/org/gcube/spatial/data/sdi/Constants.java deleted file mode 100644 index 61ec723..0000000 --- a/src/main/java/org/gcube/spatial/data/sdi/Constants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.gcube.spatial.data.sdi; - -public class Constants { - - - public static final String APPLICATION="SDI-Service"; - public static final String GEONETWORK_INTERFACE="GeoNetwork"; - public static final String GEONETWORK_CONFIGURATION_PATH="configuration"; - public static final String GEONETWORK_GROUPS_PATH="groups"; - - public static final String SDI_INTERFACE="SDI"; -} diff --git a/src/main/java/org/gcube/spatial/data/sdi/LocalConfiguration.java b/src/main/java/org/gcube/spatial/data/sdi/LocalConfiguration.java index d6873a0..90e0642 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/LocalConfiguration.java +++ b/src/main/java/org/gcube/spatial/data/sdi/LocalConfiguration.java @@ -28,6 +28,7 @@ public class LocalConfiguration { final static public String THREDDS_GE_SERVICE_NAME="th.ge.serviceName"; + final static public String METADATA_TEMPLATE_FOLDER="meta.tpl.folder"; static LocalConfiguration instance=null; diff --git a/src/main/java/org/gcube/spatial/data/sdi/SDIService.java b/src/main/java/org/gcube/spatial/data/sdi/SDIService.java index 56006b4..a2b9f3b 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/SDIService.java +++ b/src/main/java/org/gcube/spatial/data/sdi/SDIService.java @@ -7,13 +7,14 @@ import javax.ws.rs.ApplicationPath; import org.gcube.smartgears.ContextProvider; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.spatial.data.sdi.model.ServiceConstants; import org.gcube.spatial.data.sdi.rest.GeoNetwork; import org.glassfish.jersey.server.ResourceConfig; import io.swagger.jaxrs.config.BeanConfig; import lombok.extern.slf4j.Slf4j; @Slf4j -@ApplicationPath(Constants.APPLICATION) +@ApplicationPath(ServiceConstants.APPLICATION) public class SDIService extends ResourceConfig{ public SDIService() { diff --git a/src/main/java/org/gcube/spatial/data/sdi/SDIServiceManager.java b/src/main/java/org/gcube/spatial/data/sdi/SDIServiceManager.java new file mode 100644 index 0000000..fe26eef --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/SDIServiceManager.java @@ -0,0 +1,33 @@ +package org.gcube.spatial.data.sdi; + +import javax.inject.Inject; + +import org.gcube.smartgears.ApplicationManager; +import org.gcube.smartgears.ContextProvider; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.spatial.data.sdi.engine.MetadataTemplateManager; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SDIServiceManager implements ApplicationManager { + + @Inject + MetadataTemplateManager templateManager; + + + @Override + public void onInit() { + log.trace("Initializing template manager.."); + + ApplicationContext ctx = ContextProvider.get(); + templateManager.init(ctx); + } + + @Override + public void onShutdown() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/MetadataTemplateManager.java b/src/main/java/org/gcube/spatial/data/sdi/engine/MetadataTemplateManager.java new file mode 100644 index 0000000..ae341c8 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/MetadataTemplateManager.java @@ -0,0 +1,18 @@ +package org.gcube.spatial.data.sdi.engine; + +import java.io.File; +import java.util.Set; + +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.spatial.data.sdi.model.metadata.MetadataReport; +import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor; +import org.gcube.spatial.data.sdi.model.metadata.TemplateInvocation; + +public interface MetadataTemplateManager { + + + public Set getAvailableTemplates(); + public MetadataReport applyTemplates(File original,Set invocations); + public void init(ApplicationContext ctx); + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/CommonMetadataPieces.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/CommonMetadataPieces.java index 2f17b1c..db86d0c 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/CommonMetadataPieces.java +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/CommonMetadataPieces.java @@ -2,4 +2,15 @@ package org.gcube.spatial.data.sdi.engine.impl.metadata; public class CommonMetadataPieces { + public static final String resourceIdentifier=" " + + " %s" + + " " + + ""; + + public static final String fileIdentifier="" + + " %s "; + + + + } diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataHandler.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataHandler.java new file mode 100644 index 0000000..254a842 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataHandler.java @@ -0,0 +1,73 @@ +package org.gcube.spatial.data.sdi.engine.impl.metadata; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.List; +import java.util.UUID; + +import org.gcube.common.resources.gcore.utils.XPathHelper; +import org.gcube.spatial.data.sdi.engine.impl.metadata.templates.AbstractTemplate.InsertionPoint; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class MetadataHandler { + + private Document document=null; + private String metaUUID=null; + private XPathHelper helper; + public MetadataHandler(File xmlFile){ + // Get document owner + Element documentNode=null; + try{ + InputStream inputStream= new FileInputStream(xmlFile); + Reader reader = new InputStreamReader(inputStream,"UTF-8"); + + InputSource is = new InputSource(reader); + documentNode = MetadataUtils.docBuilder.parse(is).getDocumentElement(); + document=documentNode.getOwnerDocument(); + + helper=MetadataUtils.getHelper(document); + + // document = (Document)xpath.evaluate("/", inputSource, XPathConstants.NODE); + }catch(Exception e){ + // throw e; + throw new RuntimeException("Unable to fix : unable to get Document",e); + } + + + } + + public String getUUID() throws SAXException, IOException{ + //Set | get meta UUID + if(metaUUID==null){ + log.debug("Managing metadata ID.. "); + + + List metaUUIDList=helper.evaluate("//gmd:fileIdentifier/gco:CharacterString/text()"); + if(metaUUIDList.isEmpty()){ + metaUUID=UUID.randomUUID().toString(); + log.debug("Stting uuid {} ",metaUUID); + MetadataUtils.addContent("gmd:MD_Metadata",document,String.format(CommonMetadataPieces.fileIdentifier, metaUUID),helper,MetadataUtils.Position.first_child); + }else { + metaUUID=metaUUIDList.get(0); + log.debug("Found meta UUID {} ",metaUUID); + throw new RuntimeException("FOUND META ID"); + } + } + return metaUUID; + } + + + public void addContent(String content, InsertionPoint insertion) throws SAXException, IOException{ + MetadataUtils.addContent(insertion.getElementReference(), document, content, helper, insertion.getPosition()); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataTemplateManagerImpl.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataTemplateManagerImpl.java new file mode 100644 index 0000000..11d24b3 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataTemplateManagerImpl.java @@ -0,0 +1,151 @@ +package org.gcube.spatial.data.sdi.engine.impl.metadata; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import javax.inject.Singleton; + +import org.apache.commons.io.IOUtils; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.spatial.data.sdi.LocalConfiguration; +import org.gcube.spatial.data.sdi.engine.MetadataTemplateManager; +import org.gcube.spatial.data.sdi.engine.impl.metadata.templates.AbstractTemplate; +import org.gcube.spatial.data.sdi.engine.impl.metadata.templates.InvalidTemplateInvocationException; +import org.gcube.spatial.data.sdi.engine.impl.metadata.templates.ThreddsOnlineTemplate; +import org.gcube.spatial.data.sdi.model.metadata.MetadataReport; +import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor; +import org.gcube.spatial.data.sdi.model.metadata.TemplateInvocation; + +import freemarker.core.ParseException; +import freemarker.template.Configuration; +import freemarker.template.MalformedTemplateNameException; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import freemarker.template.TemplateExceptionHandler; +import freemarker.template.TemplateNotFoundException; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Singleton +public class MetadataTemplateManagerImpl implements MetadataTemplateManager { + + + private static Configuration cfg; + + private static ArrayList templateDescriptors=new ArrayList<>(); + private static HashMap availableTemplates=new HashMap<>(); + + @Override + public void init(ApplicationContext ctx) { + + // Create your Configuration instance, and specify if up to what FreeMarker + // version (here 2.3.25) do you want to apply the fixes that are not 100% + // backward-compatible. See the Configuration JavaDoc for details. + cfg = new Configuration(Configuration.VERSION_2_3_25); + + + // cfg.setDirectoryForTemplateLoading(TamplateManager.class.getPackage().new File("src/xmlTemplates")); + cfg.setServletContextForTemplateLoading(ctx, LocalConfiguration.get().getProperty(LocalConfiguration.METADATA_TEMPLATE_FOLDER)); + + // Set the preferred charset template files are stored in. UTF-8 is + // a good choice in most applications: + cfg.setDefaultEncoding("UTF-8"); + + // Sets how errors will appear. + // During web page *development* TemplateExceptionHandler.HTML_DEBUG_HANDLER is better. + cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); + + // Don't log exceptions inside FreeMarker that it will thrown at you anyway: + cfg.setLogTemplateExceptions(false); + + + // availableTemplates.add(new TemplateDescriptor("THREDDS-ONLINE", "Thredds online resources", "Template for online resources exposed by thredds.", "http://sdi-d4s.d4science.org")); + + + ThreddsOnlineTemplate tpl=new ThreddsOnlineTemplate(); + availableTemplates.put(tpl.getDescriptor().getId(), tpl); + templateDescriptors.add(tpl.getDescriptor()); + + + } + +// +// public static String getTHREDDSLinks(ThreddsLinkRequest req) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException{ +// Writer out=null; +// try{ +// Template temp = cfg.getTemplate("OnlineResources.ftlx"); +// ByteArrayOutputStream baos=new ByteArrayOutputStream(); +// out=new OutputStreamWriter(baos); +// temp.process(req, out); +// out.flush(); +// return baos.toString(StandardCharsets.UTF_8.toString()); +// }finally{ +// if(out!=null) +// IOUtils.closeQuietly(out); +// } +// } +// +// +// +// +// public MetadataTemplateManagerImpl() { +// // TODO Auto-generated constructor stub +// } + + + @Override + public Set getAvailableTemplates() { + return new HashSet<>(templateDescriptors); + } + + @Override + public MetadataReport applyTemplates(File original, Set invocations) { + MetadataReport report=new MetadataReport(); + HashSet appliedTemplates=new HashSet<>(); + for(TemplateInvocation invocation:invocations){ + try{ + applyTemplate(original, invocation); + appliedTemplates.add(invocation.getToInvokeTemplateID()); + }catch(Throwable t){ + log.warn("Unable to apply template {} ",invocation.getToInvokeTemplateID()); + } + } + report.setAppliedTemplates(appliedTemplates); + return report; + } + + private static void applyTemplate(File original,TemplateInvocation invocation) throws Exception{ + log.debug("Instantiating "+invocation); + AbstractTemplate tpl=availableTemplates.get(invocation.getToInvokeTemplateID()); + if(tpl==null) throw new InvalidTemplateInvocationException("Template with ID "+invocation.getToInvokeTemplateID()+" was not found"); + Writer out=null; + MetadataHandler handler=new MetadataHandler(original); + try{ + Template temp = cfg.getTemplate(tpl.getFileName()); + ByteArrayOutputStream baos=new ByteArrayOutputStream(); + out=new OutputStreamWriter(baos); + temp.process(tpl.getInstantiationRequest(handler,invocation), out); + out.flush(); + String instantiatedTemplate= baos.toString(StandardCharsets.UTF_8.toString()); + + //apply to original + handler.addContent(instantiatedTemplate, tpl.getInsertionPoint()); + + } catch (Exception e) { + log.error("Unable to apply template. Invocation was {} ",invocation,e); + throw e; + }finally{ + if(out!=null) + IOUtils.closeQuietly(out); + } + } + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataUtils.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataUtils.java new file mode 100644 index 0000000..5ce7271 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/MetadataUtils.java @@ -0,0 +1,126 @@ +package org.gcube.spatial.data.sdi.engine.impl.metadata; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; + +import org.gcube.common.resources.gcore.utils.XPathHelper; +import org.gcube.portlets.user.uriresolvermanager.UriResolverManager; +import org.gcube.portlets.user.uriresolvermanager.exception.IllegalArgumentException; +import org.gcube.portlets.user.uriresolvermanager.exception.UriResolverMapException; +import org.gcube.spatial.data.geonetwork.utils.ScopeUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public class MetadataUtils { + + public static Transformer transformer =null; + public static DocumentBuilder docBuilder =null; + + + static HashMap namespaces=new HashMap(); + + static{ + try{ + DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + + docBuilder = factory.newDocumentBuilder(); + + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformer = transformerFactory.newTransformer(); + + + namespaces.put("gmd", "http://www.isotc211.org/2005/gmd"); + namespaces.put("gco", "http://www.isotc211.org/2005/gco"); + namespaces.put("fra", "http://www.cnig.gouv.fr/2005/fra"); + namespaces.put("xlink", "http://www.w3.org/1999/xlink"); + namespaces.put("gml", "http://www.opengis.net/gml"); + namespaces.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + namespaces.put("gmi", "http://www.isotc211.org/2005/gmi"); + namespaces.put("gmx", "http://www.isotc211.org/2005/gmx"); + + + + + }catch(Exception e){ + throw new RuntimeException("Unable to init Fixer ",e); + } + } + + + public static enum Position{ + sibling_after,sibling_before,first_child,last_child,replace + } + + public static XPathHelper getHelper(Node root){ + XPathHelper toReturn =new XPathHelper(root); + for(Entry entry:namespaces.entrySet()) + toReturn.addNamespace(entry.getKey(), entry.getValue()); + return toReturn; + } + + + public static String readFile(String path) throws IOException{ + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded); + } + + public static String getGisLinkByUUID(String uuid) throws UriResolverMapException, IllegalArgumentException{ + Map params=new HashMap(); + params.put("scope", ScopeUtils.getCurrentScope()); + params.put("gis-UUID", uuid); + UriResolverManager resolver = new UriResolverManager("GIS"); + String toReturn= resolver.getLink(params, false); + return toReturn; + } + + public static void addContent(String path, Document doc, String toAddContent, XPathHelper documentHelper,Position position) throws SAXException, IOException{ + NodeList nodelist=documentHelper.evaluateForNodes(path); + if(nodelist==null||nodelist.getLength()==0) throw new RuntimeException("Path "+path+" not found in document"); +// if(nodelist.getLength()>1) throw new RuntimeException("Invalid Path "+path+"."+nodelist.getLength()+" entries found"); + Node targetNode=nodelist.item(0); + + Document online=docBuilder.parse(new ByteArrayInputStream(toAddContent.getBytes())); + Node toAdd=doc.importNode(online.getDocumentElement(), true); + switch(position){ + case first_child: { + targetNode.insertBefore(toAdd, targetNode.getFirstChild()); + break; + } + case last_child:{targetNode.appendChild(toAdd); + break;} + case replace : { + Node parent=targetNode.getParentNode(); + parent.replaceChild(toAdd, targetNode); + break; + } + case sibling_after :{ + Node currentlyNext=targetNode.getNextSibling(); + Node parent=targetNode.getParentNode(); + if(currentlyNext!=null)parent.insertBefore(toAdd, currentlyNext); + else parent.appendChild(toAdd); + break; + } + case sibling_before :{ + Node parent=targetNode.getParentNode(); + parent.insertBefore(toAdd, targetNode); + break; + } + } + + } + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/AbstractTemplate.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/AbstractTemplate.java index 9b60ce0..aa4993b 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/AbstractTemplate.java +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/AbstractTemplate.java @@ -1,5 +1,36 @@ package org.gcube.spatial.data.sdi.engine.impl.metadata.templates; -public class AbstractTemplate { +import org.gcube.spatial.data.sdi.engine.impl.metadata.MetadataHandler; +import org.gcube.spatial.data.sdi.engine.impl.metadata.MetadataUtils.Position; +import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor; +import org.gcube.spatial.data.sdi.model.metadata.TemplateInvocation; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@AllArgsConstructor +public abstract class AbstractTemplate { + + + + @Getter + @Setter + @ToString + @AllArgsConstructor + public static class InsertionPoint{ + private Position position; + private String elementReference; + } + + + private String fileName; + private InsertionPoint insertionPoint; + private TemplateDescriptor descriptor; + + public abstract T getInstantiationRequest(MetadataHandler original, TemplateInvocation invocation) throws InvalidTemplateInvocationException,Exception; + + } diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/InvalidTemplateInvocationException.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/InvalidTemplateInvocationException.java new file mode 100644 index 0000000..6ac74fa --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/InvalidTemplateInvocationException.java @@ -0,0 +1,36 @@ +package org.gcube.spatial.data.sdi.engine.impl.metadata.templates; + +public class InvalidTemplateInvocationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 8921135030360257131L; + + public InvalidTemplateInvocationException() { + super(); + // TODO Auto-generated constructor stub + } + + public InvalidTemplateInvocationException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + // TODO Auto-generated constructor stub + } + + public InvalidTemplateInvocationException(String message, Throwable cause) { + super(message, cause); + // TODO Auto-generated constructor stub + } + + public InvalidTemplateInvocationException(String message) { + super(message); + // TODO Auto-generated constructor stub + } + + public InvalidTemplateInvocationException(Throwable cause) { + super(cause); + // TODO Auto-generated constructor stub + } + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/ThreddsOnlineTemplate.java b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/ThreddsOnlineTemplate.java new file mode 100644 index 0000000..5d5efc3 --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/engine/impl/metadata/templates/ThreddsOnlineTemplate.java @@ -0,0 +1,51 @@ +package org.gcube.spatial.data.sdi.engine.impl.metadata.templates; + +import org.gcube.spatial.data.sdi.engine.impl.metadata.MetadataHandler; +import org.gcube.spatial.data.sdi.engine.impl.metadata.MetadataUtils; +import org.gcube.spatial.data.sdi.engine.impl.metadata.MetadataUtils.Position; +import org.gcube.spatial.data.sdi.engine.impl.metadata.templates.ThreddsOnlineTemplate.ThreddsOnlineRequest; +import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor; +import org.gcube.spatial.data.sdi.model.metadata.TemplateInvocation; +import org.gcube.spatial.data.sdi.model.metadata.ThreddsOnlineTemplateInvocation; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +public class ThreddsOnlineTemplate extends AbstractTemplate { + + private static String TEMPLATE_ID="THREDDS-ONLINE"; + private static String TEMPLATE_NAME="Thredds Online Resources"; + private static String FILENAME="ThreddsOnlineResources.ftlx"; + private static InsertionPoint INSERTION=new InsertionPoint(Position.sibling_after, ""); + private static TemplateDescriptor DESCRIPTOR=new TemplateDescriptor(TEMPLATE_ID, TEMPLATE_NAME, "Template for online resources exposed by thredds.", "http://sdi-d4s.d4science.org"); + + + public ThreddsOnlineTemplate() { + super(FILENAME, INSERTION, DESCRIPTOR); + } + + + @Getter + @AllArgsConstructor + @ToString + public static class ThreddsOnlineRequest{ + private String hostname; + private String catalog; + private String filename; + private String gisViewerLink; + } + + @Override + public ThreddsOnlineRequest getInstantiationRequest(MetadataHandler handler, TemplateInvocation invocation) throws InvalidTemplateInvocationException,Exception{ + try{ + ThreddsOnlineTemplateInvocation threddsInvocation=(ThreddsOnlineTemplateInvocation) invocation; + String uuid=handler.getUUID(); + String gisLink=MetadataUtils.getGisLinkByUUID(uuid); + return new ThreddsOnlineRequest(threddsInvocation.getHostname(), threddsInvocation.getCatalog(), threddsInvocation.getFilename(), gisLink); + }catch(ClassCastException e){ + throw new InvalidTemplateInvocationException("Invalid invocation type : "+invocation.getClass()); + } + } + +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/rest/GeoNetwork.java b/src/main/java/org/gcube/spatial/data/sdi/rest/GeoNetwork.java index ba5e136..9cfefec 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/rest/GeoNetwork.java +++ b/src/main/java/org/gcube/spatial/data/sdi/rest/GeoNetwork.java @@ -2,12 +2,12 @@ package org.gcube.spatial.data.sdi.rest; import javax.ws.rs.Path; -import org.gcube.spatial.data.sdi.Constants; +import org.gcube.spatial.data.sdi.model.ServiceConstants; import lombok.extern.slf4j.Slf4j; @Slf4j -@Path(Constants.GEONETWORK_INTERFACE) +@Path(ServiceConstants.GeoNetwork.INTERFACE) //@Api(value="GeoNetwork") public class GeoNetwork { // diff --git a/src/main/java/org/gcube/spatial/data/sdi/rest/GeoServer.java b/src/main/java/org/gcube/spatial/data/sdi/rest/GeoServer.java new file mode 100644 index 0000000..f5c087f --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/rest/GeoServer.java @@ -0,0 +1,93 @@ +package org.gcube.spatial.data.sdi.rest; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; + +import org.gcube.spatial.data.sdi.engine.SDIManager; +import org.gcube.spatial.data.sdi.model.ServiceConstants; +import org.gcube.spatial.data.sdi.model.credentials.Credentials; +import org.gcube.spatial.data.sdi.model.service.GeoServerConfiguration; + +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.jaxrs.annotation.JacksonFeatures; + +import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; + +@Path(ServiceConstants.GeoServer.INTERFACE) +@Api(value=ServiceConstants.GeoServer.INTERFACE) +@Slf4j +public class GeoServer { + + private final static String HOST_PATH_PARAM="host"; + + + @Inject + private SDIManager sdi; + + @GET + @Path("configuration/{"+HOST_PATH_PARAM+"}") + @Produces(MediaType.APPLICATION_JSON) + @JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT }) + public GeoServerConfiguration getInstanceConfiguration(@PathParam(HOST_PATH_PARAM) String host){ + try{ + log.trace("Serving credentials for host {} ",host); + host=getHost(host); + List geoservers=sdi.getContextConfiguration().getGeoserverClusterConfiguration().getAvailableInstances(); + log.trace("Got {} geoservers in current scope ",geoservers.size()); + for(GeoServerConfiguration config : geoservers){ + String configHost=getHost(config.getBaseEndpoint()); + if(configHost.equals(host)) + return config; + } + throw new WebApplicationException("Host "+host+" not found in context"); + }catch(WebApplicationException e){ + throw e; + }catch(Exception e){ + throw new WebApplicationException("Unable to serve request", e); + } + } + + + @GET + @Path("credentials/{"+HOST_PATH_PARAM+"}") + @Produces(MediaType.APPLICATION_JSON) + @JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT }) + public Credentials getInstanceCredentials(@PathParam(HOST_PATH_PARAM) String host){ + try{ + log.trace("Serving credentials for host {} ",host); + host=getHost(host); + List geoservers=sdi.getContextConfiguration().getGeoserverClusterConfiguration().getAvailableInstances(); + log.trace("Got {} geoservers in current scope ",geoservers.size()); + for(GeoServerConfiguration config : geoservers){ + String configHost=getHost(config.getBaseEndpoint()); + if(configHost.equals(host)) + return config.getAccessibleCredentials().get(0); + } + throw new WebApplicationException("Host "+host+" not found in context"); + }catch(WebApplicationException e){ + throw e; + }catch(Exception e){ + throw new WebApplicationException("Unable to serve request", e); + } + } + + + private static final String getHost(String endpoint) throws MalformedURLException{ + log.debug("Get host from endpoint {} ",endpoint); + if(endpoint.startsWith("http")){ + log.debug("Endpoint seems url.."); + return new URL(endpoint).getHost(); + } + return endpoint; + } +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/rest/Metadata.java b/src/main/java/org/gcube/spatial/data/sdi/rest/Metadata.java new file mode 100644 index 0000000..5e34c7c --- /dev/null +++ b/src/main/java/org/gcube/spatial/data/sdi/rest/Metadata.java @@ -0,0 +1,57 @@ +package org.gcube.spatial.data.sdi.rest; + +import java.io.InputStream; +import java.util.List; +import java.util.Set; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.gcube.spatial.data.sdi.engine.MetadataTemplateManager; +import org.gcube.spatial.data.sdi.model.ServiceConstants; +import org.gcube.spatial.data.sdi.model.metadata.MetadataReport; +import org.gcube.spatial.data.sdi.model.metadata.TemplateDescriptor; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Path(ServiceConstants.Metadata.INTERFACE) +public class Metadata { + + @Inject + MetadataTemplateManager templateManager; + + + @POST + @Path("/{gnCategory}") + @Consumes(MediaType.WILDCARD) + @Produces(MediaType.APPLICATION_JSON) + public MetadataReport pushMetadata(@QueryParam(ServiceConstants.Metadata.VALIDATE_PARAMETER) @DefaultValue("true") Boolean validate, + @QueryParam(ServiceConstants.Metadata.PUBLIC_PARAMETER) @DefaultValue("false") Boolean makePublic, + + @FormDataParam(ServiceConstants.Metadata.UPLOADED_FILE_PARAMETER) InputStream uploadedMeta, + @FormDataParam(ServiceConstants.Metadata.UPLOADED_FILE_PARAMETER) FormDataContentDisposition uploadedMetaDetails, + @FormDataParam(ServiceConstants.Metadata.METADATA_ENRICHMENTS_PARAMETER) Set metadataEnrichments){ + + //Receive metadata + //Optionally enrich it + //Publish it NB : validate & make public + return null; + } + + @GET + @Path("/list") + @Produces(MediaType.APPLICATION_JSON) + public Set getList(){ + return templateManager.getAvailableTemplates(); + } +} diff --git a/src/main/java/org/gcube/spatial/data/sdi/rest/SDI.java b/src/main/java/org/gcube/spatial/data/sdi/rest/SDI.java index 1220dca..ce90cf6 100644 --- a/src/main/java/org/gcube/spatial/data/sdi/rest/SDI.java +++ b/src/main/java/org/gcube/spatial/data/sdi/rest/SDI.java @@ -6,17 +6,17 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import org.gcube.spatial.data.sdi.Constants; import org.gcube.spatial.data.sdi.engine.SDIManager; import org.gcube.spatial.data.sdi.model.ScopeConfiguration; +import org.gcube.spatial.data.sdi.model.ServiceConstants; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.jaxrs.annotation.JacksonFeatures; import io.swagger.annotations.Api; -@Path(Constants.SDI_INTERFACE) -@Api(value=Constants.SDI_INTERFACE) +@Path(ServiceConstants.INTERFACE) +@Api(value=ServiceConstants.INTERFACE) public class SDI { @Inject diff --git a/src/main/webapp/WEB-INF/README b/src/main/webapp/WEB-INF/README index 1cd9e37..fc64f84 100644 --- a/src/main/webapp/WEB-INF/README +++ b/src/main/webapp/WEB-INF/README @@ -25,7 +25,7 @@ no. 654119), SoBigData (grant no. 654024); Version -------------------------------------------------- -1.0.0-SNAPSHOT (2017-07-05) +1.1.0-SNAPSHOT (2017-06-19) Please see the file named "changelog.xml" in this directory for the release notes. diff --git a/src/main/webapp/WEB-INF/changelog.xml b/src/main/webapp/WEB-INF/changelog.xml index 393e4ec..14e216e 100644 --- a/src/main/webapp/WEB-INF/changelog.xml +++ b/src/main/webapp/WEB-INF/changelog.xml @@ -4,5 +4,6 @@ Added GeoServer interface + Added Metadata interface \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/config.properties b/src/main/webapp/WEB-INF/config.properties index c358e97..1d291aa 100644 --- a/src/main/webapp/WEB-INF/config.properties +++ b/src/main/webapp/WEB-INF/config.properties @@ -13,4 +13,6 @@ th.cache.TTL=120000 th.se.category=Gis th.se.platform=thredds th.ge.serviceClass=SDI -th.ge.serviceName=THREDDS \ No newline at end of file +th.ge.serviceName=THREDDS +#Metadata +meta.tpl.folder=metadataTemplates \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/gcube-app.xml b/src/main/webapp/WEB-INF/gcube-app.xml index 0e1ff87..d034671 100644 --- a/src/main/webapp/WEB-INF/gcube-app.xml +++ b/src/main/webapp/WEB-INF/gcube-app.xml @@ -1,7 +1,7 @@ sdi-service SDI - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT REST Interface towards SDI facilities diff --git a/src/main/webapp/WEB-INF/metadataTemplates/ThreddsOnlineResources.ftlx b/src/main/webapp/WEB-INF/metadataTemplates/ThreddsOnlineResources.ftlx new file mode 100644 index 0000000..e00e7ba --- /dev/null +++ b/src/main/webapp/WEB-INF/metadataTemplates/ThreddsOnlineResources.ftlx @@ -0,0 +1,220 @@ + + + + + + OPeNDAP + + + 2.0.0 + + + + + + + NetCDFSubSet + + + 1.0.0 + + + + + + + WCS + + + 1.0.0 + + + + + + + WMS + + + 1.1.0 + + + + + + + HTTPServer + + + 1.1.0 + + + + + + + NCML + + + 1.0.0 + + + + + + + UDDC + + + 1.0.0 + + + + + + + <#if catalog??> + <#assign cataloguedPath=catalog+"/"+filename> + <#else> + <#assign cataloguedPath=filename> + + + <#assign layername=filename?keep_before_last(".")> + + + + + http://${hostname}/thredds/dodsC/public/netcdf/${cataloguedPath} + + + WWW:LINK-1.0-http--link + + + ${layername} : OPeNDAP + + + GIS data (OPenNDAP) + + + + + + + + http://${hostname}/thredds/ncss/public/netcdf/${cataloguedPath} + + + WWW:LINK-1.0-http--link + + + ${layername} : NetCDF Subset + + + GIS data (NetCDF Subset) + + + + + + + + http://${hostname}/thredds/wcs/public/netcdf/${cataloguedPath}?service=wcs&version=1.0.0&request=GetCoverage&coverage=${layername}&CRS=EPSG:4326&format=geotiff + + + OGC:WCS-1.0.0-http-get-coverage + + + ${layername} : WCS + + + GIS data (WCS) + + + + + + + + http://${hostname}/thredds/wms/public/netcdf/${cataloguedPath} + + + OGC:WMS-1.3.0-http-get-map + + + ${layername} : WMS + + + GIS data (WMS) + + + + + + + + http://${hostname}/thredds/fileServer/public/netcdf/${cataloguedPath} + + + WWW:LINK-1.0-http--link + + + ${layername} : HTTP + + + GIS data (HTTP FileServer) + + + + + + + + http://${hostname}/thredds/ncml/public/netcdf/${cataloguedPath} + + + WWW:LINK-1.0-http--link + + + ${layername} : NCML + + + GIS metadata (NCML Format) + + + + + + + + + http://${hostname}/thredds/uddc/public/netcdf/${cataloguedPath} + + + WWW:LINK-1.0-http--link + + + ${layername} : UDDC + + + GIS metadata quality (UDDC) + + + + + + + + ${gisViewerLink} + + + WWW:LINK-1.0-http--link + + + GIS Viewer link + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/profile.xml b/src/main/webapp/WEB-INF/profile.xml index bfc8d18..1867fa0 100644 --- a/src/main/webapp/WEB-INF/profile.xml +++ b/src/main/webapp/WEB-INF/profile.xml @@ -10,11 +10,11 @@ sdi-service - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT org.gcube.spatial.data sdi-service - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT sdi-service.jar diff --git a/src/test/java/org/gcube/spatial/data/sdi/test/ConfigurationTest.java b/src/test/java/org/gcube/spatial/data/sdi/test/ConfigurationTest.java new file mode 100644 index 0000000..807d2a6 --- /dev/null +++ b/src/test/java/org/gcube/spatial/data/sdi/test/ConfigurationTest.java @@ -0,0 +1,25 @@ +package org.gcube.spatial.data.sdi.test; + +import java.net.URL; + +import org.gcube.spatial.data.sdi.LocalConfiguration; +import org.gcube.spatial.data.sdi.engine.impl.GISManagerImpl; +import org.gcube.spatial.data.sdi.engine.impl.GeoNetworkManagerImpl; +import org.gcube.spatial.data.sdi.engine.impl.SDIManagerImpl; +import org.gcube.spatial.data.sdi.engine.impl.ThreddsManagerImpl; + +public class ConfigurationTest { + + public static void main(String[] args) { + TokenSetter.set("/gcube/devNext"); + + URL propertiesURL=ConfigurationTest.class.getResource("/WEB-INF/config.properties"); + + LocalConfiguration.init(propertiesURL); + + SDIManagerImpl sdi=new SDIManagerImpl(new GeoNetworkManagerImpl(), new ThreddsManagerImpl(), new GISManagerImpl()); + + System.out.println(sdi.getContextConfiguration()); + } + +} diff --git a/src/test/java/org/gcube/spatial/data/sdi/test/MainTest.java b/src/test/java/org/gcube/spatial/data/sdi/test/MainTest.java index b900244..5b0f0aa 100644 --- a/src/test/java/org/gcube/spatial/data/sdi/test/MainTest.java +++ b/src/test/java/org/gcube/spatial/data/sdi/test/MainTest.java @@ -3,12 +3,12 @@ package org.gcube.spatial.data.sdi.test; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; -import org.gcube.spatial.data.sdi.Constants; import org.gcube.spatial.data.sdi.SDIService; import org.gcube.spatial.data.sdi.engine.GISManager; import org.gcube.spatial.data.sdi.engine.GeoNetworkManager; import org.gcube.spatial.data.sdi.engine.SDIManager; import org.gcube.spatial.data.sdi.engine.ThreddsManager; +import org.gcube.spatial.data.sdi.model.ServiceConstants; import org.gcube.spatial.data.sdi.rest.GeoNetwork; import org.glassfish.hk2.utilities.binding.AbstractBinder; import org.glassfish.jersey.server.ResourceConfig; @@ -39,7 +39,7 @@ public class MainTest extends JerseyTest{ @Override protected Application configure() { - System.out.println("Configuration for "+Constants.APPLICATION); + System.out.println("Configuration for "+ServiceConstants.APPLICATION); ResourceConfig config= new ResourceConfig(SDIService.class); config.register(new MyBinder()); @@ -80,9 +80,13 @@ public class MainTest extends JerseyTest{ @Test public void getConfiguration(){ - System.out.println(target(Constants.SDI_INTERFACE).request(MediaType.APPLICATION_JSON_TYPE).get(String.class)); + System.out.println(target(ServiceConstants.INTERFACE).request(MediaType.APPLICATION_JSON_TYPE).get(String.class)); } + @Test + public void getGeoServer(){ + System.out.println(target(ServiceConstants.GeoServer.INTERFACE).path("configuration/geoserver-dev.research-infrastructures.eu").request(MediaType.APPLICATION_JSON_TYPE).get(String.class)); + } // // @Test diff --git a/src/test/java/org/gcube/spatial/data/sdi/test/TestCommon.java b/src/test/java/org/gcube/spatial/data/sdi/test/TestCommon.java index cc0a074..6e54dee 100644 --- a/src/test/java/org/gcube/spatial/data/sdi/test/TestCommon.java +++ b/src/test/java/org/gcube/spatial/data/sdi/test/TestCommon.java @@ -2,6 +2,6 @@ package org.gcube.spatial.data.sdi.test; public class TestCommon { - public static final String TEST_SCOPE="/gcube/devsec"; + public static final String TEST_SCOPE="/gcube/devNext"; }