From ff5e080b06726f0f1ddcbb5aec6d8bc861922833 Mon Sep 17 00:00:00 2001 From: Francesco Mangiacrapa Date: Tue, 28 Feb 2017 15:55:31 +0000 Subject: [PATCH] completed task #6952 git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/data-transfer/uri-resolver@144433 82a268e6-3cf1-43bd-a215-b396298e98cf --- distro/changelog.xml | 3 +- .../resolver/catalogue/CatalogueResolver.java | 23 ++- ...tionProfileReaderForCatalogueResolver.java | 53 ++++-- .../CkanPorltetApplicationProfile.java | 2 +- ...teApplicationProfileCatalogueResolver.java | 156 ++++++++++++++++++ 5 files changed, 223 insertions(+), 14 deletions(-) rename src/main/java/org/gcube/datatransfer/resolver/catalogue/{ => resource}/ApplicationProfileReaderForCatalogueResolver.java (83%) rename src/main/java/org/gcube/datatransfer/resolver/catalogue/{ => resource}/CkanPorltetApplicationProfile.java (97%) create mode 100644 src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/UpdateApplicationProfileCatalogueResolver.java diff --git a/distro/changelog.xml b/distro/changelog.xml index dc4af9f..9c92636 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -63,7 +63,8 @@ + date="2017-02-28"> [Task #6492] Catalogue Resolver: "improve"/"build better" public URLs to products + [Task #6952] Catalogue Resolver: update on the fly the Application Profile for VRE's used to resolve Product URL \ No newline at end of file diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/CatalogueResolver.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/CatalogueResolver.java index 2c39b44..3bf675b 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/CatalogueResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/CatalogueResolver.java @@ -19,6 +19,10 @@ import org.gcube.common.encryption.StringEncrypter; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.datatransfer.resolver.ResourceCatalogueCodes; import org.gcube.datatransfer.resolver.UriResolverRewriteFilter; +import org.gcube.datatransfer.resolver.applicationprofile.ApplicationProfileNotFoundException; +import org.gcube.datatransfer.resolver.catalogue.resource.ApplicationProfileReaderForCatalogueResolver; +import org.gcube.datatransfer.resolver.catalogue.resource.CkanPorltetApplicationProfile; +import org.gcube.datatransfer.resolver.catalogue.resource.UpdateApplicationProfileCatalogueResolver; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -210,7 +214,7 @@ public class CatalogueResolver extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - CatalogueEntityRequest cer = new CatalogueEntityRequest(); + final CatalogueEntityRequest cer = new CatalogueEntityRequest(); String originalScope = null; try{ String jsonRequest = IOUtils.toString(req.getInputStream()); @@ -289,7 +293,7 @@ public class CatalogueResolver extends HttpServlet{ logger.info("Clear URL is: "+bClearURL); if(bClearURL){ - String vreName = scope.substring(scope.lastIndexOf("/")+1, scope.length()); + final String vreName = scope.substring(scope.lastIndexOf("/")+1, scope.length()); //buildLink+=PATH_SEPARATOR+vreName+PATH_SEPARATOR+cer.getValueOfParameter(CatalogueRequestParameter.ENTITY_CONTEXT.getKey())+PATH_SEPARATOR+cer.getValueOfParameter(CatalogueRequestParameter.ENTITY_NAME.getKey()); String econtext = cer.getValueOfParameter(CatalogueRequestParameter.ENTITY_CONTEXT.getKey()); ResourceCatalogueCodes rc = ResourceCatalogueCodes.valueOfCodeValue(econtext); @@ -300,6 +304,21 @@ public class CatalogueResolver extends HttpServlet{ } buildLink += PATH_SEPARATOR+rc.getId()+PATH_SEPARATOR+vreName+PATH_SEPARATOR+cer.getValueOfParameter(CatalogueRequestParameter.ENTITY_NAME.getKey()); logger.info("Writing Decoded Catalogue Link: "+buildLink); + + //IT'S GOING TO UPDATE THE GENERIC RESOURCE IF IS NEEDED + new Thread(){ + public void run() { + try { + String fullScope = cer.getValueOfParameter(CatalogueRequestParameter.GCUBE_SCOPE.getKey()); + UpdateApplicationProfileCatalogueResolver.validateEndPoint(scopeToEncDecr, vreName, fullScope); + } + catch (ApplicationProfileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }; + }.start(); + }else{ //ADDING THE SERVLET NAME buildLink += req.getRequestURI(); diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/ApplicationProfileReaderForCatalogueResolver.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/ApplicationProfileReaderForCatalogueResolver.java similarity index 83% rename from src/main/java/org/gcube/datatransfer/resolver/catalogue/ApplicationProfileReaderForCatalogueResolver.java rename to src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/ApplicationProfileReaderForCatalogueResolver.java index 1099e39..44542c6 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/ApplicationProfileReaderForCatalogueResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/ApplicationProfileReaderForCatalogueResolver.java @@ -1,7 +1,7 @@ /* * */ -package org.gcube.datatransfer.resolver.catalogue; +package org.gcube.datatransfer.resolver.catalogue.resource; import static org.gcube.resources.discovery.icclient.ICFactory.client; @@ -23,7 +23,8 @@ import org.gcube.datatransfer.resolver.applicationprofile.ScopeUtil; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.Query; import org.gcube.resources.discovery.client.queries.impl.QueryBox; -import org.w3c.dom.Node; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.xml.sax.InputSource; @@ -35,24 +36,33 @@ import org.xml.sax.InputSource; */ public class ApplicationProfileReaderForCatalogueResolver { + public static final String VRE_NAME = "VRE_NAME"; + public static final String SCOPE = "SCOPE"; + public static final String END_POINT = "EndPoint"; + public static final String BODY = "Body"; + + public static final String SECONDARY_TYPE = "ApplicationProfile"; public static final String RESOURCE_NAME = "Catalogue-Resolver"; protected static final String RESOURCE_PROFILE_NAME_TEXT = "/Resource/Profile/Name/text()"; protected static final String RESOURCE_PROFILE_DESCRIPTION_TEXT = "/Resource/Profile/Description/text()"; - protected static final String RESOURCE_PROFILE_BODY_END_POINT_SCOPE_TEXT = "/Resource/Profile/Body/EndPoint/SCOPE/text()"; - protected static final String RESOURCE_PROFILE_BODY_END_POINT_VRE_NAME_TEXT = "/Resource/Profile/Body/EndPoint/VRE_NAME/text()"; + protected static final String RESOURCE_PROFILE_BODY_END_POINT_SCOPE_TEXT = "/Resource/Profile/"+BODY+"/"+END_POINT+"/"+SCOPE+"/text()"; + protected static final String RESOURCE_PROFILE_BODY_END_POINT_VRE_NAME_TEXT = "/Resource/Profile/"+BODY+"/"+END_POINT+"/"+VRE_NAME+"/text()"; + private Logger logger = Logger.getLogger(ApplicationProfileReaderForCatalogueResolver.class); private String secondaryType; private String resourceName; private String scope; private boolean useRootScope = false; + private Document document; /** The hash vre name scope. * Used by Catalogue Resolver for mapping VRE NAME with its SCOPE where to fetch the Data Catalogue Portlet so that resolve correctly URL of * kind: http://[CATALOGUE_RESOLVER_SERVLET]/[VRE_NAME]/[entity_context value]/[entity_name value] * */ private Map hashVreNameScope = new HashMap(); + private Element rootElement; /** * Instantiates a new application profile reader for catalogue resolver. @@ -69,7 +79,7 @@ public class ApplicationProfileReaderForCatalogueResolver { } /** - * Read profile from infrastrucure and fills the map {@link #hashVreNameScope} + * Read profile from infrastrucure and fills the map {@link #hashVreNameScope}. */ private void readProfileFromInfrastrucure() { @@ -91,9 +101,10 @@ public class ApplicationProfileReaderForCatalogueResolver { else { try{ String elem = appProfile.get(0); - DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); - Node node = docBuilder.parse(new InputSource(new StringReader(elem))).getDocumentElement(); - XPathHelper helper = new XPathHelper(node); + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + document = docBuilder.parse(new InputSource(new StringReader(elem))); + rootElement = document.getDocumentElement(); + XPathHelper helper = new XPathHelper(rootElement); List scopes = helper.evaluate(RESOURCE_PROFILE_BODY_END_POINT_SCOPE_TEXT); for (String scopeFound : scopes) { List vreName = helper.evaluate("/Resource/Profile/Body/EndPoint[SCOPE='"+scopeFound.toString()+"']/VRE_NAME/text()"); @@ -120,7 +131,31 @@ public class ApplicationProfileReaderForCatalogueResolver { } + /** + * Gets the root document. + * + * @return the rootDocument + */ + public Element getRootDocument() { + + return rootElement; + } + + + /** + * Gets the document. + * + * @return the document + */ + public Document getDocument(){ + return document; + } + + + /** + * Gets the hash vre name scope. + * * @return the hashVreNameScope */ public Map getHashVreNameScope() { @@ -157,6 +192,4 @@ public class ApplicationProfileReaderForCatalogueResolver { ApplicationProfileReaderForCatalogueResolver reader = new ApplicationProfileReaderForCatalogueResolver(scope, true); System.out.println(reader); }*/ - - } diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/CkanPorltetApplicationProfile.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanPorltetApplicationProfile.java similarity index 97% rename from src/main/java/org/gcube/datatransfer/resolver/catalogue/CkanPorltetApplicationProfile.java rename to src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanPorltetApplicationProfile.java index 25d38cb..a9c5eae 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/catalogue/CkanPorltetApplicationProfile.java +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/CkanPorltetApplicationProfile.java @@ -2,7 +2,7 @@ * */ -package org.gcube.datatransfer.resolver.catalogue; +package org.gcube.datatransfer.resolver.catalogue.resource; import static org.gcube.resources.discovery.icclient.ICFactory.client; diff --git a/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/UpdateApplicationProfileCatalogueResolver.java b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/UpdateApplicationProfileCatalogueResolver.java new file mode 100644 index 0000000..017a2cf --- /dev/null +++ b/src/main/java/org/gcube/datatransfer/resolver/catalogue/resource/UpdateApplicationProfileCatalogueResolver.java @@ -0,0 +1,156 @@ +/** + * + */ + +package org.gcube.datatransfer.resolver.catalogue.resource; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.List; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.log4j.Logger; +import org.gcube.common.resources.gcore.GenericResource; +import org.gcube.common.resources.gcore.Resource; +import org.gcube.common.resources.gcore.Resources; +import org.gcube.common.resources.gcore.utils.XPathHelper; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.datatransfer.resolver.applicationprofile.ApplicationProfileNotFoundException; +import org.gcube.datatransfer.resolver.applicationprofile.ScopeUtil; +import org.gcube.informationsystem.publisher.RegistryPublisherFactory; +import org.gcube.informationsystem.publisher.ScopedPublisher; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * The Class UpdateApplicationProfileCatalogueResolver. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Feb 28, 2017 + */ +public class UpdateApplicationProfileCatalogueResolver { + + + private static Logger logger = Logger.getLogger(UpdateApplicationProfileCatalogueResolver.class); + private static boolean useRootScope = false; + + + /** + * Validate end point. If the EndPoint VRE-FULLNAME does not exist it will be added to Application Profile: {@link ApplicationProfileReaderForCatalogueResolver#RESOURCE_NAME} + * + * @param scopeToInstanceResolver the scope to instance resolver + * @param VRE the vre + * @param fullScope the full scope + * @throws ApplicationProfileNotFoundException the application profile not found exception + */ + public static void validateEndPoint(String scopeToInstanceResolver, String VRE, String fullScope) throws ApplicationProfileNotFoundException { + logger.info("Checking if the VRE_NAME: "+VRE+", exists into Application Profile: "+ApplicationProfileReaderForCatalogueResolver.RESOURCE_NAME+" using scope: "+scopeToInstanceResolver); + ApplicationProfileReaderForCatalogueResolver appPrCatResolver = new ApplicationProfileReaderForCatalogueResolver(scopeToInstanceResolver, true); + Element root = appPrCatResolver.getRootDocument(); + String originalScope = null; + try { + XPathHelper helper = new XPathHelper(root); + List scopes = helper.evaluate(ApplicationProfileReaderForCatalogueResolver.RESOURCE_PROFILE_BODY_END_POINT_SCOPE_TEXT); + for (String scopeFound : scopes) { + //List vreName = helper.evaluate("/Resource/Profile/Body/EndPoint[SCOPE='" +scopeFound.toString() + "']/VRE_NAME/text()"); + if(fullScope.compareTo(scopeFound)==0){ + logger.info("The full scope: " + fullScope + ", exists into "+ApplicationProfileReaderForCatalogueResolver.RESOURCE_NAME+", skipping update VRE_NAME: "+VRE); + return; + } + } + + logger.info("The full scope: " + fullScope + ", does not exist into "+ApplicationProfileReaderForCatalogueResolver.RESOURCE_NAME+", creating the new end point VRE_NAME: "+VRE+", fullScope: "+fullScope); + NodeList body = root.getElementsByTagName(ApplicationProfileReaderForCatalogueResolver.BODY); + + if(body==null || body.getLength()==0) + throw new Exception("Body not found"); + + Document document = addNewEndPoint(appPrCatResolver.getDocument(), VRE, fullScope); + + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3"); + //initialize StreamResult with File object to save to file + StreamResult result = new StreamResult(new StringWriter()); + DOMSource source2 = new DOMSource(document); + transformer.transform(source2, result); + + logger.trace("Updated resource: \n"+result.getWriter().toString()); + + originalScope = ScopeProvider.instance.get(); + String discoveryScope = useRootScope?ScopeUtil.getInfrastructureNameFromScope(scopeToInstanceResolver):scopeToInstanceResolver; + ScopeProvider.instance.set(discoveryScope); + + ScopedPublisher rp=RegistryPublisherFactory.scopedPublisher(); + Resource resource = toResource(result); + rp.update(resource); + logger.trace("Generic Resource updated on IS successfully"); + } + catch (Exception e) { + logger.error("Error ", e); + throw new ApplicationProfileNotFoundException("Error during parsing application profile with resource name: " +ApplicationProfileReaderForCatalogueResolver.RESOURCE_NAME + " in the scope: " + scopeToInstanceResolver); + }finally{ + if(originalScope!=null && !originalScope.isEmpty()){ + ScopeProvider.instance.set(originalScope); + logger.info("scope provider setted to orginal scope: "+originalScope); + }else{ + ScopeProvider.instance.reset(); + logger.info("scope provider reset"); + } + } + } + + + /** + * To resource. + * + * @param result the result + * @return the generic resource + */ + private static GenericResource toResource(StreamResult result){ + InputStream is = new ByteArrayInputStream(result.getWriter().toString().getBytes()); + return Resources.unmarshal(GenericResource.class, is); + } + + + + /** + * Adds the new end point. + * + * @param document the document + * @param VRE the vre + * @param fullScope the full scope + * @return the document + */ + private static Document addNewEndPoint(Document document, String VRE, String fullScope){ + Element newEndPoint = document.createElement(ApplicationProfileReaderForCatalogueResolver.END_POINT); + Element newScope = document.createElement(ApplicationProfileReaderForCatalogueResolver.SCOPE); + newScope.setTextContent(fullScope); + Element newVREName = document.createElement(ApplicationProfileReaderForCatalogueResolver.VRE_NAME); + newVREName.setTextContent(VRE); + + newEndPoint.appendChild(newScope); + newEndPoint.appendChild(newVREName); + document.getElementsByTagName(ApplicationProfileReaderForCatalogueResolver.BODY).item(0).appendChild(newEndPoint); + + return document; + } + + public static void main(String[] args) { + + String scope = "/gcube"; + try { + UpdateApplicationProfileCatalogueResolver.validateEndPoint( + scope, "gcube", "/gcube/devsec"); + } + catch (Exception e) { + e.printStackTrace(); + } +} +}