This commit is contained in:
Costantino Perciante 2017-03-31 15:09:06 +00:00
commit 228c8c57b9
34 changed files with 3207 additions and 0 deletions

32
.classpath Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

42
.project Normal file
View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>catalogue-ws</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

13
.settings/.jsdtscope Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/webapp"/>
<classpathentry kind="src" path="target/m2e-wtp/web-resources"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.7

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="catalogue-ws">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<property name="context-root" value="catalogue-ws"/>
<property name="java-output-path" value="/catalogue-ws/target/classes"/>
</wb-module>
</project-modules>

View File

@ -0,0 +1,7 @@
<root>
<facet id="jst.jaxrs">
<node name="libprov">
<attribute name="provider-id" value="jaxrs-no-op-library-provider"/>
</node>
</facet>
</root>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="wst.jsdt.web"/>
<installed facet="jst.web" version="3.0"/>
<installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="java" version="1.7"/>
<installed facet="jst.jaxrs" version="2.0"/>
</faceted-project>

View File

@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -0,0 +1 @@
Window

View File

@ -0,0 +1,2 @@
disabled=06target
eclipse.preferences.version=1

224
pom.xml Normal file
View File

@ -0,0 +1,224 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maven-parent</artifactId>
<groupId>org.gcube.tools</groupId>
<version>1.0.0</version>
<relativePath />
</parent>
<groupId>org.gcube.datacatalogue</groupId>
<artifactId>catalogue-ws</artifactId>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>catalogue-ws</name>
<description>
This service allows other services to publish on the catalogue.
</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-smartgears-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.jersey>2.25.1</version.jersey>
<distroDirectory>${project.basedir}/distro</distroDirectory>
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
<distroDirectory>distro</distroDirectory>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.gcube.resources.discovery</groupId>
<artifactId>ic-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>ckan-util-library</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>home-library-jcr</artifactId>
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>common-authorization</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<!-- if your container implements Servlet API older than 3.0, use "jersey-container-servlet-core" -->
<artifactId>jersey-container-servlet-core</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-processing</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${version.jersey}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-sse</artifactId>
<version>${version.jersey}</version>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.glassfish.jersey.ext</groupId> -->
<!-- <artifactId>jersey-bean-validation</artifactId> -->
<!-- <version>${version.jersey}</version> -->
<!-- </dependency> -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>compile</scope>
</dependency>
<!-- SmartGears -->
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
<scope>provided</scope>
</dependency>
<!-- <dependency> -->
<!-- <groupId>org.gcube.common</groupId> -->
<!-- <artifactId>home-library</artifactId> -->
<!-- <version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version> -->
<!-- <scope>compile</scope> -->
<!-- </dependency> -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>${version.jersey}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.grundid.opendatalab</groupId>
<artifactId>geojson-jackson</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
<build>
<finalName>${name}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<!-- SA Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptors>
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>servicearchive</id>
<phase>install</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-profile</id>
<phase>install</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<directory>${distroDirectory}</directory>
<filtering>true</filtering>
<includes>
<include>profile.xml</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

179
profile_test.xml Normal file
View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadataformat metadatatype="software_type"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://wiki.gcube-system.org/images_gcube/e/e8/Gcdcmetadataprofilev3.xsd">
<metadatacategory id="developer_information">
<title>Developer Information</title>
<description>This section is about developer(s) information
</description>
</metadatacategory>
<metadatacategory id="extra_information">
<title>Extras</title>
<description>Other information about the artifact
</description>
</metadatacategory>
<metadatacategory id="artifact_information">
<title>Artifact Information</title>
<description>Artifact's main information
</description>
</metadatacategory>
<metadatafield categoryref="developer_information">
<fieldName>Name</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<defaultValue>Developer's fullname</defaultValue>
<note>The fullname of the developer</note>
<validator>
<regularExpression>/^[a-z ,.'-]+$/i</regularExpression>
</validator>
<tagging create="true" separator="-">onFieldName_onValue</tagging>
</metadatafield>
<metadatafield categoryref="developer_information">
<fieldName>Identifier</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<defaultValue>Developer's identifier</defaultValue>
<note>The identifier of the developer</note>
</metadatafield>
<metadatafield categoryref="artifact_information">
<fieldName>Artifact Name</fieldName>
<dataType>String</dataType>
<note>The name of the artifact</note>
<tagging create="true" separator="-">onFieldName_onValue</tagging>
</metadatafield>
<metadatafield categoryref="artifact_information">
<fieldName>Programming language</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<note>The programming language used to create the artifact</note>
<vocabulary isMultiSelection="true">
<vocabularyField>Java</vocabularyField>
<vocabularyField>C++</vocabularyField>
<vocabularyField>C</vocabularyField>
<vocabularyField>Python</vocabularyField>
<vocabularyField>Scala</vocabularyField>
<vocabularyField>Javascript</vocabularyField>
</vocabulary>
<tagging create="true" separator="-">onValue</tagging>
</metadatafield>
<metadatafield categoryref="artifact_information">
<fieldName>Used Framework</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<note>The Framework used to create the artifact</note>
<vocabulary isMultiSelection="false">
<vocabularyField>GWT</vocabularyField>
<vocabularyField>Bootstrap</vocabularyField>
<vocabularyField>GWT-Bootstrap</vocabularyField>
<vocabularyField>JQuery</vocabularyField>
<vocabularyField>AKKA</vocabularyField>
</vocabulary>
<tagging create="true" separator="-">onValue</tagging>
</metadatafield>
<metadatafield categoryref="artifact_information">
<fieldName>Maven Location</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<note>The maven location of the artifact</note>
<validator>
<regularExpression>https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,}
</regularExpression>
</validator>
</metadatafield>
<metadatafield categoryref="extra_information">
<fieldName>First Release</fieldName>
<mandatory>true</mandatory>
<dataType>Time</dataType>
<note>Date of the first release</note>
</metadatafield>
<metadatafield categoryref="extra_information">
<fieldName>Size MB</fieldName>
<mandatory>true</mandatory>
<dataType>Number</dataType>
<note>The size in megabyte of the artifact</note>
</metadatafield>
<metadatafield>
<fieldName>UsageMode</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<note>How the method is expected to be accessed </note>
<vocabulary>
<vocabularyField>Download</vocabularyField>
<vocabularyField>as-a-Service by SoBigData Infrastructure
</vocabularyField>
<vocabularyField>as-a-Service by third party infrastructure
</vocabularyField>
</vocabulary>
</metadatafield>
<metadatafield>
<fieldName>Input</fieldName>
<mandatory>false</mandatory>
<dataType>Boolean</dataType>
<note>inputParametersType. See WPS </note>
</metadatafield>
<metadatafield>
<fieldName>output</fieldName>
<mandatory>false</mandatory>
<dataType>Boolean</dataType>
<note>outputType. See WPS </note>
</metadatafield>
<metadatafield>
<fieldName>RelatedPaper</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<note>Insert a complete reference to an associated work.</note>
</metadatafield>
<metadatafield>
<fieldName>Field/Scope of use</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<vocabulary isMultiSelection="true">
<vocabularyField>Any use</vocabularyField>
<vocabularyField>Non-commercial only</vocabularyField>
<vocabularyField>Research only</vocabularyField>
<vocabularyField>Non-commercial research only</vocabularyField>
<vocabularyField>Private use</vocabularyField>
<vocabularyField>Use for developing and providing a service
</vocabularyField>
</vocabulary>
</metadatafield>
<metadatafield>
<fieldName>Field/Scope of use</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<vocabulary isMultiSelection="true">
<vocabularyField>Any use</vocabularyField>
<vocabularyField>Non-commercial only</vocabularyField>
<vocabularyField>Research only</vocabularyField>
<vocabularyField>Non-commercial research only</vocabularyField>
<vocabularyField>Private use</vocabularyField>
<vocabularyField>Use for developing and providing a service
</vocabularyField>
</vocabulary>
</metadatafield>
<metadatafield>
<fieldName>spatial</fieldName> <!--'spatial' is mandatory name of GeoSpatial field -->
<mandatory>true</mandatory>
<dataType>GeoJSON</dataType>
<note>Distribution Area</note>
</metadatafield>
</metadataformat>

View File

@ -0,0 +1,119 @@
package org.gcube.datacatalogue.catalogue.beans.resource;
import org.json.simple.JSONObject;
/**
* A custom field. It also stores index of the category and of the metadata field associated.
* If they are missing, indexes are set to Integer.MAX_VALUE
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class CustomField implements Comparable<CustomField>{
private String key;
private String qualifiedKey;
private String value;
private int indexMetadataField = Integer.MAX_VALUE;
private int indexCategory = Integer.MAX_VALUE;
public CustomField(JSONObject object) {
super();
this.key = (String)object.get("key");
this.qualifiedKey = key;
this.value = (String)object.get("value");
if(key == null || value == null || key.isEmpty())
throw new IllegalArgumentException("A custom field must have a key and a value! Provided object is " + object.toString());
}
/**
* @param key
* @param value
*/
public CustomField(String key, String value) {
super();
this.key = key;
this.qualifiedKey = key;
this.value = value;
}
/**
* @param key
* @param value
* @param indexMetadataField
* @param indexCategory
*/
public CustomField(String key, String value, int indexCategory, int indexMetadataField) {
super();
this.key = key;
this.value = value;
this.indexMetadataField = indexMetadataField;
this.indexCategory = indexCategory;
this.qualifiedKey = key;
}
public int getIndexMetadataField() {
return indexMetadataField;
}
public String getQualifiedKey() {
return qualifiedKey;
}
public void setQualifiedKey(String qualifiedKey) {
this.qualifiedKey = qualifiedKey;
}
public void setIndexMetadataField(int indexMetadataField) {
this.indexMetadataField = indexMetadataField;
}
public int getIndexCategory() {
return indexCategory;
}
public void setIndexCategory(int indexCategory) {
this.indexCategory = indexCategory;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "CustomField [key=" + key + ", qualifiedKey=" + qualifiedKey
+ ", value=" + value + ", indexMetadataField="
+ indexMetadataField + ", indexCategory=" + indexCategory + "]";
}
@Override
public int compareTo(CustomField o) {
if(o.indexCategory < 0)
o.indexCategory = Integer.MAX_VALUE;
if(this.indexCategory < 0)
this.indexCategory = Integer.MAX_VALUE;
if(this.indexCategory == o.indexCategory){
if(this.indexMetadataField == o.indexMetadataField)
return 0;
else
return this.indexMetadataField > o.indexMetadataField ? 1 : -1;
}
else
return this.indexCategory > o.indexCategory ? 1 : -1;
}
}

View File

@ -0,0 +1,31 @@
package org.gcube.datacatalogue.catalogue.utils;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
/**
* Handle caches via Ehcache
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class CachesManager {
private static CacheManager cacheManager;
public static final CachesManager singleton = new CachesManager();
public static final String PROFILES_READERS_CACHE = "profile_readers";
private CachesManager(){
cacheManager = CacheManager.newInstance();
}
public static Cache getCache(String name){
return cacheManager.getCache(name);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
cacheManager.shutdown();
}
}

View File

@ -0,0 +1,976 @@
package org.gcube.datacatalogue.catalogue.utils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.datacatalogue.catalogue.beans.resource.CustomField;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.DataType;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataCategory;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataField;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataFormat;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataGrouping;
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.MetadataTagging;
import org.geojson.GeoJsonObject;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Utils class and methods.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
@SuppressWarnings({"rawtypes","unchecked"})
public class CatalogueUtils {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CatalogueUtils.class);
public static final String HELP_URL_GCUBE_CATALOGUE = "https://wiki.gcube-system.org/gcube/GCube_Data_Catalogue";
public static final String HELP_KEY = "help";
public static final String DATASET_KEY = "id";
public static final String SUCCESS_KEY = "success";
public static final String MESSAGE_ERROR_KEY = "message";
public static final String RESULT_KEY = "result";
public static final String EXTRAS_KEY = "extras";
public static final String TAGS_KEY = "tags";
public static final String GROUPS_KEY = "groups";
public static final String LICENSE_KEY = "license_id";
public static final String AUTHOR_KEY = "author";
public static final String RESOURCES_KEY = "resources";
public static final String AUTHOR_EMAIL_KEY = "author_email";
public static final String METADATATYPE_KEY = "metadatatype";
public static final String OWNER_ORG_KEY = "owner_org";
public static final String TITLE_KEY = "title";
public static final String VERSION_KEY = "version";
public static final String SEPARATOR_MULTIPLE_VALUES_FIELD = ",";
public static final int MAX_TAG_CHARS = 100;
// =======================================================================
// GET/PUT CATALOGUE
// =======================================================================
/**
* Retrieve an instance of the library for the scope
* @param scope if it is null it is evaluated from the session
* @return
* @throws Exception
*/
public static DataCatalogue getCatalogue(){
try{
String context = ScopeProvider.instance.get();
logger.debug("Discovering ckan instance into scope " + context);
return DataCatalogueFactory.getFactory().getUtilsPerScope(context);
}catch(Exception e){
logger.error("Unable to lookup catalogue object here ");
}
return null;
}
/**
* Retrieve an instance of the library for the scope
* @param scope if it is null it is evaluated from the session
* @return
* @throws Exception
*/
public static boolean createGroupAsSysAdmin(String title, String groupName, String description) throws Exception{
return getCatalogue().createGroup(groupName, title, description) != null;
}
// =======================================================================
// METADATA PROFILE STUFF
// =======================================================================
/**
* Returns the names of the metadata profiles in a given context
* @param context
* @return
* @throws Exception
*/
public static List<String> getProfilesNames() throws Exception{
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
List<String> toReturn = new ArrayList<String>();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
if(listProfiles != null && !listProfiles.isEmpty()){
for (MetadataProfile profile : listProfiles) {
toReturn.add(profile.getName());
}
}
return toReturn;
}
/**
* Returns the source xml of the metadata profile (specified via name) in a given context
* @param context
* @return
* @throws Exception
*/
public static String getProfileSource(String profileName) throws Exception{
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
String xmlToReturn = null;
if(listProfiles != null && !listProfiles.isEmpty()){
for (MetadataProfile profile : listProfiles) {
if(profile.getName().equals(profileName)){
xmlToReturn = reader.getMetadataFormatForMetadataProfile(profile).getMetadataSource();
break;
}
}
}
return xmlToReturn;
}
/**
* Returns the metadataform of the metadata profile (specified via name) in a given context
* @param context
* @return
* @throws Exception
*/
public static MetadataFormat getMetadataProfile(String profileName) throws Exception{
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
if(listProfiles != null && !listProfiles.isEmpty()){
for (MetadataProfile profile : listProfiles) {
if(profile.getName().equals(profileName)){
return reader.getMetadataFormatForMetadataProfile(profile);
}
}
}
return null;
}
// =======================================================================
// JSON OBJECT MAPPINGS
// =======================================================================
/**
* Create a string representing an error message on failure
* @param errorMessage
* @return
*/
public static String createJSONOnFailure(String errorMessage){
JSONObject obj = new JSONObject();
obj.put(HELP_KEY, HELP_URL_GCUBE_CATALOGUE);
obj.put(SUCCESS_KEY, false);
obj.put(MESSAGE_ERROR_KEY, errorMessage);
return obj.toJSONString();
}
/**
* JSONObject containing minimum information to be set
* @return
*/
public static JSONObject createJSONObjectMin(boolean success, String errorMessage){
JSONObject obj = new JSONObject();
obj.put(HELP_KEY, HELP_URL_GCUBE_CATALOGUE);
obj.put(SUCCESS_KEY, success);
if(errorMessage != null)
obj.put(MESSAGE_ERROR_KEY, errorMessage);
return obj;
}
// =======================================================================
// DELEGATE OPS TO CKAN
// =======================================================================
/**
* Check resources have at least url/name
* @param json
* @param caller
* @throws Exception
*/
public static void checkResourcesInformation(String json, Caller caller) throws Exception {
JSONParser parser = new JSONParser();
JSONObject dataset = (JSONObject)parser.parse(json);
JSONArray resources = (JSONArray)dataset.get(RESOURCES_KEY);
if(resources == null || resources.isEmpty())
return;
else{
Iterator it = resources.iterator();
while (it.hasNext()) {
JSONObject resource = (JSONObject) it.next();
String name = (String)resource.get("name");
String url = (String)resource.get("url");
if(url == null || name == null || url.isEmpty() || name.isEmpty())
throw new Exception("Resources must have at least a name and an url");
}
}
}
/**
* This method validates the incoming json, in this sense:
* <ul>
* <li> add author
* <li> add author email
* <li> check license (?)
* </ul>
* @param json
* @param caller
* @return
* @throws Exception
*/
public static String checkBaseInformation(String json, Caller caller) throws Exception{
JSONParser parser = new JSONParser();
JSONObject dataset = (JSONObject)parser.parse(json);
JSONObject profile = getUserProfile();
// check license
String licenseId = (String)dataset.get(LICENSE_KEY);
if(licenseId == null || licenseId.isEmpty())
throw new Exception("You must specify a license identifier to be attached to the item. License list can be retrieved invoking license methods");
// set author and author email
JSONObject profileValues = (JSONObject)profile.get(RESULT_KEY);
dataset.put(AUTHOR_KEY, profileValues.get(FULLNAME_IN_PROFILE_KEY));
dataset.put(AUTHOR_EMAIL_KEY, profileValues.get(EMAIL_IN_PROFILE_KEY));
// version
String version = (String)dataset.get(VERSION_KEY);
if(version == null || version.isEmpty()){
version = "1";
dataset.put(VERSION_KEY, version);
}
// owner organization must be specified if the token belongs to a VRE
ScopeBean scopeBean = new ScopeBean(ScopeProvider.instance.get());
String ownerOrgFromScope = scopeBean.name();
boolean isVREToken = scopeBean.is(Type.VRE);
String ownerOrg = (String)dataset.get(OWNER_ORG_KEY);
if(isVREToken){
dataset.put(OWNER_ORG_KEY, ownerOrgFromScope.toLowerCase().replace(" ", "_"));
}else if(ownerOrg == null || ownerOrg.isEmpty())
throw new Exception("You must specify the field owner_org in which the item should be published!");
return dataset.toJSONString();
}
/**
* This method validate the incoming json dataset wrt a metadata profile
* @param json
* @param caller
* @param profiles
* @return
* @throws Exception
*/
public static String validateAgainstProfile(String json, Caller caller, List<String> profiles) throws Exception {
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(json);
JSONArray extrasArrayOriginal = (JSONArray)obj.get(EXTRAS_KEY);
JSONArray groupsArrayOriginal = (JSONArray)obj.get(GROUPS_KEY);
JSONArray tagsArrayOriginal = (JSONArray)obj.get(TAGS_KEY);
if(extrasArrayOriginal == null || extrasArrayOriginal.isEmpty())
throw new Exception("'extras' field is missing in context where metadata profile(s) are defined!");
// get the metadata profile
CustomField metadataTypeCF = null;
List<CustomField> customFields = new ArrayList<CustomField>();
Iterator iterator = extrasArrayOriginal.iterator();
while (iterator.hasNext()) {
JSONObject object = (JSONObject) iterator.next();
CustomField cf = new CustomField(object);
if(cf.getKey().equals(METADATATYPE_KEY))
metadataTypeCF = cf;
else
customFields.add(cf);
}
if(metadataTypeCF == null)
throw new Exception("'" + METADATATYPE_KEY + "' field is missing in context where metadata profile(s) are defined!");
if(groupsArrayOriginal == null)
groupsArrayOriginal = new JSONArray();
if(tagsArrayOriginal == null)
tagsArrayOriginal = new JSONArray();
// fetch the profile by metadatatype TODO EHCache here
MetadataFormat profile = null;
String profileNameMatched = null;
for (String profileName : profiles) {
profile = getMetadataProfile(profileName);
if(profile.getMetadataType().equals(metadataTypeCF.getValue())){
profileNameMatched = profileName;
break;
}
else
profile = null;
}
if(profile == null)
throw new Exception("'" + METADATATYPE_KEY + "' specified as custom field doesn't match any of the profile defined in this context!");
else{
JSONArray extrasArrayUpdated = new JSONArray();
List<MetadataField> metadataFields = profile.getMetadataFields();
if(metadataFields == null || metadataFields.isEmpty())
extrasArrayUpdated.addAll(extrasArrayOriginal);
else{
List<MetadataCategory> categories = profile.getMetadataCategories();
List<String> categoriesIds = new ArrayList<String>();
if(categories == null)
logger.warn("No category defined into profile " + profileNameMatched);
else{
for (MetadataCategory metadataCategory : categories) {
categoriesIds.add(metadataCategory.getId()); // save them later for matching with custom fields
JSONObject catJsonObj = new JSONObject();
JSONObject value = new JSONObject();
value.put("id", metadataCategory.getId());
value.put("title", metadataCategory.getTitle());
value.put("description", metadataCategory.getDescription());
catJsonObj.put("key", metadataCategory.getCategoryQName());
catJsonObj.put("value", value.toString());
extrasArrayUpdated.add(catJsonObj);
}
}
// the list of already validated customFields
List<CustomField> validatedCustomFields = new ArrayList<CustomField>(customFields.size());
// keep track of mandatory (only) fields
Map<String, Integer> fieldsMandatoryLowerBoundMap = new HashMap<String, Integer>();
Map<String, Integer> numberFieldsSameKeyMap = new HashMap<String, Integer>();
// now validate fields
int metadataIndex = 0;
for (MetadataField metadataField : metadataFields) {
int categoryIdIndex = categoriesIds.indexOf(metadataField.getCategoryRef());
logger.trace("Found index for this category (" + metadataField.getCategoryRef() + ")" + categoryIdIndex);
List<CustomField> validCFs = validateAgainstMetadataField(
metadataIndex,
categoryIdIndex,
customFields,
tagsArrayOriginal,
groupsArrayOriginal,
metadataField,
categories,
fieldsMandatoryLowerBoundMap,
numberFieldsSameKeyMap);
validatedCustomFields.addAll(validCFs);
metadataIndex++;
}
// check mandatory fields
Iterator<Entry<String, Integer>> iteratorLowerBounds = fieldsMandatoryLowerBoundMap.entrySet().iterator();
while (iteratorLowerBounds.hasNext()) {
Map.Entry<java.lang.String, java.lang.Integer> entry = (Map.Entry<java.lang.String, java.lang.Integer>) iteratorLowerBounds
.next();
int lowerBound = entry.getValue();
int inserted = numberFieldsSameKeyMap.get(entry.getKey());
logger.trace("Field with key " + entry.getKey() + " has been found " + inserted + " times and its lower bound is " + lowerBound);
if(inserted < lowerBound)
throw new Exception("Field with key '" + entry.getKey() + "' is mandatory, but it's not present among the provided fields or its cardinality is not respected (" + lowerBound + ").");
}
// sort validated custom fields and add to the extrasArrayUpdated json array
Collections.sort(validatedCustomFields);
logger.trace("****** SORTED LIST " + validatedCustomFields);
// add missing fields with no match (append them at the end, since no metadataIndex or categoryIndex was defined for them)
for(CustomField cf : customFields)
validatedCustomFields.add(cf);
for (CustomField customField : validatedCustomFields) {
JSONObject jsonObj = new JSONObject();
jsonObj.put("key", customField.getQualifiedKey());
jsonObj.put("value", customField.getValue());
extrasArrayUpdated.add(jsonObj);
}
// add metadatatype field
JSONObject metadataTypeJSON = new JSONObject();
metadataTypeJSON.put("key", metadataTypeCF.getKey());
metadataTypeJSON.put("value", metadataTypeCF.getValue());
extrasArrayUpdated.add(metadataTypeJSON);
}
obj.put(TAGS_KEY, tagsArrayOriginal);
obj.put(GROUPS_KEY, groupsArrayOriginal);
obj.put(EXTRAS_KEY, extrasArrayUpdated);
}
return obj.toJSONString();
}
/**
* Validate this field and generate a new value (or returns the same if there is nothing to update)
* @param metadataIndex
* @param categoryIndex
* @param customFields
* @param tagsArrayOriginal
* @param groupsArrayOriginal
* @param metadataField
* @param categories
* @param numberFieldsSameKeyMap
* @param fieldsMandatoryLowerBoundMap
* @return
* @throws Exception
*/
private static List<CustomField> validateAgainstMetadataField(
int metadataIndex,
int categoryIndex,
List<CustomField> customFields,
JSONArray tagsArrayOriginal,
JSONArray groupsArrayOriginal,
MetadataField metadataField,
List<MetadataCategory> categories, Map<String, Integer> fieldsMandatoryLowerBoundMap, Map<String, Integer> numberFieldsSameKeyMap) throws Exception {
List<CustomField> toReturn = new ArrayList<CustomField>();
String metadataFieldName = metadataField.getFieldName();
// maintain status about: is this the first time this field is parsed?
int fieldsFoundWithThisKey = 0;
Iterator<CustomField> iterator = customFields.iterator();
while (iterator.hasNext()) {
CustomField cf = (CustomField) iterator.next();
if(cf.getKey().equals(metadataFieldName)){
validate(cf, metadataField, (fieldsFoundWithThisKey == 0));
fieldsFoundWithThisKey ++;
cf.setIndexCategory(categoryIndex);
cf.setIndexMetadataField(metadataIndex);
checkAsGroup(cf, metadataField, groupsArrayOriginal);
checkAsTag(cf, metadataField, tagsArrayOriginal);
toReturn.add(cf);
iterator.remove();
}
}
if(metadataField.getMandatory()){
int lowerBound = 1;
if(fieldsMandatoryLowerBoundMap.containsKey(metadataFieldName))
lowerBound = fieldsMandatoryLowerBoundMap.get(metadataFieldName) + 1;
fieldsMandatoryLowerBoundMap.put(metadataFieldName, lowerBound);
int countPerFields = fieldsFoundWithThisKey;
if(numberFieldsSameKeyMap.containsKey(metadataFieldName))
countPerFields = numberFieldsSameKeyMap.get(metadataFieldName) + countPerFields;
numberFieldsSameKeyMap.put(metadataFieldName, countPerFields);
}
return toReturn;
}
/**
* Check if a tag must be generated
* @param fieldToValidate
* @param metadataField
* @param tagsArrayOriginal
*/
private static void checkAsTag(CustomField fieldToValidate,
MetadataField metadataField, JSONArray tagsArrayOriginal) {
MetadataTagging tagging = metadataField.getTagging();
if(tagging != null && tagging.getCreate()){
String tag = "";
switch(tagging.getTaggingValue()){
case onFieldName:
tag = fieldToValidate.getKey();
break;
case onValue:
tag = fieldToValidate.getValue();
break;
case onFieldName_onValue:
tag = fieldToValidate.getKey() + tagging.getSeparator() + fieldToValidate.getValue();
break;
case onValue_onFieldName:
tag = fieldToValidate.getValue() + tagging.getSeparator() + fieldToValidate.getKey();
break;
default:
return;
}
tag = tag.substring(0, MAX_TAG_CHARS > tag.length() ? tag.length() : MAX_TAG_CHARS);
logger.debug("Tag is " + tag);
JSONObject tagJSON = new JSONObject();
tagJSON.put("name", tag);
tagJSON.put("display_name", tag);
tagsArrayOriginal.add(tagJSON);
}
logger.trace("CURRENT TAGS " + tagsArrayOriginal);
}
/**
* Check if a group must be generated
* @param fieldToValidate
* @param metadataField
* @param groupsArrayOriginal
*/
private static void checkAsGroup(CustomField fieldToValidate,
MetadataField metadataField, JSONArray groupsArrayOriginal) {
logger.debug("Custom field is " + fieldToValidate);
logger.debug("MetadataField field is " + metadataField);
logger.debug("JSONArray field is " + groupsArrayOriginal);
MetadataGrouping grouping = metadataField.getGrouping();
if(grouping != null && grouping.getCreate()){
final List<String> groupNames = new ArrayList<String>();
switch(grouping.getGroupingValue()){
case onFieldName:
groupNames.add(fieldToValidate.getKey());
break;
case onValue:
groupNames.add(fieldToValidate.getValue());
break;
case onFieldName_onValue:
case onValue_onFieldName:
groupNames.add(fieldToValidate.getKey());
groupNames.add(fieldToValidate.getValue());
break;
default:
return;
}
for (String title : groupNames) {
JSONObject group = new JSONObject();
group.put("name", title);
groupsArrayOriginal.add(group);
}
new Thread() {
@Override
public void run() {
for (String title : groupNames)
try {
createGroupAsSysAdmin(title, title, "");
} catch (Exception e) {
logger.error("Failed to create group with title " + title, e);
}
}
}.start();
}
}
/**
* Validate the single field
* @param fieldToValidate
* @param metadataField
* @param isFirst
* @return
* @throws Exception
*/
private static void validate(CustomField fieldToValidate,
MetadataField metadataField, boolean isFirst) throws Exception {
DataType dataType = metadataField.getDataType();
String regex = metadataField.getValidator() != null ? metadataField.getValidator().getRegularExpression() : null;
boolean hasControlledVocabulary = metadataField.getVocabulary() != null;
boolean isMultiselection = hasControlledVocabulary ? metadataField.getVocabulary().isMultiSelection() : false;
String value = fieldToValidate.getValue();
String key = fieldToValidate.getKey();
if((value == null || value.isEmpty()))
if(metadataField.getMandatory() || hasControlledVocabulary)
throw new Exception("Mandatory field with name '" + key + "' doesn't have a value");
else return;
if(!isMultiselection && !isFirst)
throw new Exception("Field with key '" + key + "' cannot be repeated more than once!");
switch(dataType){
case String:
case Text:
if(regex != null && !value.matches(regex))
throw new Exception("Field with key '" + key + "' doesn't match the provided regular expression (" + regex + ")!");
if(hasControlledVocabulary){
List<String> valuesVocabulary = metadataField.getVocabulary().getVocabularyFields();
boolean match = false;
for (String valueVocabulary : valuesVocabulary) {
match = value.equals(valueVocabulary);
if(match)
break;
}
if(!match)
throw new Exception("Field with key '" + key + " doesn't match any of the vocabulary's values!");
}
break;
case Time:
if(!isValidDate(value))
throw new Exception("Field with key '" + key + "' doesn't seem a valid time!");
break;
case Time_Interval:
String[] timeValues = value.split("/");
for (int i = 0; i < timeValues.length; i++) {
String time = timeValues[i];
if(!isValidDate(time))
throw new Exception("Field with key '" + key + "' doesn't seem a valid time interval!");
}
break;
case Times_ListOf:
String[] timeIntervals = value.split(",");
for (int i = 0; i < timeIntervals.length; i++) {
String[] timeIntervalValues = timeIntervals[i].split("/");
for (i = 0; i < timeIntervalValues.length; i++) {
String time = timeIntervalValues[i];
if(!isValidDate(time))
throw new Exception("Field with key '" + key + "' doesn't seem a valid list of times!");
}
}
break;
case Boolean:
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
}else
throw new Exception("Field with key '" + key + "' doesn't seem a valid boolean value!");
break;
case Number:
if(!NumberUtils.isNumber(value))
throw new Exception("Field's value with key '" + key + "' is not a valid number!");
break;
case GeoJSON:
// validate
try{
new ObjectMapper().readValue(fieldToValidate.getValue(), GeoJsonObject.class);
}catch(Exception e){
throw new Exception("GeoJSON field with key '" + key + "' seems not valid!");
}
break;
default:
//???
}
// replace key by prepending the qualified name of the category, if needed
fieldToValidate.setQualifiedKey(metadataField.getCategoryFieldQName());
}
private static final SimpleDateFormat DATE_SIMPLE = new SimpleDateFormat("yyyy-MM-dd");
private static final SimpleDateFormat DATE_HOUR_MINUTES = new SimpleDateFormat("yyyy-MM-dd HH:mm");
/**
* Validate a time date against a formatter
* @param value
* @param formatter
* @return
*/
private static boolean isValidDate(String value) {
try{
DATE_HOUR_MINUTES.parse(value);
return true;
}catch(Exception e){
logger.trace("failed to parse date with hours and minutes, trying the other one");
try{
DATE_SIMPLE.parse(value);
return true;
}catch(Exception e2){
logger.warn("failed to parse date with simple format, returning false");
return false;
}
}
}
/**
* Execute the get
* @param caller
* @param context
* @param method
* @param uriInfo
* @return
* @throws Exception
*/
public static String delegateGet(Caller caller, String context, String method, UriInfo uriInfo){
DataCatalogue catalogue = CatalogueUtils.getCatalogue();
String username = caller.getClient().getId();
if(catalogue == null){
String msg = "There is no catalogue instance in context " + context + " or a temporary problem arised.";
logger.warn(msg);
return CatalogueUtils.createJSONOnFailure(msg);
}else{
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String authorization = catalogue.getApiKeyFromUsername(username);
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl() : catalogue.getCatalogueUrl() + "/";
requestPath += method;
MultivaluedMap<String, String> undecodedParams = uriInfo.getQueryParameters(false);
Iterator<Entry<String, List<String>>> iterator = undecodedParams.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = (Map.Entry<java.lang.String, java.util.List<java.lang.String>>) iterator
.next();
if(entry.getKey().equals("gcube-token"))
continue;
else{
List<String> values = entry.getValue();
for (String value : values) {
requestPath += entry.getKey() + "=" + value + "&";
}
}
}
if(requestPath.endsWith("&"))
requestPath = requestPath.substring(0, requestPath.length() - 1);
HttpGet request = new HttpGet(requestPath);
if(authorization != null)
request.addHeader(Constants.AUTH_CKAN_HEADER, authorization);
logger.trace("******* REQUEST URL IS " + requestPath);
HttpEntity entityRes = client.execute(request).getEntity();
String json = EntityUtils.toString(entityRes);
// substitute "help" field
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(json);
obj.put(HELP_KEY, HELP_URL_GCUBE_CATALOGUE);
return obj.toJSONString();
}catch(Exception e){
logger.error("Failed to serve the request", e);
return CatalogueUtils.createJSONOnFailure("Failed to serve the request: " + e.getMessage());
}
}
}
/**
* Execute the post
* @param caller
* @param context
* @param groupShow
* @param json
* @param uriInfo
* @throws Exception
*/
public static String delegatePost(Caller caller, String context,
String method, String json, UriInfo uriInfo){
String username = caller.getClient().getId();
DataCatalogue catalogue = CatalogueUtils.getCatalogue();
if(catalogue == null){
String msg = "There is no catalogue instance in context " + context + " or a temporary problem arised.";
logger.warn(msg);
return CatalogueUtils.createJSONOnFailure(msg);
}else{
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String authorization = catalogue.getApiKeyFromUsername(username);
String requestPath = catalogue.getCatalogueUrl().endsWith("/") ? catalogue.getCatalogueUrl() : catalogue.getCatalogueUrl() + "/";
requestPath += method + "?";
MultivaluedMap<String, String> undecodedParams = uriInfo.getQueryParameters(false);
Iterator<Entry<String, List<String>>> iterator = undecodedParams.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<java.lang.String, java.util.List<java.lang.String>> entry = (Map.Entry<java.lang.String, java.util.List<java.lang.String>>) iterator
.next();
if(entry.getKey().equals("gcube-token"))
continue;
else{
List<String> values = entry.getValue();
for (String value : values) {
requestPath += entry.getKey() + "=" + value + "&";
}
}
}
if(requestPath.endsWith("&"))
requestPath = requestPath.substring(0, requestPath.length() - 1);
logger.trace("POST request url is going to be " + requestPath);
HttpPost request = new HttpPost(requestPath);
request.addHeader(Constants.AUTH_CKAN_HEADER, authorization);
logger.trace("Sending json to CKAN is " + json);
StringEntity params = new StringEntity(json, ContentType.APPLICATION_JSON);
request.setEntity(params);
HttpEntity entityRes = client.execute(request).getEntity();
String jsonRes = EntityUtils.toString(entityRes);
logger.trace("Result from CKAN is " + jsonRes);
// substitute "help" field
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(jsonRes);
obj.put(HELP_KEY, HELP_URL_GCUBE_CATALOGUE);
return obj.toJSONString();
}catch(Exception e){
logger.error("Failed to serve the request", e);
return CatalogueUtils.createJSONOnFailure("Failed to serve the request: " + e.getMessage());
}
}
}
// =======================================================================
// SOCIAL FACILITIES
// =======================================================================
public static final String EMAIL_IN_PROFILE_KEY = "email";
public static final String FULLNAME_IN_PROFILE_KEY = "fullname";
/**
* Execute the GET http request at this url, and return the result as string
* @return
* @throws Exception
*/
public static JSONObject getUserProfile() throws Exception{
GcoreEndpointReaderSNL socialService = new GcoreEndpointReaderSNL();
String socialServiceUrl = socialService.getServiceBasePath();
String url = socialServiceUrl + "2/users/get-profile";
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
HttpGet getRequest = new HttpGet(url + "?gcube-token=" + SecurityTokenProvider.instance.get());
HttpResponse response = client.execute(getRequest);
JSONParser parser = new JSONParser();
return (JSONObject)parser.parse(EntityUtils.toString(response.getEntity()));
}catch(Exception e){
logger.error("error while performing get method " + e.toString());
throw e;
}
}
}

View File

@ -0,0 +1,79 @@
package org.gcube.datacatalogue.catalogue.utils;
/**
* Constants used within this service.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class Constants {
// methods
public final static String SHOW_METHOD = "show";
public final static String CREATE_METHOD = "create";
public final static String UPDATE_METHOD = "update";
public final static String PURGE_METHOD = "purge";
public final static String DELETE_METHOD = "delete";
public final static String PATCH_METHOD = "patch";
// this service's resources
public final static String USERS = "api/user";
public final static String ORGANIZATIONS = "api/organizations";
public final static String GROUPS = "api/groups";
public final static String ITEMS = "api/items";
public static final String PROFILES = "api/profiles";
public final static String RESOURCES = "api/resources";
public final static String LICENSES = "api/licenses";
public static final String LIST_METHOD = "api/list";
// api rest path CKAN
public final static String CKAN_API_PATH = "/api/3/action/";
// ckan header authorization
public final static String AUTH_CKAN_HEADER = "Authorization";
// ckan Groups subpaths methods (to be appended to the catalogue url)
public final static String GROUP_SHOW = CKAN_API_PATH + "group_show?";
public final static String GROUP_CREATE = CKAN_API_PATH + "group_create";
public final static String GROUP_DELETE = CKAN_API_PATH + "group_delete";
public final static String GROUP_PURGE = CKAN_API_PATH + "group_purge";
public final static String GROUP_UPDATE = CKAN_API_PATH + "group_patch";
public final static String GROUP_PATCH = CKAN_API_PATH + "group_patch";
public final static String GROUP_LIST = CKAN_API_PATH + "group_list";
// ckan Organizations subpaths methods (to be appended to the catalogue url)
public final static String ORGANIZATION_SHOW = CKAN_API_PATH + "organization_show?";
public final static String ORGANIZATION_CREATE = CKAN_API_PATH + "organization_create";
public final static String ORGANIZATION_DELETE = CKAN_API_PATH + "organization_delete";
public final static String ORGANIZATION_PURGE = CKAN_API_PATH + "organization_purge";
public final static String ORGANIZATION_PATCH = CKAN_API_PATH + "organization_patch";
public final static String ORGANIZATION_UPDATE = CKAN_API_PATH + "organization_update";
public final static String ORGANIZATION_LIST = CKAN_API_PATH + "organization_list";
// ckan User subpaths methods (to be appended to the catalogue url)
public final static String USER_SHOW = CKAN_API_PATH + "user_show?";
public final static String USER_CREATE = CKAN_API_PATH + "user_create";
public final static String USER_DELETE = CKAN_API_PATH + "user_delete";
public final static String USER_UPDATE = CKAN_API_PATH + "user_update";
// ckan Dataset/package subpath methods (to be appended to the catalogue url)
public final static String ITEM_SHOW = CKAN_API_PATH + "package_show?";
public final static String ITEM_CREATE = CKAN_API_PATH + "package_create";
public final static String ITEM_DELETE = CKAN_API_PATH + "package_delete";
public final static String ITEM_PURGE = CKAN_API_PATH + "dataset_purge";
public final static String ITEM_PATCH = CKAN_API_PATH + "package_patch";
public final static String ITEM_UPDATE = CKAN_API_PATH + "package_update";
// ckan Resource subpath methods (to be appended to the catalogue url)
public final static String RESOURCE_SHOW = CKAN_API_PATH + "resource_show?";
public final static String RESOURCE_CREATE = CKAN_API_PATH + "resource_create";
public final static String RESOURCE_DELETE = CKAN_API_PATH + "resource_delete";
public final static String RESOURCE_UPDATE = CKAN_API_PATH + "resource_update";
public final static String RESOURCE_PATCH = CKAN_API_PATH + "resource_patch";
// licenses
public final static String LICENSES_SHOW = CKAN_API_PATH + "license_list?";
// ckan capabilities
public static final String PROFILES_NAMES_SHOW = "profile_names/";
public static final String PROFILE_SHOW = "profile/";
}

View File

@ -0,0 +1,68 @@
/**
*
*/
package org.gcube.datacatalogue.catalogue.utils;
import static org.gcube.resources.discovery.icclient.ICFactory.client;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.util.List;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GcoreEndpointReaderSNL {
private static final String resource = "jersey-servlet";
private static final String serviceName = "SocialNetworking";
private static final String serviceClass = "Portal";
private static Logger logger = LoggerFactory.getLogger(GcoreEndpointReaderSNL.class);
private String serviceBasePath;
/**
* Discover the gcore endpoint for the social networking service.
* @param scope the scope
* @throws Exception the exception
*/
public GcoreEndpointReaderSNL() throws Exception {
String currentScope = ScopeProvider.instance.get();
try{
SimpleQuery query = queryFor(GCoreEndpoint.class);
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'",serviceClass));
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'",serviceName));
query.setResult("$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \""+resource+"\"]/text()");
DiscoveryClient<String> client = client();
List<String> endpoints = client.submit(query);
if (endpoints == null || endpoints.isEmpty())
throw new Exception("Cannot retrieve the GCoreEndpoint serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+currentScope);
this.serviceBasePath = endpoints.get(0);
if(serviceBasePath==null)
throw new Exception("Endpoint:"+resource+", is null for serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+currentScope);
serviceBasePath = serviceBasePath.endsWith("/") ? serviceBasePath : serviceBasePath + "/";
}catch(Exception e){
String error = "An error occurred during GCoreEndpoint discovery, serviceName: "+serviceName +", serviceClass: " +serviceClass +", in scope: "+currentScope +".";
logger.error(error, e);
throw new Exception(error);
}
}
/**
* @return the ResourceEntyName
*/
public String getServiceBasePath() {
return serviceBasePath;
}
}

View File

@ -0,0 +1,109 @@
package org.gcube.datacatalogue.catalogue.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Actions to performa after a package has been correctly created on ckan.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class PackageCreatePostActions extends Thread {
private String packageId;
private String context;
private String token;
private String username;
private JSONArray tags;
private String title;
private static final String ITEM_URL = "Item URL";
private static Logger logger = LoggerFactory.getLogger(PackageCreatePostActions.class);
/**
* @param packageId
* @param context
* @param tags
* @param title
*/
public PackageCreatePostActions(
String username,
String packageId,
String context,
String token,
JSONArray tags,
String title) {
super();
this.packageId = packageId;
this.context = context;
this.token = token;
this.username = username;
this.tags = tags;
this.title = title;
}
@Override
public void run() {
try{
ScopeProvider.instance.set(context);
SecurityTokenProvider.instance.set(token);
DataCatalogue utils = CatalogueUtils.getCatalogue();
String apiKey = utils.getApiKeyFromUsername(username);
utils.setSearchableField(packageId, true);
// add also this information as custom field
String datasetUrl = utils.getUnencryptedUrlFromDatasetIdOrName(packageId);
Map<String, List<String>> addField = new HashMap<String, List<String>>();
addField.put(ITEM_URL, Arrays.asList(datasetUrl));
utils.patchProductCustomFields(packageId, apiKey, addField);
JSONObject profile = CatalogueUtils.getUserProfile();
// set author and author email
JSONObject profileValues = (JSONObject)profile.get(CatalogueUtils.RESULT_KEY);
String fullnameUser = (String) profileValues.get(CatalogueUtils.FULLNAME_IN_PROFILE_KEY);
List<String> tagsList = null;
if(tags != null){
tagsList = new ArrayList<String>();
for(int i = 0; i < tags.size(); i++){
JSONObject obj = (JSONObject)(tags.get(i));
tagsList.add((String)(obj.get("display_name")));
}
}
// write notification post
WritePostCatalogueManagerThread threadWritePost =
new WritePostCatalogueManagerThread(
username,
context,
title,
datasetUrl,
false, // send notification to other people
tagsList,
fullnameUser,
token
);
threadWritePost.start();
}catch(Exception e){
logger.error("Error while executing post creation actions", e);
}
}
}

View File

@ -0,0 +1,287 @@
package org.gcube.datacatalogue.catalogue.utils;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Let the Product Catalogue Manager write a post in a VRE and alert there is a new product
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*/
public class WritePostCatalogueManagerThread extends Thread {
private static final String APPLICATION_ID_CATALOGUE_MANAGER = "org.gcube.datacatalogue.ProductCatalogue";
private static final String NOTIFICATION_MESSAGE = "Dear members,<br>The item '$PRODUCT_TITLE' has been just published by $USER_FULLNAME.<br>You can find it here: $PRODUCT_URL <br>";
private static final String SOCIAL_SERVICE_APPLICATION_TOKEN = "/2/tokens/generate-application-token";
private static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST = "/2/posts/write-post-app";
private static final String MEDIATYPE_JSON = "application/json";
private static Logger logger = LoggerFactory.getLogger(WritePostCatalogueManagerThread.class);
private String username;
private String scope;
private String productTitle;
private String productUrl;
private boolean enableNotification;
private List<String> hashtags;
private String userFullName;
private String token;
/**
* @param token
* @param scope
* @param productTitle
* @param productUrl
* @param enableNotification
* @param hashtags
* @param userFullName
*/
public WritePostCatalogueManagerThread(
String username, String scope,
String productTitle, String productUrl, boolean enableNotification,
List<String> hashtags, String userFullName, String token) {
super();
this.username = username;
this.scope = scope;
this.productTitle = productTitle;
this.productUrl = productUrl;
this.enableNotification = enableNotification;
this.hashtags = hashtags;
this.userFullName = userFullName;
this.token = token;
}
@Override
public void run() {
try{
SecurityTokenProvider.instance.set(token);
logger.info("Started request to write application post "
+ "for new product created. Scope is " + scope + " and "
+ "token is " + token.substring(0, 10) + "****************");
// set token and scope
ScopeProvider.instance.set(scope);
SecurityTokenProvider.instance.set(token);
// write
writeProductPost(
productTitle,
productUrl,
userFullName,
hashtags,
enableNotification
);
}catch(Exception e){
logger.error("Failed to write the post because of the following error ", e);
}finally{
SecurityTokenProvider.instance.reset();
ScopeProvider.instance.reset();
}
}
/**
* Send notification to vre members about the created product by writing a post.
* @param productName the title of the product
* @param productUrl the url of the product
* @param hashtags a list of product's hashtags
* @throws Exception
*/
private static void writeProductPost(String productName, String productUrl, String userFullname, List<String> hashtags, boolean enablePostNotification) throws Exception{
// discover service endpoint for the social networking library
String currentScope = ScopeProvider.instance.get();
String tokenUser = SecurityTokenProvider.instance.get();
logger.info("Current scope for writeProductPost is " + currentScope + " and token is " + tokenUser.substring(0, 10) + "***************");
GcoreEndpointReaderSNL socialService = new GcoreEndpointReaderSNL();
String basePath = socialService.getServiceBasePath();
if(basePath == null){
logger.error("Unable to write a post because there is no social networking service available");
}else{
// check base path form
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
try(CloseableHttpClient client = HttpClientBuilder.create().build();){
String pathTokenApp = basePath + SOCIAL_SERVICE_APPLICATION_TOKEN + "?gcube-token=" + tokenUser;
String tokenApp = requireAppToken(client, pathTokenApp);
if(tokenApp != null){
String pathWritePost = basePath + SOCIAL_SERVICE_WRITE_APPLICATION_POST + "?gcube-token=" + tokenApp;
writePost(client, pathWritePost, productName, productUrl, userFullname, hashtags, enablePostNotification);
}
}catch(Exception e){
logger.error("Failed to create a post", e);
}
}
}
/**
* Require the application token
* @param tokenUser
* @param basePath
* @param client
* @return
*/
private static String requireAppToken(CloseableHttpClient client, String path){
String token = null;
try{
HttpResponse response = performRequest(client, path, "{\"app_id\":\"" + APPLICATION_ID_CATALOGUE_MANAGER + "\"}");
int statusTokenGenerate = response.getStatusLine().getStatusCode();
if(statusTokenGenerate == HttpURLConnection.HTTP_CREATED){
// extract token
JSONObject obj = getJSONObject(response);
if(((Boolean) obj.get("success")))
token = (String)obj.get("result");
else
return null;
}else if(statusTokenGenerate == HttpURLConnection.HTTP_MOVED_TEMP
|| statusTokenGenerate == HttpURLConnection.HTTP_MOVED_PERM
|| statusTokenGenerate == HttpURLConnection.HTTP_SEE_OTHER){
// re-execute
Header[] locations = response.getHeaders("Location");
Header lastLocation = locations[locations.length - 1];
String realLocation = lastLocation.getValue();
logger.debug("New location is " + realLocation);
token = requireAppToken(client, realLocation);
}else
return null;
}catch(Exception e){
logger.error("Failed to retrieve application token", e);
}
logger.info("Returning app token " + (token != null ? token.substring(0, 10) + "*************************" : null));
return token;
}
/**
* Write post request
* @param client
* @param applicationToken
* @param productName
* @param productUrl
* @param userFullname
* @param hashtags
*/
private static void writePost(CloseableHttpClient client, String path, String productName, String productUrl, String userFullname, List<String> hashtags,
boolean enablePostNotification) {
try{
// replace
String message = NOTIFICATION_MESSAGE.replace("$PRODUCT_TITLE", productName).replace("$PRODUCT_URL", productUrl).replace("$USER_FULLNAME", userFullname);
if(hashtags != null && !hashtags.isEmpty())
for (String hashtag : hashtags) {
String modifiedHashtag = hashtag.replaceAll(" ", "_").replace("_+", "_");
if(modifiedHashtag.endsWith("_"))
modifiedHashtag = modifiedHashtag.substring(0, modifiedHashtag.length() - 1);
message += " #" + modifiedHashtag; // ckan accepts tag with empty spaces, we don't
}
logger.info("The post that is going to be written is -> " + message);
HttpResponse response = performRequest(client, path, "{\"text\":\"" + message + "\", \"enable_notification\" : "+ enablePostNotification+ "}");
int statusWritePost = response.getStatusLine().getStatusCode();
if(statusWritePost == HttpURLConnection.HTTP_CREATED){
// extract token
JSONObject obj = getJSONObject(response);
if(((Boolean) obj.get("success")))
logger.info("Post written");
else
logger.info("Failed to write the post " + obj.get("message"));
}else if(statusWritePost == HttpURLConnection.HTTP_MOVED_TEMP
|| statusWritePost == HttpURLConnection.HTTP_MOVED_PERM
|| statusWritePost == HttpURLConnection.HTTP_SEE_OTHER){
// re-execute
Header[] locations = response.getHeaders("Location");
Header lastLocation = locations[locations.length - 1];
String realLocation = lastLocation.getValue();
logger.debug("New location is " + realLocation);
writePost(client, realLocation, productName, productUrl, userFullname, hashtags, enablePostNotification);
}else
throw new RuntimeException("Failed to write the post");
}catch(Exception e){
logger.error("Failed to retrieve application token", e);
}
}
/**
* Convert the json response to a map
* @param response
* @return
*/
private static JSONObject getJSONObject(HttpResponse response){
JSONObject toReturn = null;
HttpEntity entity = response.getEntity();
if (entity != null) {
try {
String jsonString = EntityUtils.toString(response.getEntity());
JSONParser parser = new JSONParser();
toReturn = (JSONObject)parser.parse(jsonString);
}catch(Exception e){
logger.error("Failed to read json object", e);
}
}
logger.debug("Returning " + toReturn.toJSONString());
return toReturn;
}
/**
* Perform an http request post request with json entity
* @throws IOException
* @throws ClientProtocolException
*/
private static HttpResponse performRequest(CloseableHttpClient client, String path, String entity) throws ClientProtocolException, IOException{
HttpPost request = new HttpPost(path);
StringEntity stringEntity = new StringEntity(entity);
stringEntity.setContentType(MEDIATYPE_JSON);
request.setEntity(stringEntity);
return client.execute(request);
}
}

View File

@ -0,0 +1,112 @@
package org.gcube.datacatalogue.catalogue.ws;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
@Path(Constants.GROUPS)
public class Group {
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.GROUP_SHOW, uriInfo);
}
@GET
@Path(Constants.LIST_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String organizationList(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.GROUP_LIST, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.GROUP_CREATE, json, uriInfo);
}
@DELETE
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.GROUP_DELETE, json, uriInfo);
}
@DELETE
@Path(Constants.PURGE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_purge
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.GROUP_PURGE, json, uriInfo);
}
@POST
@Path(Constants.UPDATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.GROUP_UPDATE, json, uriInfo);
}
@POST
@Path(Constants.PATCH_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.GROUP_PATCH, json, uriInfo);
}
}

View File

@ -0,0 +1,153 @@
package org.gcube.datacatalogue.catalogue.ws;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.gcube.datacatalogue.catalogue.utils.PackageCreatePostActions;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.slf4j.LoggerFactory;
@Path(Constants.ITEMS)
public class Item {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(Item.class);
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.ITEM_SHOW, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_create
Caller caller = AuthorizationProvider.instance.get();
String username = caller.getClient().getId();
String context = ScopeProvider.instance.get();
try{
// check base information (and set them if needed)
json = CatalogueUtils.checkBaseInformation(json, caller);
// check resources information (name and url must be there)
CatalogueUtils.checkResourcesInformation(json, caller);
// Check if there are profiles here
List<String> profiles = CatalogueUtils.getProfilesNames();
if(profiles != null && !profiles.isEmpty())
json = CatalogueUtils.validateAgainstProfile(json, caller, profiles);
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(CatalogueUtils.delegatePost(caller, context, Constants.ITEM_CREATE, json, uriInfo));
// after creation, if it was ok ...
if((boolean)obj.get(CatalogueUtils.SUCCESS_KEY))
new PackageCreatePostActions(
username,
(String)(((JSONObject)obj.get(CatalogueUtils.RESULT_KEY)).get(CatalogueUtils.DATASET_KEY)),
context,
SecurityTokenProvider.instance.get(),
(JSONArray)((JSONObject)obj.get(CatalogueUtils.RESULT_KEY)).get(CatalogueUtils.TAGS_KEY),
(String)(((JSONObject)obj.get(CatalogueUtils.RESULT_KEY)).get(CatalogueUtils.TITLE_KEY))
).start();
return obj.toJSONString();
}catch(Exception e){
logger.error("Something went wrong... ", e);
return CatalogueUtils.createJSONOnFailure(e.toString());
}
}
@POST
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_DELETE, json, uriInfo);
}
@POST
@Path(Constants.PURGE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.dataset_purge
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_PURGE, json, uriInfo);
}
// @POST
// @Path(Constants.UPDATE_METHOD)
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// public String update(String json){
//
//
// // 1) Check if there are profiles here
// // 2) If there are profiles: match the record against them
// // 3) Else submit it
//
// // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_update
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_UPDATE, json);
//
// }
// @POST
// @Path(Constants.PATCH_METHOD)
// @Consumes(MediaType.APPLICATION_JSON)
// @Produces(MediaType.APPLICATION_JSON)
// public String patch(String json){
//
//
// // 1) Check if there are profiles here
// // 2) If there are profiles: match the record against them
// // 3) Else submit it
//
// // see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_patch
// Caller caller = AuthorizationProvider.instance.get();
// String context = ScopeProvider.instance.get();
// return CatalogueUtils.delegatePost(caller, context, Constants.ITEM_PATCH, json);
//
// }
}

View File

@ -0,0 +1,77 @@
package org.gcube.datacatalogue.catalogue.ws;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.slf4j.LoggerFactory;
@Path(Constants.PROFILES)
public class ItemProfile {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ItemProfile.class);
public final static String PROFILES_GENERIC_TYPE = "DataCatalogueMetadata";
public final static int PRETTY_PRINT_INDENT_FACTOR = 4;
@SuppressWarnings("unchecked")
@GET
@Path(Constants.PROFILES_NAMES_SHOW)
@Produces(MediaType.APPLICATION_JSON)
public String showNames(){
String context = ScopeProvider.instance.get();
logger.debug("Incoming request for context " + context);
// get the names as list
JSONObject json = CatalogueUtils.createJSONObjectMin(true, null);
try{
List<String> names = CatalogueUtils.getProfilesNames();
JSONArray array = new JSONArray();
for (String elem : names) {
try{
array.add(elem);
}catch(Exception e){
}
}
json.put(CatalogueUtils.RESULT_KEY, array);
}catch(Exception e){
json = CatalogueUtils.createJSONObjectMin(false, e.getMessage());
}
return json.toJSONString();
}
@GET
@Path(Constants.PROFILE_SHOW)
@Produces({MediaType.APPLICATION_XML, /*MediaType.APPLICATION_JSON*/})
public String showSource(
//@DefaultValue(MediaType.APPLICATION_XML) @HeaderParam("Accept") String accept,
@QueryParam("profile-name") String profileName) throws Exception{
String context = ScopeProvider.instance.get();
logger.debug("Incoming request for context/name " + context+ "/" + profileName);
return CatalogueUtils.getProfileSource(profileName);
// TODO Check how this mapping xml-> json works
/*if(accept.equals(MediaType.APPLICATION_JSON)){
org.json.JSONObject xmlJSONObj = XML.toJSONObject(content);
return xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
}*/
}
}

View File

@ -0,0 +1,31 @@
package org.gcube.datacatalogue.catalogue.ws;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
@Path(Constants.LICENSES)
public class License {
@GET
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.license_list
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.LICENSES_SHOW, uriInfo);
}
}

View File

@ -0,0 +1,112 @@
package org.gcube.datacatalogue.catalogue.ws;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
@Path(Constants.ORGANIZATIONS)
public class Organization {
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.ORGANIZATION_SHOW, uriInfo);
}
@GET
@Path(Constants.LIST_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String organizationList(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.ORGANIZATION_LIST, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ORGANIZATION_CREATE, json, uriInfo);
}
@POST
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ORGANIZATION_DELETE, json, uriInfo);
}
@POST
@Path(Constants.PURGE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String purge(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ORGANIZATION_PURGE, json, uriInfo);
}
@POST
@Path(Constants.UPDATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ORGANIZATION_UPDATE, json, uriInfo);
}
@POST
@Path(Constants.PATCH_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.ORGANIZATION_PATCH, json, uriInfo);
}
}

View File

@ -0,0 +1,120 @@
package org.gcube.datacatalogue.catalogue.ws;
import java.util.List;
import java.util.Map;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
import org.glassfish.jersey.media.multipart.BodyPart;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
@Path(Constants.RESOURCES)
public class Resource {
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.APPLICATION_JSON)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.resource_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.RESOURCE_SHOW, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.RESOURCE_CREATE, json, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public String create(
FormDataMultiPart multiPart, @Context UriInfo uriInfo
){
// see also multipart https://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
List<BodyPart> bodyParts = multiPart.getBodyParts();
for (BodyPart bodyPart : bodyParts) {
System.out.println("Body name is " + bodyPart.getContentDisposition().getFileName());
}
Map<String, List<FormDataBodyPart>> fields = multiPart.getFields();
System.out.println(fields);
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create
// see also multipart https://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
/*Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.RESOURCE_CREATE, json, uriInfo);*/
return "{\"test\": \"ok\"}";
}
@DELETE
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.RESOURCE_DELETE, json, uriInfo);
}
@POST
@Path(Constants.UPDATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.RESOURCE_UPDATE, json, uriInfo);
}
@POST
@Path(Constants.PATCH_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String patch(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_patch
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.RESOURCE_PATCH, json, uriInfo);
}
}

View File

@ -0,0 +1,74 @@
package org.gcube.datacatalogue.catalogue.ws;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.utils.Caller;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.catalogue.utils.Constants;
@Path(Constants.USERS)
public class User {
@GET
@Path(Constants.SHOW_METHOD)
@Produces(MediaType.TEXT_PLAIN)
public String show(@Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_show
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegateGet(caller, context, Constants.USER_SHOW, uriInfo);
}
@POST
@Path(Constants.CREATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String create(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_create
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.USER_CREATE, json, uriInfo);
}
@DELETE
@Path(Constants.DELETE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String delete(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_delete
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.USER_DELETE, json, uriInfo);
}
@POST
@Path(Constants.UPDATE_METHOD)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public String update(String json, @Context UriInfo uriInfo){
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_update
Caller caller = AuthorizationProvider.instance.get();
String context = ScopeProvider.instance.get();
return CatalogueUtils.delegatePost(caller, context, Constants.USER_UPDATE, json, uriInfo);
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<cache name="profile_readers" maxEntriesLocalHeap="100" eternal="false"
timeToIdleSeconds="3600" timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LFU" transactionalMode="off"
overflowToDisk="false" overflowToOffHeap="false">
<persistence strategy="none" />
</cache>
</ehcache>

View File

@ -0,0 +1,8 @@
<application mode='online'>
<name>Catalogue-WS</name>
<group>Data-Catalogue</group>
<version>1.0.0-SNAPSHOT</version>
<description>Data Catalogue Service</description>
<local-persistence location='target' />
<exclude>/rest/</exclude>
</application>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Catalogue Web Service</display-name>
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.gcube.datacatalogue.catalogue.ws</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -0,0 +1,5 @@
<html>
<body>
<h2>gCube Catalogue WS is up and running!</h2>
</body>
</html>

View File

@ -0,0 +1,143 @@
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.datacatalogue.catalogue.beans.resource.CustomField;
import org.gcube.datacatalogue.catalogue.utils.CachesManager;
import org.gcube.datacatalogue.catalogue.utils.CatalogueUtils;
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JavaTests {
//@Test
public void testGetMetadataNames() throws Exception {
ScopeProvider.instance.set("/gcube/devNext/NextNext");
DataCalogueMetadataFormatReader reader = new DataCalogueMetadataFormatReader();
List<MetadataProfile> listProfiles = reader.getListOfMetadataProfiles();
System.out.println("Result is " + listProfiles);
}
//@Test
public void testJSONValueCategory(){
JSONObject catJsonObj = new JSONObject();
JSONObject value = new JSONObject();
value.put("id", "aaaaa");
value.put("title", "this is the title");
value.put("description", "this is the description");
catJsonObj.put("qualified_name", value); // TODO check
System.out.println(catJsonObj);
}
//@Test
public void testDate(){
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String value = "2005-03-01";
try{
Date d = formatter2.parse(value);
System.out.println("F1 is " + d.toLocaleString());
if(d == null)
d = formatter2.parse(value);
}catch(Exception e){
System.err.println("failed to parse date " + e);
}
}
//@Test
public void testSorting(){
List<CustomField> toSort = new ArrayList<CustomField>();
toSort.add(new CustomField("C", "value1", Integer.MAX_VALUE, 7));
toSort.add(new CustomField("E", "value1", Integer.MAX_VALUE, 6));
toSort.add(new CustomField("X", "value1", Integer.MAX_VALUE, 3));
toSort.add(new CustomField("Z", "value1", 0, 3));
toSort.add(new CustomField("A", "value2", 1, 2));
toSort.add(new CustomField("D", "value1", 2, 4));
toSort.add(new CustomField("B", "value1", 2, 1));
Collections.sort(toSort);
System.out.println("Sorted list " + toSort);
}
//@Test
public void testJsonArray(){
JSONArray tagsArrayOriginal = new JSONArray();
String tag = "";
tagsArrayOriginal.add(tag);
System.out.println(tagsArrayOriginal);
}
//@Test
public void testEHCache() throws Exception{
ScopeProvider.instance.set("/gcube/devNext/NextNext");
Cache profilesCache = CachesManager.getCache(CachesManager.PROFILES_READERS_CACHE);
String context = ScopeProvider.instance.get();
List<String> toReturn = new ArrayList<String>();
DataCalogueMetadataFormatReader reader;
if(profilesCache.isKeyInCache(context))
reader = (DataCalogueMetadataFormatReader) profilesCache.get(context).getObjectValue();
else{
reader = new DataCalogueMetadataFormatReader();
profilesCache.put(new Element(context, reader));
}
Thread.sleep(1000 * 60);
}
//@Test
public void testJSONObj() throws Exception{
JSONObject obj = new JSONObject();
obj.put("c", "d");
modifyJSON(obj);
System.out.println(obj);
}
private static void modifyJSON(JSONObject obj){
obj.put("a", "b");
}
//@Test
public void testJSONParser() throws ParseException{
String jsonString = "{\"help\": \"https://ckan-d-d4s.d4science.org/api/3/action/help_show?name=package_create\", \"success\": true, \"result\": {\"license_title\": \"License Not Specified\", \"maintainer\": \"Giancarlo Panichi\", \"relationships_as_object\": [], \"private\": false, \"maintainer_email\": \"giancarlo.panichi@isti.cnr.it\", \"num_tags\": 2, \"id\": \"e39990ac-c644-49f4-a8a2-6774c2e69b59\", \"metadata_created\": \"2017-03-31T12:07:23.836973\", \"metadata_modified\": \"2017-03-31T12:07:23.836983\", \"author\": \"Costantino Perciante\", \"author_email\": \"costantino.perciante@isti.cnr.it\", \"state\": \"active\", \"version\": \"1\", \"creator_user_id\": \"ab8189ff-6b07-4963-b36a-c83d53d7e49b\", \"type\": \"dataset\", \"resources\": [{\"mimetype\": null, \"cache_url\": null, \"hash\": \"\", \"description\": \"\", \"name\": \"resource A\", \"format\": \"\", \"url\": \"http://www.test.it\", \"datastore_active\": false, \"cache_last_updated\": null, \"package_id\": \"e39990ac-c644-49f4-a8a2-6774c2e69b59\", \"created\": \"2017-03-31T14:07:23.943698\", \"state\": \"active\", \"mimetype_inner\": null, \"last_modified\": null, \"position\": 0, \"revision_id\": \"687a9a8e-4450-4904-9f54-603e6dc71d54\", \"url_type\": null, \"id\": \"fb0c2e90-bc5e-4028-ae61-8cc799814c4d\", \"resource_type\": null, \"size\": null}], \"num_resources\": 1, \"tags\": [{\"vocabulary_id\": null, \"state\": \"active\", \"display_name\": \"Artifact Name-catalogue-ws\", \"id\": \"5b287a15-ff52-429a-8f24-d5f9a4cc0f42\", \"name\": \"Artifact Name-catalogue-ws\"}, {\"vocabulary_id\": null, \"state\": \"active\", \"display_name\": \"Java\", \"id\": \"ad62fb1a-02f7-4ee5-96f8-50c919866552\", \"name\": \"Java\"}], \"groups\": [], \"license_id\": \"notspecified\", \"relationships_as_subject\": [], \"organization\": {\"description\": \"VRE nextnext\", \"created\": \"2016-06-21T17:29:47.479879\", \"title\": \"NextNext\", \"name\": \"nextnext\", \"is_organization\": true, \"state\": \"active\", \"image_url\": \"\", \"revision_id\": \"12264679-247a-4c40-945d-38607c006d2a\", \"type\": \"organization\", \"id\": \"131d8f52-2566-458b-8bc4-04fb57f2580d\", \"approval_status\": \"approved\"}, \"name\": \"test-web-service-3\", \"isopen\": false, \"url\": null, \"notes\": null, \"owner_org\": \"131d8f52-2566-458b-8bc4-04fb57f2580d\", \"extras\": [{\"key\": \"Field/Scope of use\", \"value\": \"Any use\"}, {\"key\": \"UsageMode\", \"value\": \"Download\"}, {\"key\": \"categoryref:artifact_information:Artifact Name\", \"value\": \"catalogue-ws\"}, {\"key\": \"categoryref:artifact_information:Maven Location\", \"value\": \"http://maven.research-infrastructures.eu/nexus/index.html\"}, {\"key\": \"categoryref:artifact_information:Programming language\", \"value\": \"Java\"}, {\"key\": \"categoryref:developer_information:Identifier\", \"value\": \"costantino.perciante\"}, {\"key\": \"categoryref:extra_information:First Release\", \"value\": \"2017-04-03\"}, {\"key\": \"categoryref:extra_information:Size MB\", \"value\": \"2\"}, {\"key\": \"metadatacategory:artifact_information\", \"value\": \"{\\\"id\\\":\\\"artifact_information\\\",\\\"title\\\":\\\"Artifact Information\\\",\\\"description\\\":\\\"Artifact's main information \\\\t\\\\t\\\"}\"}, {\"key\": \"metadatacategory:developer_information\", \"value\": \"{\\\"id\\\":\\\"developer_information\\\",\\\"title\\\":\\\"Developer Information\\\",\\\"description\\\":\\\"This section is about developer(s) information \\\\t\\\\t\\\"}\"}, {\"key\": \"metadatacategory:extra_information\", \"value\": \"{\\\"id\\\":\\\"extra_information\\\",\\\"title\\\":\\\"Extras\\\",\\\"description\\\":\\\"Other information about the artifact \\\\t\\\\t\\\"}\"}, {\"key\": \"metadatatype\", \"value\": \"software_type\"}, {\"key\": \"spatial\", \"value\": \"{\\\"type\\\": \\\"Point\\\",\\\"coordinates\\\": [-3.145, 53.078]}\"}], \"title\": \"title test from web service-3\", \"revision_id\": \"687a9a8e-4450-4904-9f54-603e6dc71d54\"}}";
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse(jsonString);
JSONArray tags = (JSONArray)((JSONObject)obj.get(CatalogueUtils.RESULT_KEY)).get(CatalogueUtils.TAGS_KEY);
System.out.println("Tags are " + tags);
}
}

View File

@ -0,0 +1,124 @@
import java.io.File;
import java.io.IOException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.http.ParseException;
import org.gcube.datacatalogue.catalogue.ws.ItemProfile;
import org.gcube.datacatalogue.catalogue.ws.Resource;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.json.simple.JSONObject;
import org.slf4j.LoggerFactory;
public class TestJersey extends JerseyTest {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(TestJersey.class);
//@Override
protected Application configure() {
logger.info("Configuring service...");
forceSet(TestProperties.CONTAINER_PORT, "0");
final ResourceConfig resourceConfig = new ResourceConfig(Resource.class, ItemProfile.class);
resourceConfig.register(MultiPartFeature.class);
return resourceConfig;
}
//@Override
public void configureClient(ClientConfig config) {
logger.info("Configuring client...");
config.register(MultiPartFeature.class);
}
//@Test
@SuppressWarnings("unchecked")
public void test() throws ParseException, IOException {
JSONObject obj = new JSONObject();
obj.put("test", "value");
final JSONObject createResource = target("api/resources/create/")
.request()
.accept(MediaType.APPLICATION_JSON)
.post(Entity.json(obj), JSONObject.class);
logger.info(createResource.toJSONString());
}
//@Test
public void testFile() throws ParseException, IOException {
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("uploadFile",
new File("/Users/costantinoperciante/Desktop/rilascio_tess.doc"));
final MultiPart multipart = new FormDataMultiPart()
.field("foo", "bar")
.bodyPart(fileDataBodyPart);
final Response createResource =
target("api/resources/create/")
.request()
.post(Entity.entity(multipart, multipart.getMediaType()));
logger.info(createResource.toString());
//
multipart.close();
}
//@Test
public void testProfilesNames() throws ParseException, IOException {
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("uploadFile",
new File("/Users/costantinoperciante/Desktop/rilascio_tess.doc"));
final MultiPart multipart = new FormDataMultiPart()
.field("foo", "bar")
.bodyPart(fileDataBodyPart);
final Response createResource =
target("api/resources/create/")
.request()
.post(Entity.entity(multipart, multipart.getMediaType()));
logger.info(createResource.toString());
//
multipart.close();
}
//@Test
public void testProfileNames() throws ParseException, IOException {
final String profiles =
target("api/profiles/profile_names/")
.queryParam("context", "/gcube/devNext/NextNext")
.request()
.get(String.class);
logger.info("Response is " + profiles);
}
//@Test
public void testProfileByName() throws ParseException, IOException {
final String profiles =
target("api/profiles/profile/")
.queryParam("context", "/gcube/devNext/NextNext")
.queryParam("name", "SoBigData.eu: Dataset Metadata NextNext")
.request(MediaType.APPLICATION_JSON)
.get(String.class);
logger.info("Response is " + profiles);
}
}