Service Refatored and Renamed to gCcat
Refs #12810: Refactor catalogue-ws Task-Url: https://support.d4science.org/issues/12810 git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-publishing/gcat@174532 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
commit
5743fc03ed
|
@ -0,0 +1,36 @@
|
||||||
|
<?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 excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<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 excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||||
|
<attributes>
|
||||||
|
<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"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>science-catalogue</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>
|
|
@ -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>
|
|
@ -0,0 +1,6 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
encoding//src/main/java=UTF-8
|
||||||
|
encoding//src/main/resources=UTF-8
|
||||||
|
encoding//src/test/java=UTF-8
|
||||||
|
encoding//src/test/resources=UTF-8
|
||||||
|
encoding/<project>=UTF-8
|
|
@ -0,0 +1,8 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
|
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.8
|
|
@ -0,0 +1,4 @@
|
||||||
|
activeProfiles=
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
resolveWorkspaceProjects=true
|
||||||
|
version=1
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?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"/>
|
||||||
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
|
||||||
|
<dependent-module archiveName="ckan-util-library-2.5.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/ckan-util-library/ckan-util-library">
|
||||||
|
<dependency-type>uses</dependency-type>
|
||||||
|
</dependent-module>
|
||||||
|
<property name="context-root" value="catalogue-ws"/>
|
||||||
|
<property name="java-output-path" value="/catalogue-ws/target/classes"/>
|
||||||
|
</wb-module>
|
||||||
|
</project-modules>
|
|
@ -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>
|
|
@ -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="jst.jaxrs" version="2.0"/>
|
||||||
|
<installed facet="java" version="1.8"/>
|
||||||
|
</faceted-project>
|
|
@ -0,0 +1 @@
|
||||||
|
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
|
@ -0,0 +1 @@
|
||||||
|
Window
|
|
@ -0,0 +1,2 @@
|
||||||
|
disabled=06target
|
||||||
|
eclipse.preferences.version=1
|
|
@ -0,0 +1,4 @@
|
||||||
|
gCube System - License
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
${gcube.license}
|
|
@ -0,0 +1,63 @@
|
||||||
|
The gCube System - ${name}
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
${description}
|
||||||
|
|
||||||
|
|
||||||
|
${gcube.description}
|
||||||
|
|
||||||
|
${gcube.funding}
|
||||||
|
|
||||||
|
|
||||||
|
Version
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
${version} (${buildDate})
|
||||||
|
|
||||||
|
Please see the file named "changelog.xml" in this directory for the release notes.
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Maintainers
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Download information
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Source code is available from SVN:
|
||||||
|
${scm.url}
|
||||||
|
|
||||||
|
Binaries can be downloaded from the gCube website:
|
||||||
|
${gcube.website}
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Installation documentation is available on-line in the gCube Wiki:
|
||||||
|
${gcube.wikiRoot}
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Documentation is available on-line in the gCube Wiki:
|
||||||
|
${gcube.wikiRoot}
|
||||||
|
|
||||||
|
Support
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Bugs and support requests can be reported in the gCube issue tracking tool:
|
||||||
|
${gcube.issueTracking}
|
||||||
|
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<ReleaseNotes>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-4-0" date="${buildDate}">
|
||||||
|
<Change></Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-3-0" date="2018-10-10">
|
||||||
|
<Change>Complete refactoring of code</Change>
|
||||||
|
<Change>Item Port type is now RESTful (old methods are still allowed)</Change>
|
||||||
|
<Change>Added update support for Item #11516</Change>
|
||||||
|
<Change>Changed caching mechanism from ehcache API to JSR-107. Ehcache is still used as runtime library.</Change>
|
||||||
|
<Change>Solved random NullPointer Exception on catalogue-ws related to old caching mechanism #11466</Change>
|
||||||
|
<Change>Fixed normalization of the organization name #12506</Change>
|
||||||
|
<Change>Added the possibility to deny social post on catalogue-ws #12514</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-1-1"
|
||||||
|
date="2018-01-11">
|
||||||
|
<Change>Item purge method enhanced</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-1-0"
|
||||||
|
date="2017-06-20">
|
||||||
|
<Change>Minor fixes while checking user's permissions</Change>
|
||||||
|
<Change>Namespaces are no longer transparently managed</Change>
|
||||||
|
<Change>Fixed 'default' value for metadata</Change>
|
||||||
|
<Change>Improved exception handling</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-0-0"
|
||||||
|
date="2017-05-01">
|
||||||
|
<Change>First Release</Change>
|
||||||
|
</Changeset>
|
||||||
|
</ReleaseNotes>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<assembly
|
||||||
|
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<baseDirectory>/</baseDirectory>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${distroDirectory}</directory>
|
||||||
|
<outputDirectory>${file.separator}</outputDirectory>
|
||||||
|
<useDefaultExcludes>true</useDefaultExcludes>
|
||||||
|
<includes>
|
||||||
|
<include>README</include>
|
||||||
|
<include>LICENSE</include>
|
||||||
|
<include>changelog.xml</include>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>755</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>target${file.separator}${build.finalName}.${project.packaging}</source>
|
||||||
|
<outputDirectory>${file.separator}${artifactId}</outputDirectory>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<application mode='online'>
|
||||||
|
<name>${artifactId}</name>
|
||||||
|
<group>${serviceClass}</group>
|
||||||
|
<version>${version}</version>
|
||||||
|
<description>${description}</description>
|
||||||
|
<local-persistence location='target' />
|
||||||
|
</application>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<Resource>
|
||||||
|
<ID />
|
||||||
|
<Type>Service</Type>
|
||||||
|
<Profile>
|
||||||
|
<Description>${description}</Description>
|
||||||
|
<Class>${serviceClass}</Class>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Packages>
|
||||||
|
<Main>
|
||||||
|
<Description>${description}</Description>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>${version}</Version>
|
||||||
|
<MavenCoordinates>
|
||||||
|
<groupId>${groupId}</groupId>
|
||||||
|
<artifactId>${artifactId}</artifactId>
|
||||||
|
<version>${version}</version>
|
||||||
|
</MavenCoordinates>
|
||||||
|
<Files>
|
||||||
|
<File>${build.finalName}.${project.packaging}</File>
|
||||||
|
</Files>
|
||||||
|
</Main>
|
||||||
|
</Packages>
|
||||||
|
</Profile>
|
||||||
|
</Resource>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<web-app>
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>org.gcube.datacatalogue.sciencecatalogue.ResourceInitializer</servlet-name>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>org.gcube.datacatalogue.sciencecatalogue.ResourceInitializer</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,304 @@
|
||||||
|
<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.data-publishing</groupId>
|
||||||
|
<artifactId>gcat</artifactId>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<name>gCube Catalogue Service</name>
|
||||||
|
<description>
|
||||||
|
This service allows any client to publish on the gCube Catalogue.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.distribution</groupId>
|
||||||
|
<artifactId>gcube-bom</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.distribution</groupId>
|
||||||
|
<artifactId>gcube-smartgears-bom</artifactId>
|
||||||
|
<version>LATEST</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>gxRest</artifactId>
|
||||||
|
<version>1.0.1-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<version.jersey>2.13</version.jersey>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
|
||||||
|
<!-- webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory -->
|
||||||
|
<distroDirectory>${project.basedir}/distro</distroDirectory>
|
||||||
|
<serviceClass>DataCatalogue</serviceClass>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/${project.artifactId}</connection>
|
||||||
|
<developerConnection>scm:https://svn.d4science.research-infrastructures.eu/gcube//trunk/data-catalogue/${project.artifactId}</developerConnection>
|
||||||
|
<url>https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/${project.artifactId}</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- ehCAChe -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.cache</groupId>
|
||||||
|
<artifactId>cache-api</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.ehcache</groupId>
|
||||||
|
<artifactId>ehcache</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- END ehCAChe -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.data-catalogue</groupId>
|
||||||
|
<artifactId>gcubedatacatalogue-metadata-discovery</artifactId>
|
||||||
|
<version>[3.0.0-SNAPSHOT, 4.0.0-SNAPSHOT)</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-log4j12</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.data-catalogue</groupId>
|
||||||
|
<artifactId>ckan-util-library</artifactId>
|
||||||
|
<version>[2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.containers</groupId>
|
||||||
|
<artifactId>jersey-container-servlet</artifactId>
|
||||||
|
<version>${version.jersey}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- Required with jersey 2.27
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish.jersey.inject</groupId>
|
||||||
|
<artifactId>jersey-hk2</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.gcube.common</groupId>
|
||||||
|
<artifactId>storagehub-client-library</artifactId>
|
||||||
|
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Home Library dependencies MUST be removed when the storagehub add missing features -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>home-library-jcr</artifactId>
|
||||||
|
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.common</groupId>
|
||||||
|
<artifactId>home-library</artifactId>
|
||||||
|
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- END of Home Library dependencies -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.servlet</groupId>
|
||||||
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Libraries explicitly forced to provided -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.resources</groupId>
|
||||||
|
<artifactId>common-gcore-resources</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-gcore-stubs</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-scope</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-scope-maps</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.resources.discovery</groupId>
|
||||||
|
<artifactId>discovery-client</artifactId>
|
||||||
|
<scope>provided</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>common-authorization</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.resources.discovery</groupId>
|
||||||
|
<artifactId>ic-client</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- END Libraries explicitly forced to provided -->
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-smartgears</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.grundid.opendatalab</groupId>
|
||||||
|
<artifactId>geojson-jackson</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-lang</groupId>
|
||||||
|
<artifactId>commons-lang</artifactId>
|
||||||
|
<version>2.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Used to automatically convert XML to JSON -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20140107</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Test libraries -->
|
||||||
|
<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>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.0.13</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy-profile</id>
|
||||||
|
<goals>
|
||||||
|
<goal>copy-resources</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>process-resources</phase>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>${webappDirectory}</outputDirectory>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>${distroDirectory}</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<warName>${artifactId}</warName>
|
||||||
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
|
<!-- webXml>src\main\webapp\WEB-INF\web.xml</webXml -->
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>war</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.gcube.gcat;
|
||||||
|
|
||||||
|
import javax.ws.rs.ApplicationPath;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.gcat.rest.Group;
|
||||||
|
import org.glassfish.jersey.server.ResourceConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@ApplicationPath("/")
|
||||||
|
public class ResourceInitializer extends ResourceConfig {
|
||||||
|
|
||||||
|
public static final String APPLICATION_JSON_CHARSET_UTF_8 = MediaType.APPLICATION_JSON + ";charset=UTF-8";
|
||||||
|
|
||||||
|
public ResourceInitializer() {
|
||||||
|
packages(Group.class.getPackage().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.gcube.gcat.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@HttpMethod("PATCH")
|
||||||
|
public @interface PATCH {
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.gcube.gcat.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@HttpMethod("PURGE")
|
||||||
|
public @interface PURGE {
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.gcube.gcat.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class ScienceCatalogueException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generated Serial Version UID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -5449813222333935588L;
|
||||||
|
|
||||||
|
public ScienceCatalogueException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScienceCatalogueException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScienceCatalogueException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package org.gcube.gcat.oldutils;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.cache.CacheManager;
|
||||||
|
import javax.cache.Caching;
|
||||||
|
import javax.cache.configuration.MutableConfiguration;
|
||||||
|
import javax.cache.expiry.CreatedExpiryPolicy;
|
||||||
|
import javax.cache.expiry.Duration;
|
||||||
|
import javax.cache.spi.CachingProvider;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle caches via Ehcache stuff.
|
||||||
|
* @author Costantino Perciante (ISTI - CNR)
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CachesManager {
|
||||||
|
|
||||||
|
// the following caches are declared within the ehcache.xml (no default is available, so pay attention)
|
||||||
|
public static final String PROFILES_READERS_CACHE = "profile_readers";
|
||||||
|
public static final String PROFILES_USERS_CACHE = "profile_users";
|
||||||
|
|
||||||
|
private static final CacheManager cacheManager;
|
||||||
|
private static final Cache<String, DataCalogueMetadataFormatReader> readerCache;
|
||||||
|
private static final Cache<String, JsonNode> userCache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
CachingProvider provider = Caching.getCachingProvider();
|
||||||
|
cacheManager = provider.getCacheManager();
|
||||||
|
|
||||||
|
MutableConfiguration<String, DataCalogueMetadataFormatReader> readerConfiguration =
|
||||||
|
new MutableConfiguration<String, DataCalogueMetadataFormatReader>()
|
||||||
|
.setTypes(String.class, DataCalogueMetadataFormatReader.class)
|
||||||
|
.setStoreByValue(false)
|
||||||
|
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
|
||||||
|
readerCache = cacheManager.createCache(PROFILES_READERS_CACHE, readerConfiguration);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MutableConfiguration<String, JsonNode> userConfiguration =
|
||||||
|
new MutableConfiguration<String, JsonNode>()
|
||||||
|
.setTypes(String.class, JsonNode.class)
|
||||||
|
.setStoreByValue(false)
|
||||||
|
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ONE_MINUTE));
|
||||||
|
userCache = cacheManager.createCache(PROFILES_USERS_CACHE, userConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CachesManager() {}
|
||||||
|
|
||||||
|
public static Cache<String, DataCalogueMetadataFormatReader> getReaderCache() {
|
||||||
|
return readerCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Cache<String, JsonNode> getUserCache() {
|
||||||
|
return userCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
super.finalize();
|
||||||
|
cacheManager.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
package org.gcube.gcat.oldutils;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom field bean. It also stores index of the category and of the metadata field associated.
|
||||||
|
* These are used to sort them before pushing the content to CKAN.
|
||||||
|
* If they are missing, indexes are set to Integer.MAX_VALUE.
|
||||||
|
* @author Costantino Perciante (ISTI - CNR)
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CustomField implements Comparable<CustomField> {
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
private String qualifiedKey;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
private int indexCategory = Integer.MAX_VALUE;
|
||||||
|
private int indexMetadataField = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
private void init(String key, String value, int indexCategory, int indexMetadataField) {
|
||||||
|
if(key == null || value == null || key.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"A custom field must have a key and a value! Provided values are " + key + "=" + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.key = key;
|
||||||
|
this.qualifiedKey = key;
|
||||||
|
this.value = value;
|
||||||
|
|
||||||
|
this.indexMetadataField = indexMetadataField;
|
||||||
|
this.indexCategory = indexCategory;
|
||||||
|
|
||||||
|
if(this.indexCategory < 0) {
|
||||||
|
this.indexCategory = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.indexMetadataField < 0) {
|
||||||
|
this.indexMetadataField = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CustomField(JSONObject object) {
|
||||||
|
super();
|
||||||
|
init((String) object.get("key"), (String) object.get("value"), -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public CustomField(String key, String value) {
|
||||||
|
super();
|
||||||
|
init(key, value, -1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
* @param indexMetadataField
|
||||||
|
* @param indexCategory
|
||||||
|
*/
|
||||||
|
public CustomField(String key, String value, int indexCategory, int indexMetadataField) {
|
||||||
|
super();
|
||||||
|
init(key, value, indexCategory, indexMetadataField);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQualifiedKey() {
|
||||||
|
return qualifiedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQualifiedKey(String qualifiedKey) {
|
||||||
|
this.qualifiedKey = qualifiedKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getIndexCategory() {
|
||||||
|
return indexCategory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexCategory(int indexCategory) {
|
||||||
|
this.indexCategory = indexCategory;
|
||||||
|
if(this.indexCategory < 0)
|
||||||
|
this.indexCategory = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndexMetadataField() {
|
||||||
|
return indexMetadataField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexMetadataField(int indexMetadataField) {
|
||||||
|
this.indexMetadataField = indexMetadataField;
|
||||||
|
if(this.indexMetadataField < 0) {
|
||||||
|
this.indexMetadataField = Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CustomField [key=" + key + ", qualifiedKey=" + qualifiedKey + ", value=" + value
|
||||||
|
+ ", indexMetadataField=" + indexMetadataField + ", indexCategory=" + indexCategory + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(CustomField o) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,633 @@
|
||||||
|
package org.gcube.gcat.oldutils;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.math.NumberUtils;
|
||||||
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
|
||||||
|
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.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.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKAN;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANPackage;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUtility;
|
||||||
|
import org.gcube.gcat.rest.Namespace;
|
||||||
|
import org.gcube.gcat.rest.Profile;
|
||||||
|
import org.gcube.gcat.social.SocialService;
|
||||||
|
import org.geojson.GeoJsonObject;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import eu.trentorise.opendata.jackan.model.CkanGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate creation item requests utilities.
|
||||||
|
* @author Costantino Perciante (ISTI - CNR)
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public class Validator {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Validator.class);
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
private static JSONObject getJSONObject(String json) {
|
||||||
|
JSONParser parser = new JSONParser();
|
||||||
|
JSONObject jsonObject;
|
||||||
|
try {
|
||||||
|
jsonObject = (JSONObject) parser.parse(json);
|
||||||
|
} catch(ParseException e) {
|
||||||
|
throw new BadRequestException(e.getMessage());
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateAgainstProfile(String json, List<String> profiles) throws Exception {
|
||||||
|
JSONObject jsonObject = getJSONObject(json);
|
||||||
|
validateAgainstProfile(jsonObject, profiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method validate the incoming json dataset wrt a metadata profile
|
||||||
|
* @param json
|
||||||
|
* @param caller
|
||||||
|
* @param profiles
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static void validateAgainstProfile(JSONObject obj, List<String> profiles) throws Exception {
|
||||||
|
|
||||||
|
JSONArray extrasArrayOriginal = (JSONArray) obj.get(CKANPackage.EXTRA_TYPES_KEY);
|
||||||
|
JSONArray groupsArrayOriginal = (JSONArray) obj.get(CKANPackage.GROUPS_KEY);
|
||||||
|
JSONArray tagsArrayOriginal = (JSONArray) obj.get(CKANPackage.TAGS_KEY);
|
||||||
|
|
||||||
|
if(extrasArrayOriginal == null || extrasArrayOriginal.isEmpty()) {
|
||||||
|
throw new Exception("'extras' field is missing in context where metadata profile(s) are defined!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(groupsArrayOriginal == null) {
|
||||||
|
groupsArrayOriginal = new JSONArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tagsArrayOriginal == null) {
|
||||||
|
tagsArrayOriginal = new JSONArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the metadata profile specifying the type
|
||||||
|
CustomField metadataTypeCF = null;
|
||||||
|
List<CustomField> customFields = new ArrayList<CustomField>(extrasArrayOriginal.size());
|
||||||
|
Iterator iterator = extrasArrayOriginal.iterator();
|
||||||
|
while(iterator.hasNext()) {
|
||||||
|
JSONObject object = (JSONObject) iterator.next();
|
||||||
|
CustomField cf = new CustomField(object);
|
||||||
|
if(cf.getKey().equals(CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE)) {
|
||||||
|
metadataTypeCF = cf;
|
||||||
|
} else if(cf.getKey().equals(SocialService.ITEM_URL)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
customFields.add(cf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(metadataTypeCF == null) {
|
||||||
|
throw new Exception("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE
|
||||||
|
+ "' extra field is missing in context where metadata profile(s) are defined!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fetch the profile by metadata type specified above
|
||||||
|
MetadataFormat profile = null;
|
||||||
|
for(String profileName : profiles) {
|
||||||
|
profile = Validator.getMetadataProfile(profileName);
|
||||||
|
if(profile.getType().equals(metadataTypeCF.getValue())) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
profile = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(profile == null) {
|
||||||
|
throw new Exception("'" + CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE
|
||||||
|
+ "' extra field's value ('" + metadataTypeCF.getValue() +
|
||||||
|
"') specified as custom field doesn't match any of the profiles defined in this context!");
|
||||||
|
} else {
|
||||||
|
JSONArray extrasArrayUpdated = null;
|
||||||
|
List<MetadataField> metadataFields = profile.getMetadataFields();
|
||||||
|
|
||||||
|
if(metadataFields == null || metadataFields.isEmpty()) {
|
||||||
|
extrasArrayUpdated = extrasArrayOriginal;
|
||||||
|
} else {
|
||||||
|
extrasArrayUpdated = new JSONArray();
|
||||||
|
|
||||||
|
List<NamespaceCategory> categories = Namespace.getNamespaceCategories();
|
||||||
|
logger.debug("Retrieved namespaces are {}", categories);
|
||||||
|
List<String> categoriesIds = new ArrayList<String>(categories == null ? 0 : categories.size());
|
||||||
|
if(categories == null || categories.isEmpty()) {
|
||||||
|
logger.warn("No category defined in context {}", ScopeProvider.instance.get());
|
||||||
|
} else {
|
||||||
|
for(NamespaceCategory metadataCategory : categories) {
|
||||||
|
categoriesIds.add(metadataCategory.getId()); // save them later for matching with custom fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the list of already validated customFields
|
||||||
|
List<CustomField> validatedCustomFields = new ArrayList<CustomField>(customFields.size());
|
||||||
|
|
||||||
|
// keep track of mandatory fields and their cardinality
|
||||||
|
Map<String,Integer> fieldsMandatoryLowerBoundMap = new HashMap<String,Integer>(metadataFields.size());
|
||||||
|
Map<String,Integer> fieldsMandatoryUpperBoundMap = new HashMap<String,Integer>(metadataFields.size());
|
||||||
|
Map<String,Integer> numberFieldsMandatorySameKeyMap = new HashMap<String,Integer>(
|
||||||
|
metadataFields.size());
|
||||||
|
|
||||||
|
// keep track of the groups that must be created AFTER validation but BEFORE item creation
|
||||||
|
List<String> groupsToCreateAfterValidation = new ArrayList<String>();
|
||||||
|
|
||||||
|
// now validate fields
|
||||||
|
int metadataIndex = 0;
|
||||||
|
for(MetadataField metadataField : metadataFields) {
|
||||||
|
|
||||||
|
int categoryIdIndex = categoriesIds.indexOf(metadataField.getCategoryRef());
|
||||||
|
logger.debug("Found index for category " + metadataField.getCategoryRef() + " " + categoryIdIndex);
|
||||||
|
List<CustomField> validCFs = validateAgainstMetadataField(metadataIndex, categoryIdIndex,
|
||||||
|
customFields, tagsArrayOriginal, groupsArrayOriginal, metadataField, categories,
|
||||||
|
fieldsMandatoryLowerBoundMap, fieldsMandatoryUpperBoundMap, numberFieldsMandatorySameKeyMap,
|
||||||
|
groupsToCreateAfterValidation);
|
||||||
|
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 upperBound = fieldsMandatoryUpperBoundMap.get(entry.getKey());
|
||||||
|
int inserted = numberFieldsMandatorySameKeyMap.get(entry.getKey());
|
||||||
|
|
||||||
|
logger.info("Field with key '" + entry.getKey() + "' has been found " + inserted
|
||||||
|
+ " times and its lower bound is " + lowerBound + " and upper bound " + upperBound);
|
||||||
|
|
||||||
|
if(inserted < lowerBound || inserted > upperBound) {
|
||||||
|
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 ([min = "
|
||||||
|
+ lowerBound + ", max=" + upperBound + "]).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there are no tags, throw an exception
|
||||||
|
if(tagsArrayOriginal.isEmpty()) {
|
||||||
|
throw new Exception("Please define at least one tag for this item!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort validated custom fields and add to the extrasArrayUpdated json array
|
||||||
|
Collections.sort(validatedCustomFields);
|
||||||
|
|
||||||
|
logger.debug("Sorted list of custom fields is " + 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);
|
||||||
|
|
||||||
|
// convert back to json
|
||||||
|
for(CustomField customField : validatedCustomFields) {
|
||||||
|
JSONObject jsonObj = new JSONObject();
|
||||||
|
jsonObj.put(CKANPackage.EXTRA_TYPES_KEY_KEY, customField.getQualifiedKey());
|
||||||
|
jsonObj.put(CKANPackage.EXTRA_TYPES_VALUE_KEY, customField.getValue());
|
||||||
|
extrasArrayUpdated.add(jsonObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add metadata type field as last element
|
||||||
|
JSONObject metadataTypeJSON = new JSONObject();
|
||||||
|
metadataTypeJSON.put(CKANPackage.EXTRA_TYPES_KEY_KEY, metadataTypeCF.getKey());
|
||||||
|
metadataTypeJSON.put(CKANPackage.EXTRA_TYPES_VALUE_KEY, metadataTypeCF.getValue());
|
||||||
|
extrasArrayUpdated.add(metadataTypeJSON);
|
||||||
|
|
||||||
|
// create groups
|
||||||
|
for(String title : groupsToCreateAfterValidation) {
|
||||||
|
try {
|
||||||
|
createGroupAsSysAdmin(title, title, "");
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Failed to create group with title " + title, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.put(CKANPackage.TAGS_KEY, tagsArrayOriginal);
|
||||||
|
obj.put(CKANPackage.GROUPS_KEY, groupsArrayOriginal);
|
||||||
|
obj.put(CKANPackage.EXTRA_TYPES_KEY, extrasArrayUpdated);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 CkanGroup createGroupAsSysAdmin(String title, String groupName, String description) throws Exception {
|
||||||
|
return CKAN.getCatalogue().createGroup(groupName, title, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param isApplication
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private static List<CustomField> validateAgainstMetadataField(int metadataIndex, int categoryIndex,
|
||||||
|
List<CustomField> customFields, JSONArray tagsArrayOriginal, JSONArray groupsArrayOriginal,
|
||||||
|
MetadataField metadataField, List<NamespaceCategory> categories,
|
||||||
|
Map<String,Integer> fieldsMandatoryLowerBoundMap, Map<String,Integer> fieldsMandatoryUpperBoundMap,
|
||||||
|
Map<String,Integer> numberFieldsMandatorySameKeyMap, List<String> groupToCreate) throws Exception {
|
||||||
|
|
||||||
|
List<CustomField> toReturn = new ArrayList<CustomField>();
|
||||||
|
String metadataFieldName = metadataField.getCategoryFieldQName(); // get the qualified one, if any
|
||||||
|
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++;
|
||||||
|
cf.setIndexCategory(categoryIndex);
|
||||||
|
cf.setIndexMetadataField(metadataIndex);
|
||||||
|
checkAsGroup(cf, metadataField, groupsArrayOriginal, groupToCreate);
|
||||||
|
checkAsTag(cf, metadataField, tagsArrayOriginal);
|
||||||
|
toReturn.add(cf);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case of mandatory fields, keep track of the number of times they appear
|
||||||
|
if(metadataField.getMandatory()) {
|
||||||
|
// lower bound
|
||||||
|
int lowerBound = 1;
|
||||||
|
if(fieldsMandatoryLowerBoundMap.containsKey(metadataFieldName))
|
||||||
|
lowerBound = fieldsMandatoryLowerBoundMap.get(metadataFieldName) + 1;
|
||||||
|
fieldsMandatoryLowerBoundMap.put(metadataFieldName, lowerBound);
|
||||||
|
|
||||||
|
// upper bound
|
||||||
|
boolean hasVocabulary = metadataField.getVocabulary() != null;
|
||||||
|
int upperBound = hasVocabulary ? (metadataField.getVocabulary().isMultiSelection()
|
||||||
|
? metadataField.getVocabulary().getVocabularyFields().size()
|
||||||
|
: 1) : 1;
|
||||||
|
|
||||||
|
if(fieldsMandatoryUpperBoundMap.containsKey(metadataFieldName))
|
||||||
|
upperBound += fieldsMandatoryUpperBoundMap.get(metadataFieldName);
|
||||||
|
|
||||||
|
fieldsMandatoryUpperBoundMap.put(metadataFieldName, upperBound);
|
||||||
|
|
||||||
|
// fields with this same key
|
||||||
|
int countPerFields = fieldsFoundWithThisKey;
|
||||||
|
if(numberFieldsMandatorySameKeyMap.containsKey(metadataFieldName))
|
||||||
|
countPerFields += numberFieldsMandatorySameKeyMap.get(metadataFieldName);
|
||||||
|
numberFieldsMandatorySameKeyMap.put(metadataFieldName, countPerFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there was no field with this key and it was not mandatory, just add an entry of the kind {"key": "key-value", "value" : ""}.
|
||||||
|
// Sometimes it is important to view the field as empty.
|
||||||
|
if(fieldsFoundWithThisKey == 0 && !metadataField.getMandatory()) {
|
||||||
|
toReturn.add(new CustomField(metadataFieldName, "", -1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int MAX_TAG_CHARS = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
String tag = "";
|
||||||
|
|
||||||
|
switch(tagging.getTaggingValue()) {
|
||||||
|
case onFieldName:
|
||||||
|
tag = metadataField.getFieldName();
|
||||||
|
break;
|
||||||
|
case onValue:
|
||||||
|
tag = fieldToValidate.getValue();
|
||||||
|
break;
|
||||||
|
case onFieldName_onValue:
|
||||||
|
tag = metadataField.getFieldName() + tagging.getSeparator() + fieldToValidate.getValue();
|
||||||
|
break;
|
||||||
|
case onValue_onFieldName:
|
||||||
|
tag = fieldToValidate.getValue() + tagging.getSeparator() + metadataField.getFieldName();
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a group must be generated
|
||||||
|
* @param fieldToValidate
|
||||||
|
* @param metadataField
|
||||||
|
* @param groupsArrayOriginal
|
||||||
|
* @param isApplication
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private static void checkAsGroup(CustomField fieldToValidate, MetadataField metadataField,
|
||||||
|
JSONArray groupsArrayOriginal, List<String> groupToCreate) throws Exception {
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
boolean propagateUp = grouping.getPropagateUp();
|
||||||
|
final Set<String> groupNames = new HashSet<String>();
|
||||||
|
|
||||||
|
switch(grouping.getGroupingValue()) {
|
||||||
|
case onFieldName:
|
||||||
|
groupNames.add(metadataField.getFieldName());
|
||||||
|
break;
|
||||||
|
case onValue:
|
||||||
|
if(fieldToValidate.getValue() != null && !fieldToValidate.getValue().isEmpty())
|
||||||
|
groupNames.add(fieldToValidate.getValue());
|
||||||
|
break;
|
||||||
|
case onFieldName_onValue:
|
||||||
|
case onValue_onFieldName:
|
||||||
|
groupNames.add(metadataField.getFieldName());
|
||||||
|
if(fieldToValidate.getValue() != null && !fieldToValidate.getValue().isEmpty())
|
||||||
|
groupNames.add(fieldToValidate.getValue());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String title : groupNames) {
|
||||||
|
logger.debug("Adding group to which add this item " + CatalogueUtilMethods.fromGroupTitleToName(title));
|
||||||
|
JSONObject group = new JSONObject();
|
||||||
|
group.put("name", CatalogueUtilMethods.fromGroupTitleToName(title));
|
||||||
|
if(propagateUp) {
|
||||||
|
List<String> parents = Validator.getGroupHierarchyNames(CatalogueUtilMethods.fromGroupTitleToName(title));
|
||||||
|
for(String parent : parents) {
|
||||||
|
JSONObject groupP = new JSONObject();
|
||||||
|
groupP.put("name", parent);
|
||||||
|
groupsArrayOriginal.add(groupP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupsArrayOriginal.add(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
// force group creation if needed
|
||||||
|
if(grouping.getCreate()) {
|
||||||
|
for(String title : groupNames)
|
||||||
|
groupToCreate.add(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the single field
|
||||||
|
* @param fieldToValidate
|
||||||
|
* @param metadataField
|
||||||
|
* @param isFirst
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private static void validate(CustomField fieldToValidate, MetadataField metadataField) throws Exception {
|
||||||
|
|
||||||
|
DataType dataType = metadataField.getDataType();
|
||||||
|
String regex = metadataField.getValidator() != null ? metadataField.getValidator().getRegularExpression()
|
||||||
|
: null;
|
||||||
|
boolean hasControlledVocabulary = metadataField.getVocabulary() != null;
|
||||||
|
String value = fieldToValidate.getValue();
|
||||||
|
String key = fieldToValidate.getKey();
|
||||||
|
String defaultValue = metadataField.getDefaultValue();
|
||||||
|
|
||||||
|
// replace key by prepending the qualified name of the category, if needed
|
||||||
|
fieldToValidate.setQualifiedKey(metadataField.getCategoryFieldQName());
|
||||||
|
|
||||||
|
if((value == null || value.isEmpty()))
|
||||||
|
if(metadataField.getMandatory() || hasControlledVocabulary)
|
||||||
|
throw new Exception("Mandatory field with name '" + key
|
||||||
|
+ "' doesn't have a value but it is mandatory or has a controlled vocabulary!");
|
||||||
|
else {
|
||||||
|
if(defaultValue != null && !defaultValue.isEmpty()) {
|
||||||
|
value = defaultValue;
|
||||||
|
fieldToValidate.setValue(defaultValue);
|
||||||
|
}
|
||||||
|
return; // there is no need to check other stuff
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
if(valuesVocabulary == null || valuesVocabulary.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean match = false;
|
||||||
|
for(String valueVocabulary : valuesVocabulary) {
|
||||||
|
match = value.equals(valueVocabulary);
|
||||||
|
if(match)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!match)
|
||||||
|
throw new Exception("Field with key '" + key + "' has a value '" + value
|
||||||
|
+ "' but it doesn't match any of the vocabulary's values (" + valuesVocabulary + ")!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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("/");
|
||||||
|
if(timeIntervalValues.length > 2)
|
||||||
|
throw new Exception("Field with key '" + key + "' doesn't seem a valid list of times!");
|
||||||
|
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:
|
||||||
|
|
||||||
|
try {
|
||||||
|
new ObjectMapper().readValue(fieldToValidate.getValue(), GeoJsonObject.class);
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new Exception("GeoJSON field with key '" + key + "' seems not valid!");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.debug("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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the group hierarchy
|
||||||
|
* @param groupName
|
||||||
|
* @param isApplication
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static List<String> getGroupHierarchyNames(String groupName) throws Exception {
|
||||||
|
List<String> toReturn = new ArrayList<String>();
|
||||||
|
String apiKey = CKANUtility.getApiKey();
|
||||||
|
List<CkanGroup> ckanGroups = CKAN.getCatalogue().getParentGroups(groupName, apiKey);
|
||||||
|
if(ckanGroups != null && !ckanGroups.isEmpty()) {
|
||||||
|
for(CkanGroup ckanGroup : ckanGroups) {
|
||||||
|
toReturn.add(ckanGroup.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
|
||||||
|
DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,300 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.NullNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public abstract class CKAN {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CKAN.class);
|
||||||
|
|
||||||
|
protected static final String ID_KEY = "id";
|
||||||
|
protected static final String NAME_KEY = "name";
|
||||||
|
|
||||||
|
protected static final String ERROR_KEY = "error";
|
||||||
|
protected static final String ERROR_TYPE_KEY = "__type";
|
||||||
|
protected static final String MESSAGE_KEY = "message";
|
||||||
|
protected static final String OWNER_ORG_KEY = "owner_org";
|
||||||
|
|
||||||
|
protected static final String RESULT_KEY = "result";
|
||||||
|
protected static final String SUCCESS_KEY = "success";
|
||||||
|
|
||||||
|
protected static final String NOT_FOUND_ERROR = "Not Found Error";
|
||||||
|
protected static final String AUTHORIZATION_ERROR = "Authorization Error";
|
||||||
|
protected static final String VALIDATION_ERROR = "Validation Error";
|
||||||
|
|
||||||
|
// 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";
|
||||||
|
|
||||||
|
protected String LIST;
|
||||||
|
protected String CREATE;
|
||||||
|
protected String READ;
|
||||||
|
protected String UPDATE;
|
||||||
|
protected String PATCH;
|
||||||
|
protected String DELETE;
|
||||||
|
protected String PURGE;
|
||||||
|
|
||||||
|
protected final ObjectMapper mapper;
|
||||||
|
protected final DataCatalogue dataCatalogue;
|
||||||
|
|
||||||
|
protected String name;
|
||||||
|
protected String apiKey;
|
||||||
|
|
||||||
|
protected JsonNode result;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String getApiKey() {
|
||||||
|
if(apiKey==null) {
|
||||||
|
try {
|
||||||
|
return CKANUtility.getApiKey();
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApiKey(String apiKey) {
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectMapper getMapper() {
|
||||||
|
return mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode getJsonNodeResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CKAN() {
|
||||||
|
try {
|
||||||
|
this.mapper = new ObjectMapper();
|
||||||
|
this.dataCatalogue = getCatalogue();
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode getAsJsonNode(String json) {
|
||||||
|
try {
|
||||||
|
return mapper.readTree(json);
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new BadRequestException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an instance of the library for the current scope
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static DataCatalogue getCatalogue() throws Exception {
|
||||||
|
String context = ContextUtility.getCurrentContext();
|
||||||
|
logger.debug("Discovering ckan instance in context {}", context);
|
||||||
|
return DataCatalogueFactory.getFactory().getUtilsPerScope(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the CKAN response and return the
|
||||||
|
* @param json
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected JsonNode validateCKANResponse(String json) {
|
||||||
|
JsonNode jsonNode = getAsJsonNode(json);
|
||||||
|
if(jsonNode.get(SUCCESS_KEY).asBoolean()) {
|
||||||
|
return jsonNode.get(RESULT_KEY);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
JsonNode error = jsonNode.get(ERROR_KEY);
|
||||||
|
|
||||||
|
String errorType = error.get(ERROR_TYPE_KEY).asText();
|
||||||
|
|
||||||
|
if(errorType.compareTo(VALIDATION_ERROR) == 0) {
|
||||||
|
throw new BadRequestException(getAsString(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String message = error.get(MESSAGE_KEY).asText();
|
||||||
|
|
||||||
|
if(errorType.compareTo(NOT_FOUND_ERROR) == 0) {
|
||||||
|
throw new NotFoundException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(errorType.compareTo(AUTHORIZATION_ERROR) == 0) {
|
||||||
|
throw new NotAuthorizedException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TODO parse more cases
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new BadRequestException(json);
|
||||||
|
}
|
||||||
|
throw new BadRequestException(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getAsString(JsonNode node) {
|
||||||
|
try {
|
||||||
|
String json = mapper.writeValueAsString(node);
|
||||||
|
return json;
|
||||||
|
} catch(JsonProcessingException e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode checkName(JsonNode jsonNode) {
|
||||||
|
try {
|
||||||
|
String gotName = jsonNode.get(NAME_KEY).asText();
|
||||||
|
if(name==null) {
|
||||||
|
name = gotName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gotName != null && gotName.compareTo(name) != 0) {
|
||||||
|
String error = String.format(
|
||||||
|
"The name (%s) does not match with the '%s' contained in the provided content (%s).",
|
||||||
|
name, NAME_KEY, gotName);
|
||||||
|
throw new BadRequestException(error);
|
||||||
|
}
|
||||||
|
return jsonNode;
|
||||||
|
} catch(BadRequestException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new BadRequestException("Unable to obtain a correct 'name' from the provided content");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode checkName(String json) {
|
||||||
|
JsonNode jsonNode = getAsJsonNode(json);
|
||||||
|
checkName(jsonNode);
|
||||||
|
return jsonNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode createJsonNodeWithID(String id) {
|
||||||
|
ObjectNode objectNode = mapper.createObjectNode();
|
||||||
|
objectNode.put(ID_KEY, id);
|
||||||
|
return objectNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode createJsonNodeWithNameAsID() {
|
||||||
|
return createJsonNodeWithID(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String,String> getMapWithNameAsID() {
|
||||||
|
return getMapWithID(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Map<String,String> getMapWithID(String id) {
|
||||||
|
Map<String,String> map = new HashMap<>();
|
||||||
|
map.put(ID_KEY, id);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode sendRequest(HTTPMETHOD httpMethod, String path, Map<String,String> parameters, String body) {
|
||||||
|
String catalogueURL = dataCatalogue.getCatalogueUrl().endsWith("/") ? dataCatalogue.getCatalogueUrl() : dataCatalogue.getCatalogueUrl() + "/";
|
||||||
|
HTTPCall httpCall = new HTTPCall(catalogueURL);
|
||||||
|
httpCall.setgCubeTargetService(false);
|
||||||
|
httpCall.addHeader(AUTH_CKAN_HEADER, getApiKey());
|
||||||
|
String ret = httpCall.call(path, httpMethod, parameters, body, MediaType.APPLICATION_JSON);
|
||||||
|
JsonNode result = validateCKANResponse(ret);
|
||||||
|
if(result instanceof NullNode) {
|
||||||
|
result = mapper.createObjectNode();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sendGetRequest(String path, Map<String,String> parameters) {
|
||||||
|
result = sendRequest(HTTPMETHOD.GET, path, parameters, null);
|
||||||
|
return getAsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sendPostRequest(String path, String body) {
|
||||||
|
result = sendRequest(HTTPMETHOD.POST, path, null, body);
|
||||||
|
return getAsString(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sendPostRequest(String path, JsonNode jsonNode) {
|
||||||
|
return sendPostRequest(path, getAsString(jsonNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String list() {
|
||||||
|
return sendGetRequest(LIST, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String create(String json) {
|
||||||
|
return sendPostRequest(CREATE, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read() {
|
||||||
|
return sendGetRequest(READ, getMapWithNameAsID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String update(String json) {
|
||||||
|
checkName(json);
|
||||||
|
return sendPostRequest(UPDATE, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String patch(String json) {
|
||||||
|
JsonNode jsonNode = checkName(json);
|
||||||
|
ObjectNode objectNode = ((ObjectNode) jsonNode);
|
||||||
|
objectNode.put(ID_KEY, name);
|
||||||
|
objectNode.remove(NAME_KEY);
|
||||||
|
return sendPostRequest(PATCH, objectNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void delete() {
|
||||||
|
sendPostRequest(DELETE, createJsonNodeWithNameAsID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(boolean purge) {
|
||||||
|
if(purge) {
|
||||||
|
purge();
|
||||||
|
} else {
|
||||||
|
delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void purge() {
|
||||||
|
sendPostRequest(PURGE, createJsonNodeWithNameAsID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANGroup extends CKAN {
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_list
|
||||||
|
public static final String GROUP_LIST = CKAN.CKAN_API_PATH + "group_list";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.group_create
|
||||||
|
public static final String GROUP_CREATE = CKAN.CKAN_API_PATH + "group_create";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.group_show
|
||||||
|
public static final String GROUP_SHOW = CKAN.CKAN_API_PATH + "group_show";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.group_update
|
||||||
|
public static final String GROUP_UPDATE = CKAN.CKAN_API_PATH + "group_update";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.group_patch
|
||||||
|
public static final String GROUP_PATCH = CKAN.CKAN_API_PATH + "group_patch";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_delete
|
||||||
|
public static final String GROUP_DELETE = CKAN.CKAN_API_PATH + "group_delete";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.group_purge
|
||||||
|
public static final String GROUP_PURGE = CKAN.CKAN_API_PATH + "group_purge";
|
||||||
|
|
||||||
|
public CKANGroup() {
|
||||||
|
super();
|
||||||
|
LIST = GROUP_LIST;
|
||||||
|
CREATE = GROUP_CREATE;
|
||||||
|
READ = GROUP_SHOW;
|
||||||
|
UPDATE = GROUP_UPDATE;
|
||||||
|
PATCH = GROUP_PATCH;
|
||||||
|
DELETE = GROUP_DELETE;
|
||||||
|
PURGE = GROUP_PURGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANLicense extends CKAN {
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.license_list
|
||||||
|
public static final String LICENSES_LIST = CKAN.CKAN_API_PATH + "license_list";
|
||||||
|
|
||||||
|
public CKANLicense() {
|
||||||
|
super();
|
||||||
|
LIST = LICENSES_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.shared.RolesCkanGroupOrOrg;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
import eu.trentorise.opendata.jackan.model.CkanOrganization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANOrganization extends CKAN {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANOrganization.class);
|
||||||
|
|
||||||
|
// CKAN Connector sanitize the Organization name as following
|
||||||
|
//organizationName.replaceAll(" ", "_").replace(".", "_").toLowerCase()
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_list
|
||||||
|
public static final String ORGANIZATION_LIST = CKAN.CKAN_API_PATH + "organization_list";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_create
|
||||||
|
public static final String ORGANIZATION_CREATE = CKAN.CKAN_API_PATH + "organization_create";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.organization_show
|
||||||
|
public static final String ORGANIZATION_SHOW = CKAN.CKAN_API_PATH + "organization_show";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.organization_update
|
||||||
|
public static final String ORGANIZATION_UPDATE = CKAN.CKAN_API_PATH + "organization_update";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.organization_patch
|
||||||
|
public static final String ORGANIZATION_PATCH = CKAN.CKAN_API_PATH + "organization_patch";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_delete
|
||||||
|
public static final String ORGANIZATION_DELETE = CKAN.CKAN_API_PATH + "organization_delete";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.organization_purge
|
||||||
|
public static final String ORGANIZATION_PURGE = CKAN.CKAN_API_PATH + "organization_purge";
|
||||||
|
|
||||||
|
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.create.organization_member_create
|
||||||
|
public static final String ORGANIZATION_MEMBER_CREATE = CKAN.CKAN_API_PATH + "organization_member_create";
|
||||||
|
|
||||||
|
// https://docs.ckan.org/en/latest/api/index.html#ckan.logic.action.get.organization_list_for_user
|
||||||
|
public static final String ORGANIZATION_LIST_FOR_USER = CKAN.CKAN_API_PATH + "organization_list_for_user";
|
||||||
|
|
||||||
|
protected static final String USERNAME_KEY = "username";
|
||||||
|
protected static final String ROLE_KEY = "role";
|
||||||
|
|
||||||
|
|
||||||
|
public CKANOrganization() {
|
||||||
|
super();
|
||||||
|
LIST = ORGANIZATION_LIST;
|
||||||
|
CREATE = ORGANIZATION_CREATE;
|
||||||
|
READ = ORGANIZATION_SHOW;
|
||||||
|
UPDATE = ORGANIZATION_UPDATE;
|
||||||
|
PATCH = ORGANIZATION_PATCH;
|
||||||
|
DELETE = ORGANIZATION_DELETE;
|
||||||
|
PURGE = ORGANIZATION_PURGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static final String ORGANIZATION_PERMISSION_KEY = "permission";
|
||||||
|
protected static final String ORGANIZATION_PERMISSION_VALUE_READ = "read";
|
||||||
|
|
||||||
|
public String getUserRole(String gCubeUsername) {
|
||||||
|
Map<String,Map<CkanOrganization,RolesCkanGroupOrOrg>> rolesPerOrganization = dataCatalogue
|
||||||
|
.getUserRoleByOrganization(gCubeUsername, CKANUtility.getApiKey(gCubeUsername));
|
||||||
|
if(rolesPerOrganization.containsKey(name)) {
|
||||||
|
Map<CkanOrganization,RolesCkanGroupOrOrg> map = rolesPerOrganization.get(name);
|
||||||
|
Set<CkanOrganization> ckanOrganizations = map.keySet();
|
||||||
|
for(CkanOrganization ckanOrganization : ckanOrganizations) {
|
||||||
|
return map.get(ckanOrganization).name().toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUserToOrganisation(String gCubeUsername, String role, boolean force) {
|
||||||
|
String ckanUsername = CKANUtility.getCKANUsername(gCubeUsername);
|
||||||
|
String userRole = getUserRole(gCubeUsername);
|
||||||
|
if((userRole==null || force)) {
|
||||||
|
if(userRole!=null && userRole.toLowerCase().compareTo(role.toLowerCase())==0) {
|
||||||
|
logger.debug("User {} is already member of Organisation {} with role {}", ckanUsername, name, userRole);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ObjectNode objectNode = mapper.createObjectNode();
|
||||||
|
objectNode.put(ID_KEY, name);
|
||||||
|
objectNode.put(USERNAME_KEY, ckanUsername);
|
||||||
|
objectNode.put(ROLE_KEY, role);
|
||||||
|
sendPostRequest(ORGANIZATION_MEMBER_CREATE, getAsString(objectNode));
|
||||||
|
logger.debug("User {} successfully added to Organisation {} with role {}", ckanUsername, name, role);
|
||||||
|
}else {
|
||||||
|
logger.debug("User {} is already member of Organisation {} with role {}", ckanUsername, name, userRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCKANOrganizationName() {
|
||||||
|
String context = ContextUtility.getCurrentContext();
|
||||||
|
return getCKANOrganizationName(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCKANOrganizationName(String context) {
|
||||||
|
ScopeBean scopeBean = new ScopeBean(context);
|
||||||
|
return scopeBean.name().toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,346 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HEAD;
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.NotAllowedException;
|
||||||
|
import javax.ws.rs.OPTIONS;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||||
|
import org.gcube.gcat.annotation.PURGE;
|
||||||
|
import org.gcube.gcat.oldutils.Validator;
|
||||||
|
import org.gcube.gcat.social.SocialService;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.gcube.gcat.utils.URIResolver;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANPackage extends CKAN {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CKANPackage.class);
|
||||||
|
|
||||||
|
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_list
|
||||||
|
public static final String ITEM_LIST = CKAN.CKAN_API_PATH + "package_list";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create
|
||||||
|
public static final String ITEM_CREATE = CKAN.CKAN_API_PATH + "package_create";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_show
|
||||||
|
public static final String ITEM_SHOW = CKAN.CKAN_API_PATH + "package_show";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update
|
||||||
|
public static final String ITEM_UPDATE = CKAN.CKAN_API_PATH + "package_update";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch
|
||||||
|
public static final String ITEM_PATCH = CKAN.CKAN_API_PATH + "package_patch";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.package_delete
|
||||||
|
public static final String ITEM_DELETE = CKAN.CKAN_API_PATH + "package_delete";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.dataset_purge
|
||||||
|
public static final String ITEM_PURGE = CKAN.CKAN_API_PATH + "dataset_purge";
|
||||||
|
|
||||||
|
protected static final String LICENSE_KEY = "license_id";
|
||||||
|
|
||||||
|
protected static final String ITEM_URL_KEY = "item_url";
|
||||||
|
protected static final String AUTHOR_KEY = "author";
|
||||||
|
protected static final String AUTHOR_EMAIL_KEY = "author_email";
|
||||||
|
protected static final String OWNER_ORG_KEY = "owner_org";
|
||||||
|
protected static final String RESOURCES_KEY = "resources";
|
||||||
|
protected static final String TITLE_KEY = "title";
|
||||||
|
|
||||||
|
public static final String EXTRA_TYPES_KEY = "extras";
|
||||||
|
public static final String EXTRA_TYPES_KEY_KEY = "key";
|
||||||
|
public static final String EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE = "system:type";
|
||||||
|
public static final String EXTRA_TYPES_VALUE_KEY = "value";
|
||||||
|
|
||||||
|
public static final String GROUPS_KEY = "groups";
|
||||||
|
public static final String TAGS_KEY = "tags";
|
||||||
|
|
||||||
|
protected final List<CKANResource> managedResources;
|
||||||
|
|
||||||
|
protected String itemID;
|
||||||
|
|
||||||
|
public CKANPackage() {
|
||||||
|
super();
|
||||||
|
LIST = ITEM_LIST;
|
||||||
|
CREATE = ITEM_CREATE;
|
||||||
|
READ = ITEM_SHOW;
|
||||||
|
UPDATE = ITEM_UPDATE;
|
||||||
|
PATCH = ITEM_PATCH;
|
||||||
|
DELETE = ITEM_DELETE;
|
||||||
|
PURGE = ITEM_PURGE;
|
||||||
|
managedResources = new ArrayList<CKANResource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectNode checkBaseInformation(String json) throws Exception {
|
||||||
|
ObjectNode objectNode = (ObjectNode) mapper.readTree(json);
|
||||||
|
|
||||||
|
objectNode = (ObjectNode) checkName(objectNode);
|
||||||
|
|
||||||
|
// We need to enforce the itemID to properly manage resource persistence
|
||||||
|
if(objectNode.has(ID_KEY)) {
|
||||||
|
itemID = objectNode.get(ID_KEY).asText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check license
|
||||||
|
String licenseId = null;
|
||||||
|
if(objectNode.has(LICENSE_KEY)) {
|
||||||
|
licenseId = objectNode.get(LICENSE_KEY).asText();
|
||||||
|
}
|
||||||
|
if(licenseId == null || licenseId.isEmpty()) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
"You must specify a license identifier for the item. License list can be retrieved using licence collection");
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode userJsonNode = CKANUtility.getCKANUser();
|
||||||
|
objectNode.put(AUTHOR_KEY, userJsonNode.get(CKANUser.NAME).asText());
|
||||||
|
objectNode.put(AUTHOR_EMAIL_KEY, userJsonNode.get(CKANUser.EMAIL).asText());
|
||||||
|
|
||||||
|
// owner organization must be specified if the token belongs to a VRE
|
||||||
|
ScopeBean scopeBean = new ScopeBean(ContextUtility.getCurrentContext());
|
||||||
|
String contextName = scopeBean.name();
|
||||||
|
|
||||||
|
String gotOrganization = null;
|
||||||
|
if(objectNode.has(OWNER_ORG_KEY)) {
|
||||||
|
gotOrganization = objectNode.get(OWNER_ORG_KEY).asText();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(scopeBean.is(Type.VRE)) {
|
||||||
|
String organizationFromContext = contextName.toLowerCase().replace(" ", "_");
|
||||||
|
if(gotOrganization != null) {
|
||||||
|
if(gotOrganization.compareTo(organizationFromContext) != 0) {
|
||||||
|
CKANOrganization ckanOrganization = new CKANOrganization();
|
||||||
|
ckanOrganization.setName(organizationFromContext);
|
||||||
|
ckanOrganization.read();
|
||||||
|
String organizationID = null;
|
||||||
|
if(ckanOrganization.result.has(ID_KEY)) {
|
||||||
|
organizationID = ckanOrganization.result.get(ID_KEY).asText();
|
||||||
|
}
|
||||||
|
if(organizationID == null || gotOrganization.compareTo(organizationID) != 0) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
"You can only publish in the Organization associate to the current VRE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
objectNode.put(OWNER_ORG_KEY, organizationFromContext);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO check if the requested organization context is a sub context of current context
|
||||||
|
// TODO check if the check is correct for PARTHENOS
|
||||||
|
if(gotOrganization == null) {
|
||||||
|
throw new BadRequestException("You must specify an Organization usign " + OWNER_ORG_KEY + " field");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JsonNode validateJson(String json) {
|
||||||
|
try {
|
||||||
|
// check base information (and set them if needed)
|
||||||
|
ObjectNode objectNode = checkBaseInformation(json);
|
||||||
|
|
||||||
|
// Validating against profiles if any
|
||||||
|
// List<String> profiles = Profile.getProfilesNames(); TODO RESTORE THIS LINE
|
||||||
|
List<String> profiles = null; // TODO REMOVE THIS LINE
|
||||||
|
if(profiles != null && !profiles.isEmpty()) {
|
||||||
|
Validator.validateAgainstProfile(getAsString(objectNode), profiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectNode;
|
||||||
|
} catch(BadRequestException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new BadRequestException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.package_list
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void rollbackManagedResources() {
|
||||||
|
for(CKANResource ckanResource : managedResources) {
|
||||||
|
try {
|
||||||
|
ckanResource.rollback();
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.error("Unable to rollback resource {} to the original value", ckanResource.getResourceID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ArrayNode createResources(ArrayNode resourcesToBeCreated) {
|
||||||
|
ArrayNode created = mapper.createArrayNode();
|
||||||
|
for(JsonNode resourceNode : resourcesToBeCreated) {
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
String json = ckanResource.create(getAsString(resourceNode));
|
||||||
|
created.add(getAsJsonNode(json));
|
||||||
|
managedResources.add(ckanResource);
|
||||||
|
}
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.package_create
|
||||||
|
@Override
|
||||||
|
public String create(String json) {
|
||||||
|
try {
|
||||||
|
logger.debug("Going to create Item {}", json);
|
||||||
|
|
||||||
|
JsonNode jsonNode = validateJson(json);
|
||||||
|
|
||||||
|
ArrayNode resourcesToBeCreated = mapper.createArrayNode();
|
||||||
|
if(jsonNode.has(RESOURCES_KEY)) {
|
||||||
|
resourcesToBeCreated = (ArrayNode) jsonNode.get(RESOURCES_KEY);
|
||||||
|
((ObjectNode) jsonNode).remove(RESOURCES_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
super.create(getAsString(jsonNode));
|
||||||
|
|
||||||
|
this.itemID = result.get(ID_KEY).asText();
|
||||||
|
ArrayNode created = createResources(resourcesToBeCreated);
|
||||||
|
((ObjectNode) result).replace(RESOURCES_KEY, created);
|
||||||
|
|
||||||
|
// Adding Item URL via Resolver
|
||||||
|
URIResolver uriResolver = new URIResolver();
|
||||||
|
String catalogueItemURL = uriResolver.getCatalogueItemURL(name);
|
||||||
|
((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL);
|
||||||
|
|
||||||
|
// Actions performed after a package has been correctly created on ckan.
|
||||||
|
String title = result.get(TITLE_KEY).asText();
|
||||||
|
|
||||||
|
ArrayNode arrayNode = (ArrayNode) result.get(TAGS_KEY);
|
||||||
|
SocialService packagePostActions = new SocialService(catalogueItemURL, name, arrayNode, title);
|
||||||
|
packagePostActions.start();
|
||||||
|
|
||||||
|
return getAsString(result);
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
rollbackManagedResources();
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
rollbackManagedResources();
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.package_update
|
||||||
|
@Override
|
||||||
|
public String update(String json) {
|
||||||
|
try {
|
||||||
|
JsonNode jsonNode = validateJson(json);
|
||||||
|
this.itemID = jsonNode.get(ID_KEY).asText();
|
||||||
|
|
||||||
|
read();
|
||||||
|
|
||||||
|
Map<String, CKANResource> originalResources = new HashMap<>();
|
||||||
|
ArrayNode originalResourcesarrayNode = (ArrayNode) result.get(RESOURCES_KEY);
|
||||||
|
if(originalResources!=null) {
|
||||||
|
for(JsonNode resourceNode : originalResourcesarrayNode) {
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setPreviousRepresentation(resourceNode);
|
||||||
|
String resourceID = ckanResource.getResourceID();
|
||||||
|
originalResources.put(resourceID, ckanResource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(jsonNode.has(RESOURCES_KEY)) {
|
||||||
|
ArrayNode resourcesToBeSend = mapper.createArrayNode();
|
||||||
|
ArrayNode receivedResources = (ArrayNode) jsonNode.get(RESOURCES_KEY);
|
||||||
|
for(JsonNode resourceNode : receivedResources) {
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
String resourceId = CKANResource.extractResourceID(resourceNode);
|
||||||
|
if(resourceId!=null) {
|
||||||
|
if(originalResources.containsKey(resourceId)) {
|
||||||
|
ckanResource = originalResources.get(resourceId);
|
||||||
|
originalResources.remove(resourceId);
|
||||||
|
}else {
|
||||||
|
throw new BadRequestException("The content cotains a resource with id " + resourceId + " which does not exists") ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resourceNode = ckanResource.createOrUpdate(resourceNode);
|
||||||
|
resourcesToBeSend.add(resourceNode);
|
||||||
|
managedResources.add(ckanResource);
|
||||||
|
|
||||||
|
}
|
||||||
|
((ObjectNode) jsonNode).replace(RESOURCES_KEY, resourcesToBeSend);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendPostRequest(ITEM_UPDATE, getAsString(jsonNode));
|
||||||
|
|
||||||
|
for(String resourceId : originalResources.keySet()) {
|
||||||
|
CKANResource ckanResource = originalResources.get(resourceId);
|
||||||
|
ckanResource.deleteFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adding Item URL via Resolver
|
||||||
|
URIResolver uriResolver = new URIResolver();
|
||||||
|
String catalogueItemURL = uriResolver.getCatalogueItemURL(name);
|
||||||
|
((ObjectNode) result).put(ITEM_URL_KEY, catalogueItemURL);
|
||||||
|
|
||||||
|
return getAsString(result);
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
rollbackManagedResources();
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
rollbackManagedResources();
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.package_patch
|
||||||
|
@Override
|
||||||
|
public String patch(String json) {
|
||||||
|
String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(),
|
||||||
|
PUT.class.getSimpleName(), DELETE.class.getSimpleName(), PURGE.class.getSimpleName()};
|
||||||
|
throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void delete() {
|
||||||
|
super.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void purge() {
|
||||||
|
try {
|
||||||
|
delete();
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
// If the item was deleted but not purged we obtain Not Found. This is accepted. The item has to be purged
|
||||||
|
// with SysAdmin right.
|
||||||
|
Status status = Status.fromStatusCode(e.getResponse().getStatusInfo().getStatusCode());
|
||||||
|
if(status != Status.NOT_FOUND) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setApiKey(CKANUtility.getSysAdminAPI());
|
||||||
|
read();
|
||||||
|
if(result.has(RESOURCES_KEY)) {
|
||||||
|
itemID = result.get(ID_KEY).asText();
|
||||||
|
ArrayNode arrayNode = (ArrayNode) result.get(RESOURCES_KEY);
|
||||||
|
for(JsonNode jsonNode : arrayNode) {
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setPreviousRepresentation(jsonNode);
|
||||||
|
ckanResource.deleteFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.purge();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,409 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.ws.rs.BadRequestException;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HEAD;
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.NotAllowedException;
|
||||||
|
import javax.ws.rs.OPTIONS;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
|
||||||
|
import org.gcube.gcat.utils.ApplicationMode;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall;
|
||||||
|
import org.gcube.gcat.workspace.StorageHubManagement;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANResource extends CKAN {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CKANResource.class);
|
||||||
|
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.resource_create
|
||||||
|
public static final String RESOURCE_CREATE = CKAN.CKAN_API_PATH + "resource_create";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.resource_show
|
||||||
|
public static final String RESOURCE_SHOW = CKAN.CKAN_API_PATH + "resource_show";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.resource_update
|
||||||
|
public static final String RESOURCE_UPDATE = CKAN.CKAN_API_PATH + "resource_update";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.patch.resource_patch
|
||||||
|
public static final String RESOURCE_PATCH = CKAN.CKAN_API_PATH + "resource_patch";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.resource_delete
|
||||||
|
public static final String RESOURCE_DELETE = CKAN.CKAN_API_PATH + "resource_delete";
|
||||||
|
|
||||||
|
/* TODO Remove this code ASAP. It requires a function from Storage HUB */
|
||||||
|
private static final String URI_RESOLVER_STORAGE_HUB_HOST_PROD = "data.d4science.org";
|
||||||
|
private static final String URI_RESOLVER_STORAGE_HUB_HOST_DEV = "data-d.d4science.org";
|
||||||
|
|
||||||
|
public static final String URI_RESOLVER_STORAGE_HUB_HOST;
|
||||||
|
public static final String URI_RESOLVER_STORAGE_HUB_PATH = "/shub/";
|
||||||
|
|
||||||
|
protected static final String URL_KEY = "url";
|
||||||
|
|
||||||
|
private static final String RESOURCES_KEY = "resources";
|
||||||
|
private static final String PACKAGE_ID_KEY = "package_id";
|
||||||
|
private static final String MIME_TYPE_KEY = "mimetype";
|
||||||
|
private static final String REVISION_ID_KEY = "revision_id";
|
||||||
|
|
||||||
|
private static final String TEMP = "TEMP_";
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
String context = ContextUtility.getCurrentContext();
|
||||||
|
if(context.startsWith("/gcube")) {
|
||||||
|
URI_RESOLVER_STORAGE_HUB_HOST = URI_RESOLVER_STORAGE_HUB_HOST_DEV;
|
||||||
|
} else {
|
||||||
|
URI_RESOLVER_STORAGE_HUB_HOST = URI_RESOLVER_STORAGE_HUB_HOST_PROD;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/* TODO END Code to be Removed */
|
||||||
|
|
||||||
|
protected String itemID;
|
||||||
|
|
||||||
|
public String getItemID() {
|
||||||
|
return itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String resourceID;
|
||||||
|
|
||||||
|
protected Boolean persisted;
|
||||||
|
protected URL persistedURL;
|
||||||
|
|
||||||
|
protected String mimeType;
|
||||||
|
|
||||||
|
protected JsonNode previousRepresentation;
|
||||||
|
|
||||||
|
protected StorageHubManagement storageHubManagement;
|
||||||
|
|
||||||
|
public URL getPersistedURL() {
|
||||||
|
return persistedURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String extractResourceID(JsonNode jsonNode) {
|
||||||
|
String resourceID = null;
|
||||||
|
if(jsonNode.has(ID_KEY)) {
|
||||||
|
resourceID = jsonNode.get(ID_KEY).asText();
|
||||||
|
}
|
||||||
|
return resourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResourceID() {
|
||||||
|
if(resourceID==null && previousRepresentation!=null) {
|
||||||
|
resourceID = CKANResource.extractResourceID(previousRepresentation);
|
||||||
|
}
|
||||||
|
return resourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceID(String resourceID) {
|
||||||
|
this.resourceID = resourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPreviousRepresentation(JsonNode jsonNode) {
|
||||||
|
previousRepresentation = jsonNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode getPreviousRepresentation() {
|
||||||
|
if(previousRepresentation==null && resourceID!=null) {
|
||||||
|
super.read();
|
||||||
|
validate(result);
|
||||||
|
previousRepresentation = result;
|
||||||
|
}
|
||||||
|
return previousRepresentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CKANResource(String itemID) {
|
||||||
|
super();
|
||||||
|
this.itemID = itemID;
|
||||||
|
CREATE = RESOURCE_CREATE;
|
||||||
|
READ = RESOURCE_SHOW;
|
||||||
|
UPDATE = RESOURCE_UPDATE;
|
||||||
|
PATCH = RESOURCE_PATCH;
|
||||||
|
DELETE = RESOURCE_DELETE;
|
||||||
|
PURGE = null;
|
||||||
|
persisted = null;
|
||||||
|
previousRepresentation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(itemID);
|
||||||
|
String itemJson = ckanPackage.read();
|
||||||
|
JsonNode item = getAsJsonNode(itemJson);
|
||||||
|
JsonNode resources = item.get(RESOURCES_KEY);
|
||||||
|
return getAsString(resources);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ObjectNode persistStorageFile(ObjectNode objectNode) {
|
||||||
|
|
||||||
|
if(objectNode.has(URL_KEY)) {
|
||||||
|
String urlString = objectNode.get(URL_KEY).asText();
|
||||||
|
|
||||||
|
URL url;
|
||||||
|
try {
|
||||||
|
url = new URL(urlString);
|
||||||
|
} catch(MalformedURLException e) {
|
||||||
|
throw new BadRequestException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
url = copyStorageResource(url);
|
||||||
|
|
||||||
|
if(mimeType!=null) {
|
||||||
|
objectNode.put(MIME_TYPE_KEY, mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectNode.put(URL_KEY, url.toString());
|
||||||
|
return objectNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
String error = String.format("The content must contains the %s property", URL_KEY);
|
||||||
|
throw new BadRequestException(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ObjectNode validate(String json) throws MalformedURLException {
|
||||||
|
JsonNode jsonNode = getAsJsonNode(json);
|
||||||
|
return validate(jsonNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ObjectNode validate(JsonNode jsonNode) {
|
||||||
|
|
||||||
|
ObjectNode objectNode = (ObjectNode) jsonNode;
|
||||||
|
|
||||||
|
if(objectNode.has(PACKAGE_ID_KEY)) {
|
||||||
|
String packageId = objectNode.get(PACKAGE_ID_KEY).asText();
|
||||||
|
if(packageId.compareTo(itemID) != 0) {
|
||||||
|
String error = String.format(
|
||||||
|
"Item ID %s does not match %s which is the value of %s contained in the representation.",
|
||||||
|
itemID, packageId, PACKAGE_ID_KEY);
|
||||||
|
throw new BadRequestException(error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
objectNode.put(PACKAGE_ID_KEY, itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(objectNode.has(ID_KEY)) {
|
||||||
|
String gotId = objectNode.get(ID_KEY).asText();
|
||||||
|
if(resourceID == null) {
|
||||||
|
resourceID = gotId;
|
||||||
|
} else {
|
||||||
|
if(resourceID.compareTo(gotId) != 0) {
|
||||||
|
String error = String.format(
|
||||||
|
"Resource ID %s does not match %s which is the value of %s contained in the representation.",
|
||||||
|
resourceID, gotId, ID_KEY);
|
||||||
|
throw new BadRequestException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resourceID = TEMP + UUID.randomUUID().toString();
|
||||||
|
logger.trace(
|
||||||
|
"The id of the resource with name {} for package {} has not been provided. It has been generated : {}",
|
||||||
|
name, itemID, resourceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return objectNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URL getFinalURL(String url) {
|
||||||
|
try {
|
||||||
|
URL urlURL = new URL(url);
|
||||||
|
return getFinalURL(urlURL);
|
||||||
|
} catch(MalformedURLException e) {
|
||||||
|
throw new BadRequestException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URL getFinalURL(URL url) {
|
||||||
|
HTTPCall httpCall = new HTTPCall(url.toString());
|
||||||
|
httpCall.setgCubeTargetService(false);
|
||||||
|
URL finalURL = httpCall.getFinalURL(url);
|
||||||
|
return finalURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isStorageFile(URL url) {
|
||||||
|
if(url.getHost().compareTo(URI_RESOLVER_STORAGE_HUB_HOST) == 0) {
|
||||||
|
if(url.getPath().startsWith(URI_RESOLVER_STORAGE_HUB_PATH)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the URl is a workspace URL so that is has to copy the resource to guarantee
|
||||||
|
* the resource remain persistent
|
||||||
|
* @param url the URL to check
|
||||||
|
* @return the public URL of the copied resource if any. It return the original URL otherwise
|
||||||
|
*/
|
||||||
|
protected URL copyStorageResource(URL url) {
|
||||||
|
persistedURL = getFinalURL(url);
|
||||||
|
if(isStorageFile(persistedURL)) {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
storageHubManagement = new StorageHubManagement();
|
||||||
|
persistedURL = storageHubManagement.ensureResourcePersistence(persistedURL, itemID, resourceID, name);
|
||||||
|
mimeType = storageHubManagement.getMimeType();
|
||||||
|
persisted = true;
|
||||||
|
applicationMode.end();
|
||||||
|
}
|
||||||
|
return persistedURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteStorageResource(URL url) {
|
||||||
|
persistedURL = getFinalURL(url);
|
||||||
|
if(isStorageFile(persistedURL)) {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
storageHubManagement = new StorageHubManagement();
|
||||||
|
storageHubManagement.deleteResourcePersistence(persistedURL, itemID);
|
||||||
|
applicationMode.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPersisted() {
|
||||||
|
if(persisted == null) {
|
||||||
|
persistedURL = getFinalURL(persistedURL);
|
||||||
|
if(isStorageFile(persistedURL)) {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
storageHubManagement = new StorageHubManagement();
|
||||||
|
persisted = storageHubManagement.isItemPersistedFile(persistedURL, itemID);
|
||||||
|
applicationMode.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return persisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String create(JsonNode jsonNode) {
|
||||||
|
try {
|
||||||
|
ObjectNode objectNode = validate(jsonNode);
|
||||||
|
objectNode = persistStorageFile(objectNode);
|
||||||
|
String ret = super.create(getAsString(objectNode));
|
||||||
|
String gotResourceID = result.get(ID_KEY).asText();
|
||||||
|
if(gotResourceID.compareTo(resourceID)!=0) {
|
||||||
|
resourceID = gotResourceID;
|
||||||
|
String revisionID = result.get(REVISION_ID_KEY).asText();
|
||||||
|
storageHubManagement.renameFile(resourceID, revisionID);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String create(String json) {
|
||||||
|
JsonNode jsonNode = getAsJsonNode(json);
|
||||||
|
return create(jsonNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String read() {
|
||||||
|
return sendGetRequest(READ, getMapWithID(resourceID));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String update(JsonNode jsonNode) {
|
||||||
|
ObjectNode resourceNode = (ObjectNode) jsonNode;
|
||||||
|
// This cannot be moved outside otherwise we don't
|
||||||
|
resourceNode = validate(resourceNode);
|
||||||
|
|
||||||
|
getPreviousRepresentation();
|
||||||
|
|
||||||
|
String oldURL = previousRepresentation.get(CKANResource.URL_KEY).asText();
|
||||||
|
String newURL = resourceNode.get(CKANResource.URL_KEY).asText();
|
||||||
|
if(oldURL.compareTo(newURL)==0) {
|
||||||
|
logger.trace("The URL of the resource with id {} was not changed", resourceID);
|
||||||
|
}else {
|
||||||
|
logger.trace("The URL of resource with id {} has been changed the old URL was {}, the new URL is {}", resourceID, oldURL, newURL);
|
||||||
|
resourceNode = persistStorageFile(resourceNode);
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
URL urlOLD = new URL(oldURL);
|
||||||
|
deleteStorageResource(urlOLD);
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.error("Unable to remove old file at URL {}", oldURL);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
String ret = super.update(getAsString(resourceNode));
|
||||||
|
String revisionID = result.get(REVISION_ID_KEY).asText();
|
||||||
|
storageHubManagement.addRevisionID(resourceID, revisionID);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String update(String json) {
|
||||||
|
JsonNode jsonNode = getAsJsonNode(json);
|
||||||
|
return update(jsonNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String patch(String json) {
|
||||||
|
String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(),
|
||||||
|
PUT.class.getSimpleName(), DELETE.class.getSimpleName()};
|
||||||
|
throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
try {
|
||||||
|
deleteFile();
|
||||||
|
super.delete();
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new WebApplicationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void purge() {
|
||||||
|
String[] moreAllowed = new String[] {HEAD.class.getSimpleName(), GET.class.getSimpleName(),
|
||||||
|
PUT.class.getSimpleName(), DELETE.class.getSimpleName()};
|
||||||
|
throw new NotAllowedException(OPTIONS.class.getSimpleName(), moreAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode createOrUpdate(JsonNode jsonNode) {
|
||||||
|
ObjectNode resourceNode = (ObjectNode) jsonNode;
|
||||||
|
if(resourceNode.has(ID_KEY)) {
|
||||||
|
update(resourceNode);
|
||||||
|
}else {
|
||||||
|
create(resourceNode);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteFile() {
|
||||||
|
try {
|
||||||
|
getPreviousRepresentation();
|
||||||
|
URL url = new URL(previousRepresentation.get(URL_KEY).asText());
|
||||||
|
deleteStorageResource(url);
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Unable to delete resource {}", previousRepresentation!=null ? getAsString(previousRepresentation) : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rollback() {
|
||||||
|
if(previousRepresentation!=null) {
|
||||||
|
update(previousRepresentation);
|
||||||
|
}else {
|
||||||
|
delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.utils.RandomString;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANUser extends CKAN {
|
||||||
|
|
||||||
|
/* User Paths */
|
||||||
|
// see https://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_list
|
||||||
|
public static final String USER_LIST = CKAN.CKAN_API_PATH + "user_list";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.create.user_create
|
||||||
|
public static final String USER_CREATE = CKAN.CKAN_API_PATH + "user_create";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.get.user_show
|
||||||
|
public static final String USER_SHOW = CKAN.CKAN_API_PATH + "user_show";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.update.user_update
|
||||||
|
public static final String USER_UPDATE = CKAN.CKAN_API_PATH + "user_update";
|
||||||
|
// see http://docs.ckan.org/en/latest/api/#ckan.logic.action.delete.user_delete
|
||||||
|
public static final String USER_DELETE = CKAN.CKAN_API_PATH + "user_delete";
|
||||||
|
|
||||||
|
|
||||||
|
public CKANUser() {
|
||||||
|
super();
|
||||||
|
LIST = USER_LIST;
|
||||||
|
CREATE = USER_CREATE;
|
||||||
|
READ = USER_SHOW;
|
||||||
|
UPDATE = USER_UPDATE;
|
||||||
|
PATCH = null;
|
||||||
|
DELETE = USER_DELETE;
|
||||||
|
PURGE = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String NAME = "name";
|
||||||
|
public static final String EMAIL = "email";
|
||||||
|
public static final String PASSWORD = "password";
|
||||||
|
|
||||||
|
public String create() {
|
||||||
|
RandomString randomString = new RandomString(12);
|
||||||
|
ObjectNode objectNode = mapper.createObjectNode();
|
||||||
|
objectNode.put(NAME, name);
|
||||||
|
objectNode.put(EMAIL, name+"@gcube.ckan.org");
|
||||||
|
objectNode.put(PASSWORD, randomString.nextString());
|
||||||
|
return create(getAsString(objectNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(boolean purge) {
|
||||||
|
this.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueFactory;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogueRunningCluster;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.utils.CatalogueUtilMethods;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANUtility {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CKANUtility.class);
|
||||||
|
|
||||||
|
public static final String MEMBER_ROLE = "member";
|
||||||
|
private static final String API_KEY = "apikey";
|
||||||
|
|
||||||
|
public static DataCatalogue getCatalogue() throws Exception {
|
||||||
|
String context = ContextUtility.getCurrentContext();
|
||||||
|
logger.debug("Discovering ckan instance in context {}", context);
|
||||||
|
return DataCatalogueFactory.getFactory().getUtilsPerScope(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSysAdminAPI() {
|
||||||
|
try {
|
||||||
|
DataCatalogueRunningCluster catalogueRunningInstance = new DataCatalogueRunningCluster(
|
||||||
|
ContextUtility.getCurrentContext());
|
||||||
|
return catalogueRunningInstance.getSysAdminToken();
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getCKANUsername(String username) {
|
||||||
|
String ckanUsername = CatalogueUtilMethods.fromUsernameToCKanUsername(username);
|
||||||
|
return ckanUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getCKANUsername() {
|
||||||
|
return getCKANUsername(ContextUtility.getUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JsonNode getCKANUser() {
|
||||||
|
return createCKANUser(getCKANUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static JsonNode createCKANUser(String ckanUsername) {
|
||||||
|
CKANUser ckanUser = new CKANUser();
|
||||||
|
ckanUser.setApiKey(getSysAdminAPI());
|
||||||
|
try {
|
||||||
|
ckanUser.setName(ckanUsername);
|
||||||
|
ckanUser.read();
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
if(e.getResponse().getStatusInfo() == Status.NOT_FOUND) {
|
||||||
|
ckanUser.setName(ckanUsername);
|
||||||
|
ckanUser.create();
|
||||||
|
}else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JsonNode jsonNode = ckanUser.getJsonNodeResult();
|
||||||
|
addUserToOrganization(ckanUsername, MEMBER_ROLE, false);
|
||||||
|
return jsonNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void addUserToOrganization(String ckanUsername, String role, boolean force) {
|
||||||
|
CKANOrganization ckanOrganization = new CKANOrganization();
|
||||||
|
ckanOrganization.setApiKey(getSysAdminAPI());
|
||||||
|
String organizationName = CKANOrganization.getCKANOrganizationName();
|
||||||
|
ckanOrganization.setName(organizationName);
|
||||||
|
ckanOrganization.addUserToOrganisation(ContextUtility.getUsername(), role, force);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getApiKey() throws Exception {
|
||||||
|
String ckanUsername = getCKANUsername();
|
||||||
|
return getApiKey(ckanUsername);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getApiKey(String ckanUsername) {
|
||||||
|
try {
|
||||||
|
String apiKey = getCatalogue().getApiKeyFromUsername(ckanUsername);
|
||||||
|
if(apiKey == null) {
|
||||||
|
JsonNode jsonNode = createCKANUser(ckanUsername);
|
||||||
|
apiKey = jsonNode.get(API_KEY).asText();
|
||||||
|
}
|
||||||
|
return apiKey;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class BaseREST {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Context
|
||||||
|
private UriInfo uriInfo;
|
||||||
|
|
||||||
|
public static final String GROUPS = "groups";
|
||||||
|
public static final String ITEMS = "items";
|
||||||
|
public static final String LICENSES = "licenses";
|
||||||
|
public static final String NAMESPACES = "namespaces";
|
||||||
|
public static final String ORGANIZATIONS = "organizations";
|
||||||
|
public static final String PROFILES = "profiles";
|
||||||
|
public static final String RESOURCES = "resources";
|
||||||
|
public static final String USERS = "users";
|
||||||
|
|
||||||
|
public static final String PURGE_QUERY_PARAMETER = "purge";
|
||||||
|
|
||||||
|
public static final String APPLICATION_JSON_CHARSET_UTF_8 = MediaType.APPLICATION_JSON + ";charset=UTF-8";
|
||||||
|
|
||||||
|
protected static final String LOCATION_HEADER = "Location";
|
||||||
|
|
||||||
|
protected void setCalledMethod(String method) {
|
||||||
|
CalledMethodProvider.instance.set(method);
|
||||||
|
logger.info("{}", uriInfo.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResponseBuilder addLocation(ResponseBuilder responseBuilder, String id) {
|
||||||
|
return responseBuilder.header(LOCATION_HEADER,
|
||||||
|
String.format("%s/%s", uriInfo.getAbsolutePath().toString(), id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.annotation.PATCH;
|
||||||
|
import org.gcube.gcat.annotation.PURGE;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.GROUPS)
|
||||||
|
public class Group extends REST<CKANGroup> {
|
||||||
|
|
||||||
|
protected static final String GROUP_ID_PARAMETER = "GROUP_ID";
|
||||||
|
|
||||||
|
public Group() {
|
||||||
|
super(BaseREST.GROUPS, GROUP_ID_PARAMETER, CKANGroup.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response create(String json) {
|
||||||
|
return super.create(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + GROUP_ID_PARAMETER + "}")
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String read(@PathParam(GROUP_ID_PARAMETER) String id) {
|
||||||
|
return super.read(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/{" + GROUP_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String update(@PathParam(GROUP_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.update(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("/{" + GROUP_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String patch(@PathParam(GROUP_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.patch(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{" + GROUP_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response delete(@PathParam(GROUP_ID_PARAMETER) String id,
|
||||||
|
@QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) {
|
||||||
|
return super.delete(id, purge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PURGE
|
||||||
|
@Path("/{" + GROUP_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response purge(@PathParam(GROUP_ID_PARAMETER) String id) {
|
||||||
|
return delete(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.annotation.PURGE;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANPackage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.ITEMS)
|
||||||
|
public class Item extends REST<CKANPackage> {
|
||||||
|
|
||||||
|
public static final String ITEM_ID_PARAMETER = "ITEM_ID";
|
||||||
|
|
||||||
|
public Item() {
|
||||||
|
super(BaseREST.ITEMS, ITEM_ID_PARAMETER, CKANPackage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response create(String json) {
|
||||||
|
return super.create(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + ITEM_ID_PARAMETER + "}")
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String read(@PathParam(ITEM_ID_PARAMETER) String id) {
|
||||||
|
return super.read(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/{" + ITEM_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String update(@PathParam(ITEM_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.update(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@PATCH
|
||||||
|
@Path("/{" + ITEM_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String patch(@PathParam(ITEM_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.patch(id, json);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{" + ITEM_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response delete(@PathParam(ITEM_ID_PARAMETER) String id,
|
||||||
|
@QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) {
|
||||||
|
return super.delete(id, purge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PURGE
|
||||||
|
@Path("/{" + ITEM_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response purge(@PathParam(ITEM_ID_PARAMETER) String id) {
|
||||||
|
return super.purge(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANLicense;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.LICENSES)
|
||||||
|
public class License extends REST<CKANLicense> {
|
||||||
|
|
||||||
|
public License() {
|
||||||
|
super(BaseREST.LICENSES, null, CKANLicense.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
|
||||||
|
import org.gcube.datacatalogue.metadatadiscovery.bean.jaxb.NamespaceCategory;
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.NAMESPACES)
|
||||||
|
public class Namespace extends BaseREST {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the categories.
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static List<NamespaceCategory> getNamespaceCategories() throws Exception {
|
||||||
|
DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader();
|
||||||
|
return reader.getListOfNamespaceCategories();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String list() {
|
||||||
|
setCalledMethod("GET /" + BaseREST.NAMESPACES);
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
ArrayNode arrayNode = mapper.createArrayNode();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<NamespaceCategory> namespaces = Namespace.getNamespaceCategories();
|
||||||
|
for(NamespaceCategory namespaceCategory : namespaces) {
|
||||||
|
ObjectNode namespace = mapper.createObjectNode();
|
||||||
|
namespace.put("id", namespaceCategory.getId());
|
||||||
|
namespace.put("title", namespaceCategory.getTitle());
|
||||||
|
namespace.put("name", namespaceCategory.getNamespaceCategoryQName());
|
||||||
|
namespace.put("description", namespaceCategory.getDescription());
|
||||||
|
arrayNode.add(namespace);
|
||||||
|
}
|
||||||
|
return mapper.writeValueAsString(arrayNode);
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.annotation.PATCH;
|
||||||
|
import org.gcube.gcat.annotation.PURGE;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANOrganization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.ORGANIZATIONS)
|
||||||
|
public class Organization extends REST<CKANOrganization> {
|
||||||
|
|
||||||
|
public static final String ORGANIZATION_ID_PARAMETER = "ORGANIZATION_ID";
|
||||||
|
|
||||||
|
public Organization() {
|
||||||
|
super(BaseREST.ORGANIZATIONS, ORGANIZATION_ID_PARAMETER, CKANOrganization.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response create(String json) {
|
||||||
|
return super.create(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + ORGANIZATION_ID_PARAMETER + "}")
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String read(@PathParam(ORGANIZATION_ID_PARAMETER) String id) {
|
||||||
|
return super.read(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/{" + ORGANIZATION_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String update(@PathParam(ORGANIZATION_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.update(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("/{" + ORGANIZATION_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String patch(@PathParam(ORGANIZATION_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.patch(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{" + ORGANIZATION_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response delete(@PathParam(ORGANIZATION_ID_PARAMETER) String id,
|
||||||
|
@QueryParam(BaseREST.PURGE_QUERY_PARAMETER) @DefaultValue("false") Boolean purge) {
|
||||||
|
return super.delete(id, purge);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PURGE
|
||||||
|
@Path("/{" + ORGANIZATION_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public Response purge(@PathParam(ORGANIZATION_ID_PARAMETER) String id) {
|
||||||
|
return super.purge(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.HeaderParam;
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
import org.gcube.datacatalogue.metadatadiscovery.DataCalogueMetadataFormatReader;
|
||||||
|
import org.gcube.datacatalogue.metadatadiscovery.bean.MetadataProfile;
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.oldutils.CachesManager;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.XML;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.PROFILES)
|
||||||
|
public class Profile extends BaseREST {
|
||||||
|
|
||||||
|
public static final String PROFILE_NAME_PARAMETER = "PROFILE_NAME";
|
||||||
|
|
||||||
|
public static DataCalogueMetadataFormatReader getDataCalogueMetadataFormatReader() throws Exception {
|
||||||
|
Cache<String,DataCalogueMetadataFormatReader> readerCache = CachesManager.getReaderCache();
|
||||||
|
String context = ScopeProvider.instance.get();
|
||||||
|
DataCalogueMetadataFormatReader reader;
|
||||||
|
if(readerCache.containsKey(context))
|
||||||
|
reader = (DataCalogueMetadataFormatReader) readerCache.get(context);
|
||||||
|
else {
|
||||||
|
reader = new DataCalogueMetadataFormatReader();
|
||||||
|
readerCache.put(context, reader);
|
||||||
|
}
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of the metadata profiles in a given context
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static List<String> getProfilesNames() throws Exception {
|
||||||
|
|
||||||
|
DataCalogueMetadataFormatReader reader = getDataCalogueMetadataFormatReader();
|
||||||
|
|
||||||
|
List<String> toReturn = new ArrayList<String>();
|
||||||
|
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 {
|
||||||
|
|
||||||
|
DataCalogueMetadataFormatReader reader = Profile.getDataCalogueMetadataFormatReader();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String list() {
|
||||||
|
setCalledMethod("GET /" + BaseREST.PROFILES);
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
ArrayNode arrayNode = mapper.createArrayNode();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<String> names = getProfilesNames();
|
||||||
|
for(String name : names) {
|
||||||
|
arrayNode.add(name);
|
||||||
|
}
|
||||||
|
return mapper.writeValueAsString(arrayNode);
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + PROFILE_NAME_PARAMETER + "}")
|
||||||
|
@Produces({MediaType.APPLICATION_XML, ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8})
|
||||||
|
public String read(@PathParam(PROFILE_NAME_PARAMETER) String id,
|
||||||
|
@DefaultValue(MediaType.APPLICATION_JSON) @HeaderParam("Accept") String accept) {
|
||||||
|
setCalledMethod("GET /" + BaseREST.PROFILES + "/{" + PROFILE_NAME_PARAMETER + "}");
|
||||||
|
try {
|
||||||
|
String profile = Profile.getProfileSource(id);
|
||||||
|
if(accept.startsWith(MediaType.APPLICATION_XML)){
|
||||||
|
return profile;
|
||||||
|
}else {
|
||||||
|
JSONObject xmlJSONObj = XML.toJSONObject(profile);
|
||||||
|
String jsonString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.ResponseBuilder;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKAN;
|
||||||
|
|
||||||
|
public class REST<C extends CKAN> extends BaseREST {
|
||||||
|
|
||||||
|
protected final String COLLECTION_PARAMETER;
|
||||||
|
protected final String ID_PARAMETER;
|
||||||
|
protected final Class<C> reference;
|
||||||
|
|
||||||
|
public REST(String collection_name, String id_name, Class<C> reference) {
|
||||||
|
this.COLLECTION_PARAMETER = collection_name;
|
||||||
|
this.ID_PARAMETER = id_name;
|
||||||
|
this.reference = reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected C getInstance() {
|
||||||
|
try {
|
||||||
|
C ckan = reference.newInstance();
|
||||||
|
return ckan;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String list() {
|
||||||
|
setCalledMethod("GET /" + COLLECTION_PARAMETER);
|
||||||
|
C ckan = getInstance();
|
||||||
|
return ckan.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response create(String json) {
|
||||||
|
setCalledMethod("POST /" + COLLECTION_PARAMETER);
|
||||||
|
C ckan = getInstance();
|
||||||
|
String ret = ckan.create(json);
|
||||||
|
|
||||||
|
ResponseBuilder responseBuilder = Response.status(Status.CREATED).entity(ret);
|
||||||
|
responseBuilder = addLocation(responseBuilder, ckan.getName());
|
||||||
|
return responseBuilder.type(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String read(String id) {
|
||||||
|
setCalledMethod("GET /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}");
|
||||||
|
C ckan = getInstance();
|
||||||
|
ckan.setName(id);
|
||||||
|
return ckan.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String update(String id, String json) {
|
||||||
|
setCalledMethod("PUT /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}");
|
||||||
|
C ckan = getInstance();
|
||||||
|
ckan.setName(id);
|
||||||
|
return ckan.update(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String patch(String id, String json) {
|
||||||
|
setCalledMethod("PATCH /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}");
|
||||||
|
C ckan = getInstance();
|
||||||
|
ckan.setName(id);
|
||||||
|
return ckan.patch(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response delete(String id, Boolean purge) {
|
||||||
|
if(purge) {
|
||||||
|
setCalledMethod("PURGE /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}");
|
||||||
|
} else {
|
||||||
|
setCalledMethod("DELETE /" + COLLECTION_PARAMETER + "/{" + ID_PARAMETER + "}");
|
||||||
|
}
|
||||||
|
C ckan = getInstance();
|
||||||
|
ckan.setName(id);
|
||||||
|
ckan.delete(purge);
|
||||||
|
return Response.status(Status.NO_CONTENT).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response purge(String id) {
|
||||||
|
return delete(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.annotation.PATCH;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.ITEMS + "/{" + Resource.ITEM_ID_PARAMETER + "}/" + BaseREST.RESOURCES)
|
||||||
|
public class Resource extends BaseREST {
|
||||||
|
|
||||||
|
protected static final String ITEM_ID_PARAMETER = "ITEM_ID";
|
||||||
|
protected static final String RESOURCE_ID_PARAMETER = "RESOURCE_ID";
|
||||||
|
|
||||||
|
protected static final String COLLECTION = BaseREST.ITEMS + "/{" + Resource.ITEM_ID_PARAMETER + "}/" + BaseREST.RESOURCES;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String list(@PathParam(ITEM_ID_PARAMETER) String itemID) {
|
||||||
|
setCalledMethod("GET /" + COLLECTION);
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setName(itemID);
|
||||||
|
return ckanResource.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String create(@PathParam(ITEM_ID_PARAMETER) String itemID, String json) {
|
||||||
|
setCalledMethod("POST /" + COLLECTION);
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
return ckanResource.create(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + RESOURCE_ID_PARAMETER + "}")
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String read(@PathParam(ITEM_ID_PARAMETER) String itemID,
|
||||||
|
@PathParam(RESOURCE_ID_PARAMETER) String resourceID) {
|
||||||
|
setCalledMethod("GET /" + COLLECTION + "/{" + RESOURCE_ID_PARAMETER + "}");
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setName(resourceID);
|
||||||
|
return ckanResource.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/{" + RESOURCE_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String update(@PathParam(ITEM_ID_PARAMETER) String itemID,
|
||||||
|
@PathParam(RESOURCE_ID_PARAMETER) String resourceID, String json) {
|
||||||
|
setCalledMethod("PUT /" + COLLECTION + "/{" + RESOURCE_ID_PARAMETER + "}");
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setName(resourceID);
|
||||||
|
return ckanResource.update(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("/{" + RESOURCE_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public String patch(@PathParam(ITEM_ID_PARAMETER) String itemID,
|
||||||
|
@PathParam(RESOURCE_ID_PARAMETER) String resourceID, String json) {
|
||||||
|
setCalledMethod("PATCH /" + COLLECTION + "/{" + RESOURCE_ID_PARAMETER + "}");
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setName(resourceID);
|
||||||
|
return ckanResource.patch(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{" + RESOURCE_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public void delete(@PathParam(ITEM_ID_PARAMETER) String itemID,
|
||||||
|
@PathParam(RESOURCE_ID_PARAMETER) String resourceID) {
|
||||||
|
setCalledMethod("DELETE /" + COLLECTION + "/{" + RESOURCE_ID_PARAMETER + "}");
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.setName(resourceID);
|
||||||
|
ckanResource.delete(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
import javax.ws.rs.ext.ExceptionMapper;
|
||||||
|
import javax.ws.rs.ext.Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Provider
|
||||||
|
public class ScienceCatalogueExceptionMapper implements ExceptionMapper<Exception> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response toResponse(Exception exception) {
|
||||||
|
|
||||||
|
Status status = Status.INTERNAL_SERVER_ERROR;
|
||||||
|
String exceptionMessage = exception.getMessage();
|
||||||
|
MediaType mediaType = MediaType.TEXT_PLAIN_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
if(WebApplicationException.class.isAssignableFrom(exception.getClass())) {
|
||||||
|
Response gotResponse = ((WebApplicationException) exception).getResponse();
|
||||||
|
status = Status.fromStatusCode(gotResponse.getStatusInfo().getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.status(status).entity(exceptionMessage).type(mediaType).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ResourceInitializer;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
@Path(BaseREST.USERS)
|
||||||
|
public class User extends REST<CKANUser> {
|
||||||
|
|
||||||
|
protected static final String USER_ID_PARAMETER = "USER_ID";
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
super(BaseREST.USERS, USER_ID_PARAMETER, CKANUser.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String list() {
|
||||||
|
return super.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public Response create(String json) {
|
||||||
|
return super.create(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{" + USER_ID_PARAMETER + "}")
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String read(@PathParam(USER_ID_PARAMETER) String id) {
|
||||||
|
return super.read(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/{" + USER_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Override
|
||||||
|
public String update(@PathParam(USER_ID_PARAMETER) String id, String json) {
|
||||||
|
return super.update(id, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@Path("/{" + USER_ID_PARAMETER + "}")
|
||||||
|
@Consumes(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
@Produces(ResourceInitializer.APPLICATION_JSON_CHARSET_UTF_8)
|
||||||
|
public Response delete(@PathParam(USER_ID_PARAMETER) String id) {
|
||||||
|
return super.delete(id, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.gcube.gcat.social;
|
||||||
|
|
||||||
|
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.gcat.utils.ContextUtility;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover the Social Networking Service in the Infrastructure.
|
||||||
|
* @author Costantino Perciante (ISTI - CNR)
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class GcoreEndpointReaderSNL {
|
||||||
|
|
||||||
|
private static final String RESOURCE = "jersey-servlet";
|
||||||
|
private static final String SERVICE_NAME = "SocialNetworking";
|
||||||
|
private static final String SERVICE_CLASSE = "Portal";
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(GcoreEndpointReaderSNL.class);
|
||||||
|
private String serviceBasePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discover the gcore endpoint for the social networking service.
|
||||||
|
* @throws Exception the exception
|
||||||
|
*/
|
||||||
|
public GcoreEndpointReaderSNL() throws Exception {
|
||||||
|
|
||||||
|
try {
|
||||||
|
SimpleQuery query = queryFor(GCoreEndpoint.class);
|
||||||
|
query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'", SERVICE_CLASSE));
|
||||||
|
query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'");
|
||||||
|
query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'", SERVICE_NAME));
|
||||||
|
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 SERVICE_NAME: " + SERVICE_NAME
|
||||||
|
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtility.getCurrentContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.serviceBasePath = endpoints.get(0);
|
||||||
|
|
||||||
|
if(serviceBasePath == null)
|
||||||
|
throw new Exception("Endpoint:" + RESOURCE + ", is null for SERVICE_NAME: " + SERVICE_NAME
|
||||||
|
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtility.getCurrentContext());
|
||||||
|
|
||||||
|
serviceBasePath = serviceBasePath.endsWith("/") ? serviceBasePath : serviceBasePath + "/";
|
||||||
|
|
||||||
|
} catch(Exception e) {
|
||||||
|
String error = "An error occurred during GCoreEndpoint discovery, SERVICE_NAME: " + SERVICE_NAME
|
||||||
|
+ ", SERVICE_CLASSE: " + SERVICE_CLASSE + ", in scope: " + ContextUtility.getCurrentContext() + ".";
|
||||||
|
logger.error(error, e);
|
||||||
|
throw new Exception(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the base path of the service
|
||||||
|
*/
|
||||||
|
public String getServiceBasePath() {
|
||||||
|
return serviceBasePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
package org.gcube.gcat.social;
|
||||||
|
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.cache.Cache;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
|
||||||
|
import org.gcube.gcat.oldutils.CachesManager;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKAN;
|
||||||
|
import org.gcube.gcat.utils.ApplicationMode;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class SocialService extends Thread {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SocialService.class);
|
||||||
|
|
||||||
|
public static final String ITEM_URL = "Item URL";
|
||||||
|
|
||||||
|
// https://wiki.gcube-system.org/gcube/Social_Networking_Service#Write_application_post_2
|
||||||
|
protected static final String SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH = "/2/posts/write-post-app";
|
||||||
|
// https://wiki.gcube-system.org/gcube/Social_Networking_Service
|
||||||
|
protected static final String SOCIAL_SERVICE_GET_USER_INFO_PATH = "2/users/get-profile";
|
||||||
|
|
||||||
|
// String.format(NOTIFICATION_MESSAGE, title, fullName, url)
|
||||||
|
protected static final String NOTIFICATION_MESSAGE = "Dear members,<br>The item '%s' has been just published by %s.<br>You can find it at: %s <br>";
|
||||||
|
|
||||||
|
protected static final String RESULT_KEY = "result";
|
||||||
|
protected static final String FULLNAME_IN_PROFILE_KEY = "fullname";
|
||||||
|
protected static final String SOCIAL_POST_TEXT_KEY = "text";
|
||||||
|
protected static final String SOCIAL_POST_ENABLE_NOTIFICATION_KEY = "enable_notification";
|
||||||
|
protected static final String SOCIAL_POST_RESPONSE_SUCCESS_KEY = "success";
|
||||||
|
protected static final String SOCIAL_POST_RESPONSE_MESSAGE_KEY = "message";
|
||||||
|
|
||||||
|
protected String id;
|
||||||
|
protected String url;
|
||||||
|
protected String title;
|
||||||
|
protected List<String> tags;
|
||||||
|
protected final GcoreEndpointReaderSNL socialService;
|
||||||
|
protected final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public SocialService() throws Exception {
|
||||||
|
super();
|
||||||
|
this.socialService = new GcoreEndpointReaderSNL();
|
||||||
|
this.objectMapper = new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocialService(String id, String url, List<String> tags, String title) throws Exception {
|
||||||
|
this();
|
||||||
|
this.id = id;
|
||||||
|
this.url = url;
|
||||||
|
this.tags = tags;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocialService(String id, String url, ArrayNode arrayNode, String title) throws Exception {
|
||||||
|
this();
|
||||||
|
this.id = id;
|
||||||
|
this.url = url;
|
||||||
|
|
||||||
|
this.tags = new ArrayList<>();
|
||||||
|
if(arrayNode != null && arrayNode.size() > 0) {
|
||||||
|
for(int i = 0; i < arrayNode.size(); i++) {
|
||||||
|
String tagName = arrayNode.get(i).get("display_name").asText();
|
||||||
|
tags.add(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the GET http request at this url, and return the result as string
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public JsonNode getGCubeUserProfile() throws Exception {
|
||||||
|
String username = ContextUtility.getUsername();
|
||||||
|
return getGCubeUserProfile(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode getGCubeUserProfile(String username) throws Exception {
|
||||||
|
Cache<String,JsonNode> userCache = CachesManager.getUserCache();
|
||||||
|
|
||||||
|
if(userCache.containsKey(username))
|
||||||
|
return userCache.get(username);
|
||||||
|
else {
|
||||||
|
String socialServiceBasePath = socialService.getServiceBasePath();
|
||||||
|
HTTPCall httpCall = new HTTPCall(socialServiceBasePath);
|
||||||
|
String response = httpCall.call(SOCIAL_SERVICE_GET_USER_INFO_PATH, HTTPMETHOD.GET, (Map<String,String>) null,
|
||||||
|
MediaType.APPLICATION_JSON);
|
||||||
|
JsonNode jsonNode = objectMapper.readTree(response);
|
||||||
|
userCache.put(username, jsonNode);
|
||||||
|
return jsonNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullName() throws Exception {
|
||||||
|
if(!ContextUtility.isApplication()) {
|
||||||
|
JsonNode jsonNode = getGCubeUserProfile();
|
||||||
|
JsonNode result = jsonNode.get(RESULT_KEY);
|
||||||
|
return result.get(FULLNAME_IN_PROFILE_KEY).asText();
|
||||||
|
} else {
|
||||||
|
return ContextUtility.getUsername();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
DataCatalogue dataCatalogue = CKAN.getCatalogue();
|
||||||
|
|
||||||
|
if(!dataCatalogue.isSocialPostEnabled()) {
|
||||||
|
logger.info("Social Post are disabled in the context {}", ContextUtility.getCurrentContext());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.info("Going to send Social Post about the Item {} available at {}", id, url);
|
||||||
|
|
||||||
|
boolean notifyUsers = dataCatalogue.isNotificationToUsersEnabled();
|
||||||
|
// write notification post
|
||||||
|
sendSocialPost(notifyUsers);
|
||||||
|
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Error while executing post creation actions", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendSocialPost(boolean notifyUsers) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
String fullName = getFullName();
|
||||||
|
|
||||||
|
String basePath = socialService.getServiceBasePath();
|
||||||
|
if(basePath == null) {
|
||||||
|
logger.info("Unable to write a post because there is no social networking service available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
basePath = basePath.endsWith("/") ? basePath : basePath + "/";
|
||||||
|
|
||||||
|
StringWriter messageWriter = new StringWriter();
|
||||||
|
messageWriter.append(String.format(NOTIFICATION_MESSAGE, title, fullName, url));
|
||||||
|
|
||||||
|
for(String tag : tags) {
|
||||||
|
tag = tag.trim();
|
||||||
|
tag = tag.replaceAll(" ", "_").replace("_+", "_");
|
||||||
|
if(tag.endsWith("_")) {
|
||||||
|
tag = tag.substring(0, tag.length() - 1);
|
||||||
|
}
|
||||||
|
messageWriter.append(" #");
|
||||||
|
messageWriter.append(tag);
|
||||||
|
}
|
||||||
|
String message = messageWriter.toString();
|
||||||
|
|
||||||
|
logger.debug("The post that is going to be written is {} " + message);
|
||||||
|
|
||||||
|
ObjectNode objectNode = objectMapper.createObjectNode();
|
||||||
|
objectNode.put(SOCIAL_POST_TEXT_KEY, message);
|
||||||
|
objectNode.put(SOCIAL_POST_ENABLE_NOTIFICATION_KEY, notifyUsers);
|
||||||
|
|
||||||
|
// Do not use ApplicationMode class here because is a thread and change the current token could impact
|
||||||
|
// on the other threads.
|
||||||
|
HTTPCall httpCall = new HTTPCall(basePath);
|
||||||
|
httpCall.setgCubeTargetService(false);
|
||||||
|
httpCall.addHeader(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY,
|
||||||
|
ApplicationMode.getCatalogueApplicationToken());
|
||||||
|
String response = httpCall.call(SOCIAL_SERVICE_WRITE_APPLICATION_POST_PATH, HTTPMETHOD.POST,
|
||||||
|
objectMapper.writeValueAsString(objectNode), MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
JsonNode jsonNode = objectMapper.readTree(response);
|
||||||
|
if(jsonNode.get(SOCIAL_POST_RESPONSE_SUCCESS_KEY).asBoolean()) {
|
||||||
|
logger.info("Post written : {}", message);
|
||||||
|
} else {
|
||||||
|
logger.info("Failed to write the post {}. Reason {}", message,
|
||||||
|
jsonNode.get(SOCIAL_POST_RESPONSE_MESSAGE_KEY).asText());
|
||||||
|
}
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Unable to send Social Post", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.client.Constants;
|
||||||
|
import org.gcube.common.authorization.library.AuthorizationEntry;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.authorization.library.provider.ClientInfo;
|
||||||
|
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.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class ApplicationMode {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ApplicationMode.class);
|
||||||
|
|
||||||
|
private static final String PROPERTY_FILENAME = "config.properties";
|
||||||
|
private static final String TOKEN_VARNAME = "TOKEN";
|
||||||
|
private static final String CATALOGUE_APPLICATION_TOKEN;
|
||||||
|
|
||||||
|
public static String getCatalogueApplicationToken() {
|
||||||
|
return CATALOGUE_APPLICATION_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
InputStream input = Constants.class.getClassLoader().getResourceAsStream(PROPERTY_FILENAME);
|
||||||
|
// load a properties file
|
||||||
|
properties.load(input);
|
||||||
|
CATALOGUE_APPLICATION_TOKEN = properties.getProperty(TOKEN_VARNAME);
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new WebApplicationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final String originalToken;
|
||||||
|
|
||||||
|
public ApplicationMode() {
|
||||||
|
String applicationtoken = SecurityTokenProvider.instance.get();
|
||||||
|
if(applicationtoken.compareTo(CATALOGUE_APPLICATION_TOKEN)!=0) {
|
||||||
|
this.originalToken = applicationtoken;
|
||||||
|
}else {
|
||||||
|
logger.warn("You are already in application Mode. Operation on this instance will not have any effect.");
|
||||||
|
this.originalToken = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setToken(String token) {
|
||||||
|
SecurityTokenProvider.instance.set(token);
|
||||||
|
ScopeProvider.instance.set(ContextUtility.getCurrentContext());
|
||||||
|
try {
|
||||||
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
||||||
|
ClientInfo clientInfo = authorizationEntry.getClientInfo();
|
||||||
|
logger.debug("User : {} - Type : {}", clientInfo.getId(), clientInfo.getType().name());
|
||||||
|
String qualifier = authorizationEntry.getQualifier();
|
||||||
|
Caller caller = new Caller(clientInfo, qualifier);
|
||||||
|
AuthorizationProvider.instance.set(caller);
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.error("Unable to set Caller");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void start() {
|
||||||
|
if(originalToken!=null) {
|
||||||
|
setToken(CATALOGUE_APPLICATION_TOKEN);
|
||||||
|
}else {
|
||||||
|
logger.warn("You are already in application Mode. start() does not provide any effect.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void end() {
|
||||||
|
if(originalToken!=null) {
|
||||||
|
setToken(originalToken);
|
||||||
|
}else {
|
||||||
|
logger.warn("You are already in application Mode. end() does not provide any effect.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String CATALOGUE_NAME = "ScienceCatalogue";
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.client.Constants;
|
||||||
|
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
|
||||||
|
import org.gcube.common.authorization.library.AuthorizationEntry;
|
||||||
|
import org.gcube.common.authorization.library.ClientType;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.authorization.library.provider.ClientInfo;
|
||||||
|
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.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class ContextUtility {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(ContextUtility.class);
|
||||||
|
|
||||||
|
public static void setContext(String token) throws ObjectNotFound, Exception{
|
||||||
|
SecurityTokenProvider.instance.set(token);
|
||||||
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
||||||
|
ClientInfo clientInfo = authorizationEntry.getClientInfo();
|
||||||
|
logger.debug("User : {} - Type : {}", clientInfo.getId(), clientInfo.getType().name());
|
||||||
|
String qualifier = authorizationEntry.getQualifier();
|
||||||
|
Caller caller = new Caller(clientInfo, qualifier);
|
||||||
|
AuthorizationProvider.instance.set(caller);
|
||||||
|
ScopeProvider.instance.set(getCurrentContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentContext() {
|
||||||
|
try {
|
||||||
|
String token = SecurityTokenProvider.instance.get();
|
||||||
|
return Constants.authorizationService().get(token).getContext();
|
||||||
|
}catch (Exception e) {
|
||||||
|
String context = ScopeProvider.instance.get();
|
||||||
|
if(context!=null) {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClientInfo getClientInfo() {
|
||||||
|
try {
|
||||||
|
Caller caller = AuthorizationProvider.instance.get();
|
||||||
|
if(caller!=null){
|
||||||
|
return caller.getClient();
|
||||||
|
}else{
|
||||||
|
String token = SecurityTokenProvider.instance.get();
|
||||||
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
||||||
|
return authorizationEntry.getClientInfo();
|
||||||
|
}
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String GET_USERNAME_ERROR = "Unable to retrieve user";
|
||||||
|
|
||||||
|
public static String getUsername() {
|
||||||
|
try {
|
||||||
|
return getClientInfo().getId();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(GET_USERNAME_ERROR);
|
||||||
|
throw new InternalServerErrorException(GET_USERNAME_ERROR, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isApplication() {
|
||||||
|
try {
|
||||||
|
ClientInfo clientInfo = getClientInfo();
|
||||||
|
return clientInfo.getType() == ClientType.EXTERNALSERVICE ;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,313 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||||
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class HTTPCall {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(HTTPCall.class);
|
||||||
|
|
||||||
|
protected static final String USER_AGENT_KEY = "User-Agent";
|
||||||
|
protected static final String USER_AGENT_NAME = Constants.CATALOGUE_NAME;
|
||||||
|
|
||||||
|
public enum HTTPMETHOD {
|
||||||
|
HEAD, GET, POST, PUT, DELETE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String PATH_SEPARATOR = "/";
|
||||||
|
public static final String PARAM_STARTER = "?";
|
||||||
|
public static final String PARAM_EQUALS = "=";
|
||||||
|
public static final String PARAM_SEPARATOR = "&";
|
||||||
|
public static final String UTF8 = "UTF-8";
|
||||||
|
|
||||||
|
protected final String address;
|
||||||
|
protected final String userAgent;
|
||||||
|
|
||||||
|
protected Map<String,String> headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the target service is a gCube Service it adds the HTTP header
|
||||||
|
* to provide gCube authorization token and/or scope
|
||||||
|
*/
|
||||||
|
protected boolean gCubeTargetService;
|
||||||
|
|
||||||
|
public boolean isgCubeTargetService() {
|
||||||
|
return gCubeTargetService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setgCubeTargetService(boolean gCubeTargetService) {
|
||||||
|
this.gCubeTargetService = gCubeTargetService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HTTPCall(String address) {
|
||||||
|
this(address, HTTPCall.USER_AGENT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HTTPCall(String address, String userAgent) {
|
||||||
|
this.address = address;
|
||||||
|
this.userAgent = userAgent;
|
||||||
|
this.gCubeTargetService = true;
|
||||||
|
this.headers = new HashMap<>();
|
||||||
|
addHeader(USER_AGENT_KEY, this.userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHeader(String key, String value) {
|
||||||
|
headers.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getParametersDataString(Map<String,String> parameters) throws UnsupportedEncodingException {
|
||||||
|
|
||||||
|
if(parameters == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for(String key : parameters.keySet()) {
|
||||||
|
if(first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
result.append(PARAM_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(URLEncoder.encode(key, UTF8));
|
||||||
|
result.append(PARAM_EQUALS);
|
||||||
|
result.append(URLEncoder.encode(parameters.get(key), UTF8));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URL getURL(String address, String path, String urlParameters) throws MalformedURLException {
|
||||||
|
|
||||||
|
StringWriter stringWriter = new StringWriter();
|
||||||
|
stringWriter.append(address);
|
||||||
|
|
||||||
|
if(address.endsWith(PATH_SEPARATOR)) {
|
||||||
|
if(path.startsWith(PATH_SEPARATOR)) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(path.compareTo("") != 0 && !path.startsWith(PATH_SEPARATOR)) {
|
||||||
|
stringWriter.append(PATH_SEPARATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stringWriter.append(path);
|
||||||
|
|
||||||
|
if(urlParameters != null) {
|
||||||
|
stringWriter.append(PARAM_STARTER);
|
||||||
|
stringWriter.append(urlParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getURL(stringWriter.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected URL getURL(String urlString) throws MalformedURLException {
|
||||||
|
URL url = new URL(urlString);
|
||||||
|
if(url.getProtocol().compareTo("https") == 0) {
|
||||||
|
url = new URL(url.getProtocol(), url.getHost(), url.getDefaultPort(), url.getFile());
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpURLConnection getConnection(String path, String urlParameters, HTTPMETHOD method, String body,
|
||||||
|
InputStream inputStream, String contentType) throws Exception {
|
||||||
|
URL url = getURL(address, path, urlParameters);
|
||||||
|
return getConnection(url, method, body, inputStream, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getFinalURL(URL url) {
|
||||||
|
try {
|
||||||
|
URL finalURL = url;
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
connection.setInstanceFollowRedirects(false);
|
||||||
|
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
String responseMessage = connection.getResponseMessage();
|
||||||
|
|
||||||
|
if(responseCode >= Status.BAD_REQUEST.getStatusCode()) {
|
||||||
|
Status status = Status.fromStatusCode(responseCode);
|
||||||
|
throw new WebApplicationException(responseMessage, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER
|
||||||
|
|| responseCode == Status.TEMPORARY_REDIRECT.getStatusCode() || responseCode == 308) {
|
||||||
|
|
||||||
|
finalURL = getURL(connection.getHeaderField("Location"));
|
||||||
|
finalURL = getFinalURL(finalURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalURL;
|
||||||
|
|
||||||
|
}catch (WebApplicationException e) {
|
||||||
|
throw e;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected HttpURLConnection getConnection(URL url, HTTPMETHOD method, String body, InputStream inputStream,
|
||||||
|
String contentType) throws Exception {
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
|
|
||||||
|
if(gCubeTargetService) {
|
||||||
|
if(SecurityTokenProvider.instance.get() == null) {
|
||||||
|
if(ScopeProvider.instance.get() == null) {
|
||||||
|
throw new RuntimeException("Null Token and Scope. Please set your token first.");
|
||||||
|
}
|
||||||
|
connection.setRequestProperty("gcube-scope", ScopeProvider.instance.get());
|
||||||
|
} else {
|
||||||
|
connection.setRequestProperty(org.gcube.common.authorization.client.Constants.TOKEN_HEADER_ENTRY,
|
||||||
|
SecurityTokenProvider.instance.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.setDoOutput(true);
|
||||||
|
|
||||||
|
connection.setRequestProperty("Content-type", contentType);
|
||||||
|
for(String key : headers.keySet()) {
|
||||||
|
connection.setRequestProperty(key, headers.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.setRequestMethod(method.toString());
|
||||||
|
|
||||||
|
if(inputStream != null && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) {
|
||||||
|
|
||||||
|
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
|
||||||
|
int len;
|
||||||
|
while((len = inputStream.read(buffer)) > 0) {
|
||||||
|
wr.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
wr.flush();
|
||||||
|
wr.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(body != null && (method == HTTPMETHOD.POST || method == HTTPMETHOD.PUT)) {
|
||||||
|
|
||||||
|
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
|
||||||
|
wr.writeBytes(body);
|
||||||
|
wr.flush();
|
||||||
|
wr.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
String responseMessage = connection.getResponseMessage();
|
||||||
|
logger.trace("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage);
|
||||||
|
|
||||||
|
// 308 Permanent Redirect https://tools.ietf.org/html/rfc7538#section-3
|
||||||
|
if(responseCode == HttpURLConnection.HTTP_MOVED_TEMP || responseCode == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|
|| responseCode == HttpURLConnection.HTTP_SEE_OTHER
|
||||||
|
|| responseCode == Status.TEMPORARY_REDIRECT.getStatusCode() || responseCode == 308) {
|
||||||
|
|
||||||
|
URL redirectURL = getURL(connection.getHeaderField("Location"));
|
||||||
|
|
||||||
|
logger.trace("{} is going to be redirect to {}", url.toString(), redirectURL.toString());
|
||||||
|
|
||||||
|
connection = getConnection(redirectURL, method, body, inputStream, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected StringBuilder getStringBuilder(InputStream inputStream) throws IOException {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
||||||
|
String line;
|
||||||
|
while((line = reader.readLine()) != null) {
|
||||||
|
result.append(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String call(String path, HTTPMETHOD method, Map<String,String> parameters, String contentType) {
|
||||||
|
return call(path, method, parameters, null, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String call(String path, HTTPMETHOD method, String body, String contentType) {
|
||||||
|
return call(path, method, null, body, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String call(String path, HTTPMETHOD method, Map<String,String> parameters, String body, String contentType) {
|
||||||
|
return call(path, method, body, null, parameters, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String call(String path, HTTPMETHOD method, InputStream inputStream, Map<String,String> parameters,
|
||||||
|
String contentType) {
|
||||||
|
return call(path, method, null, inputStream, parameters, contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String call(String path, HTTPMETHOD method, String body, InputStream inputStream,
|
||||||
|
Map<String,String> parameters, String contentType) {
|
||||||
|
HttpURLConnection connection;
|
||||||
|
try {
|
||||||
|
String urlParameters = getParametersDataString(parameters);
|
||||||
|
connection = getConnection(path, urlParameters, method, body, inputStream, contentType);
|
||||||
|
int responseCode = connection.getResponseCode();
|
||||||
|
String responseMessage = connection.getResponseMessage();
|
||||||
|
logger.info("{} {} : {} - {}", method, connection.getURL(), responseCode, responseMessage);
|
||||||
|
|
||||||
|
if(responseCode >= Status.BAD_REQUEST.getStatusCode()) {
|
||||||
|
try {
|
||||||
|
StringBuilder result = getStringBuilder(connection.getErrorStream());
|
||||||
|
String res = result.toString();
|
||||||
|
logger.trace("Server returned content : {}", res);
|
||||||
|
return res;
|
||||||
|
}catch (Exception e) {
|
||||||
|
Status status = Status.fromStatusCode(responseCode);
|
||||||
|
throw new WebApplicationException(responseMessage, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StringBuilder result = getStringBuilder(connection.getInputStream());
|
||||||
|
String res = result.toString();
|
||||||
|
logger.trace("Server returned content : {}", res);
|
||||||
|
|
||||||
|
connection.disconnect();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
|
||||||
|
} catch(WebApplicationException e) {
|
||||||
|
throw e;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lucio Lelii (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class RandomString {
|
||||||
|
|
||||||
|
private static final char[] symbols;
|
||||||
|
|
||||||
|
static {
|
||||||
|
StringBuilder tmp = new StringBuilder();
|
||||||
|
for (char ch = '0'; ch <= '9'; ++ch)
|
||||||
|
tmp.append(ch);
|
||||||
|
for (char ch = 'a'; ch <= 'z'; ++ch)
|
||||||
|
tmp.append(ch);
|
||||||
|
symbols = tmp.toString().toCharArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Random random = new Random();
|
||||||
|
|
||||||
|
private final char[] buf;
|
||||||
|
|
||||||
|
public RandomString(int length) {
|
||||||
|
if (length < 1)
|
||||||
|
throw new IllegalArgumentException("length < 1: " + length);
|
||||||
|
buf = new char[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String nextString() {
|
||||||
|
for (int idx = 0; idx < buf.length; ++idx)
|
||||||
|
buf[idx] = symbols[random.nextInt(symbols.length)];
|
||||||
|
return new String(buf);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.gcube.gcat.utils;
|
||||||
|
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.DataCatalogue;
|
||||||
|
import org.gcube.datacatalogue.ckanutillibrary.server.utils.url.EntityContext;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKAN;
|
||||||
|
import org.gcube.gcat.utils.HTTPCall.HTTPMETHOD;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
public class URIResolver {
|
||||||
|
|
||||||
|
private static final String CATALOGUE_CONTEXT = "gcube_scope";
|
||||||
|
private static final String ENTITY_TYPE = "entity_context";
|
||||||
|
private static final String ENTITY_NAME = "entity_name";
|
||||||
|
private static final String CATALOGUE_PLAIN_URL = "clear_url";
|
||||||
|
|
||||||
|
protected ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public URIResolver() {
|
||||||
|
this.objectMapper = new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCatalogueItemURL(String name) {
|
||||||
|
try {
|
||||||
|
DataCatalogue dataCatalogue = CKAN.getCatalogue();
|
||||||
|
String uriResolverURL = dataCatalogue.getUriResolverUrl();
|
||||||
|
|
||||||
|
HTTPCall httpCall = new HTTPCall(uriResolverURL);
|
||||||
|
|
||||||
|
ObjectNode requestContent = objectMapper.createObjectNode();
|
||||||
|
requestContent.put(CATALOGUE_CONTEXT, ContextUtility.getCurrentContext());
|
||||||
|
requestContent.put(ENTITY_TYPE, EntityContext.PRODUCT.toString());
|
||||||
|
requestContent.put(ENTITY_NAME, name);
|
||||||
|
requestContent.put(CATALOGUE_PLAIN_URL, true);
|
||||||
|
|
||||||
|
String url = httpCall.call("", HTTPMETHOD.POST, objectMapper.writeValueAsString(requestContent),
|
||||||
|
MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
return url;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new WebApplicationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,295 @@
|
||||||
|
package org.gcube.gcat.workspace;
|
||||||
|
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.ws.rs.InternalServerErrorException;
|
||||||
|
|
||||||
|
import org.gcube.common.homelibrary.home.Home;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeLibrary;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManager;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManagerFactory;
|
||||||
|
import org.gcube.common.homelibrary.home.User;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.Workspace;
|
||||||
|
import org.gcube.common.storagehub.client.StreamDescriptor;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ContainerType;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.FileContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.FolderContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ItemContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ListResolver;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ListResolverTyped;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.OpenResolver;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.StorageHubClient;
|
||||||
|
import org.gcube.common.storagehub.model.Metadata;
|
||||||
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.gcat.utils.Constants;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StorageHubManagement {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(StorageHubManagement.class);
|
||||||
|
|
||||||
|
public static final String ORIGINAL_URL = "OriginalURL";
|
||||||
|
public static final String ORIGINAL_NAME = "OriginalName";
|
||||||
|
|
||||||
|
public static final String CATALOGUE_ITEM_ID = "CatalogueItemID";
|
||||||
|
public static final String CATALOGUE_RESOURCE_ID = "CatalogueResourceID";
|
||||||
|
public static final String CATALOGUE_RESOURCE_REVISION_ID = "CatalogueResourceRevisionID";
|
||||||
|
|
||||||
|
public static final String CATALOGUE_FOLDER_DESCRIPTION = "Catalogue Folder used to persist Resources";
|
||||||
|
|
||||||
|
protected final StorageHubClient storageHubClient;
|
||||||
|
|
||||||
|
protected FileContainer createdFile;
|
||||||
|
protected String mimeType;
|
||||||
|
|
||||||
|
public String getMimeType() {
|
||||||
|
return mimeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageHubManagement() {
|
||||||
|
storageHubClient = new StorageHubClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void recursiveList(FolderContainer folder, int level) {
|
||||||
|
ListResolverTyped listResolverTyped = folder.list();
|
||||||
|
List<ItemContainer<? extends Item>> containers = listResolverTyped.getContainers();
|
||||||
|
for(ItemContainer<? extends Item> itemContainer : containers) {
|
||||||
|
Item item = itemContainer.get();
|
||||||
|
String name = item.getName();
|
||||||
|
ContainerType containerType = itemContainer.getType();
|
||||||
|
StringWriter indent = new StringWriter(level + 1);
|
||||||
|
for(int i = 0; i < level + 1; i++) {
|
||||||
|
indent.append('-');
|
||||||
|
}
|
||||||
|
logger.debug("{} {} {} (ID:{})", indent.toString(), containerType, name, itemContainer.getId());
|
||||||
|
switch(containerType) {
|
||||||
|
case FOLDER:
|
||||||
|
FolderContainer folderContainer = (FolderContainer) itemContainer;
|
||||||
|
//if(item.getName().compareTo("553095a0-a14a-4e41-b014-2e6f3a1aeac7")!=0)
|
||||||
|
recursiveList(folderContainer, level + 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GENERIC_ITEM:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FolderContainer getWorkspaceRoot() {
|
||||||
|
try {
|
||||||
|
return storageHubClient.getWSRoot();
|
||||||
|
}catch (Exception e) {
|
||||||
|
String username = ContextUtility.getUsername();
|
||||||
|
logger.info("Unable to obtain the Workspace Root for {}. Going to create it.", username);
|
||||||
|
try {
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
User user = manager.createUser(username);
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
Home home = manager.getHome(user);
|
||||||
|
Workspace ws = home.getWorkspace();
|
||||||
|
ws.getRoot();
|
||||||
|
return storageHubClient.getWSRoot();
|
||||||
|
}catch (Exception ex) {
|
||||||
|
logger.info("Unable to create the Workspace Root for {}.", username);
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected FolderContainer getOrCreateFolder(FolderContainer parent, String name, String description) {
|
||||||
|
try {
|
||||||
|
FolderContainer destinationFolder = null;
|
||||||
|
ListResolverTyped listResolverTyped = parent.list();
|
||||||
|
List<ItemContainer<? extends Item>> containers = listResolverTyped.getContainers();
|
||||||
|
for(ItemContainer<? extends Item> itemContainer : containers) {
|
||||||
|
if(itemContainer instanceof FolderContainer) {
|
||||||
|
if(itemContainer.get().getName().compareTo(name) == 0) {
|
||||||
|
destinationFolder = (FolderContainer) itemContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(destinationFolder == null) {
|
||||||
|
destinationFolder = parent.newFolder(name, description);
|
||||||
|
}
|
||||||
|
return destinationFolder;
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFolderName() {
|
||||||
|
String currentContext = ContextUtility.getCurrentContext();
|
||||||
|
String folderName = currentContext.replaceFirst("/", "").replace("/", "_");
|
||||||
|
return folderName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FolderContainer getCatalogueFolder() {
|
||||||
|
FolderContainer destinationFolder = getWorkspaceRoot();
|
||||||
|
String folderName = getFolderName();
|
||||||
|
destinationFolder = getOrCreateFolder(destinationFolder, folderName, ContextUtility.getCurrentContext() + " folder");
|
||||||
|
destinationFolder = getOrCreateFolder(destinationFolder, Constants.CATALOGUE_NAME, CATALOGUE_FOLDER_DESCRIPTION);
|
||||||
|
return destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FolderContainer getDestinationFolder(AbstractFileItem item) {
|
||||||
|
FolderContainer destinationFolder = getCatalogueFolder();
|
||||||
|
mimeType = item.getContent().getMimeType();
|
||||||
|
String[] splittedMimeType = mimeType.split("/");
|
||||||
|
for(String name : splittedMimeType) {
|
||||||
|
try {
|
||||||
|
destinationFolder = getOrCreateFolder(destinationFolder, name,
|
||||||
|
"Automatic Folder Created using mimetype");
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new InternalServerErrorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destinationFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FileContainer copyFile(FileContainer sourceFileContainer, FolderContainer destinationFolder,
|
||||||
|
String copiedFilename) {
|
||||||
|
StreamDescriptor streamDescriptor = sourceFileContainer.download("");
|
||||||
|
FileContainer createdFile = destinationFolder.uploadFile(streamDescriptor.getStream(), copiedFilename,
|
||||||
|
sourceFileContainer.get().getDescription());
|
||||||
|
/*
|
||||||
|
FileContainer copiedFile = sourceFileContainer.copy(destinationFolder, copiedFilename);
|
||||||
|
*/
|
||||||
|
return createdFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ItemContainer<? extends Item> getContainerByStorageURL(URL url) {
|
||||||
|
URL finalURL = url;
|
||||||
|
String path = finalURL.getPath();
|
||||||
|
String fileID = path.substring(path.lastIndexOf('/') + 1);
|
||||||
|
|
||||||
|
OpenResolver openResolver = storageHubClient.open(fileID);
|
||||||
|
ItemContainer<Item> itemContainer = openResolver.asItem();
|
||||||
|
Item item = itemContainer.get();
|
||||||
|
if(item instanceof AbstractFileItem) {
|
||||||
|
logger.debug("The resource with ID {} is a file", fileID);
|
||||||
|
return openResolver.asFile();
|
||||||
|
}
|
||||||
|
return itemContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isItemPersistedFile(FileContainer fileContainer, FolderContainer destinationFolder, String itemID) {
|
||||||
|
// Checking if the file is already a file of the science catalogue folder of the scope related to such an item.
|
||||||
|
ListResolver listResolver = fileContainer.getAnchestors();
|
||||||
|
List<ItemContainer<? extends Item>> itemContainers = listResolver.getContainers();
|
||||||
|
for(ItemContainer<? extends Item> itemContainer : itemContainers) {
|
||||||
|
if(itemContainer.getId().compareTo(destinationFolder.getId()) == 0) {
|
||||||
|
Metadata metadata = fileContainer.get().getPropertyMap();
|
||||||
|
Map<String,Object> map = metadata.getValues();
|
||||||
|
if(map.get(CATALOGUE_ITEM_ID).toString().compareTo(itemID) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isItemPersistedFile(URL url, String itemID) {
|
||||||
|
ItemContainer<? extends Item> itemContainer = getContainerByStorageURL(url);
|
||||||
|
FileContainer fileContainer;
|
||||||
|
if(itemContainer instanceof FileContainer) {
|
||||||
|
fileContainer = (FileContainer) itemContainer;
|
||||||
|
}else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FolderContainer destinationFolder = getDestinationFolder(fileContainer.get());
|
||||||
|
return isItemPersistedFile(fileContainer, destinationFolder, itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tree(FolderContainer folderContainer) throws Exception {
|
||||||
|
logger.debug("{} (ID:{})", folderContainer.get().getName(), folderContainer.getId());
|
||||||
|
recursiveList(folderContainer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FileContainer getFileByID(String id) throws Exception {
|
||||||
|
OpenResolver openResolver = storageHubClient.open(id);
|
||||||
|
FileContainer fileContainer = (FileContainer) openResolver.asFile();
|
||||||
|
return fileContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void deleteFileByID(String id) throws Exception {
|
||||||
|
FileContainer fileContainer = getFileByID(id);
|
||||||
|
fileContainer.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public URL ensureResourcePersistence(URL url, String itemID, String resourceID, String name) {
|
||||||
|
ItemContainer<? extends Item> itemContainer = getContainerByStorageURL(url);
|
||||||
|
FileContainer fileContainer;
|
||||||
|
if(itemContainer instanceof FileContainer) {
|
||||||
|
fileContainer = (FileContainer) itemContainer;
|
||||||
|
}else {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
FolderContainer destinationFolder = getDestinationFolder(fileContainer.get());
|
||||||
|
|
||||||
|
if(isItemPersistedFile(fileContainer, destinationFolder, itemID)) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
createdFile = copyFile(fileContainer, destinationFolder, resourceID);
|
||||||
|
|
||||||
|
Map<String,Object> map = new HashMap<>();
|
||||||
|
map.put(ORIGINAL_URL, url.toString());
|
||||||
|
map.put(ORIGINAL_NAME, name);
|
||||||
|
map.put(CATALOGUE_ITEM_ID, itemID);
|
||||||
|
map.put(CATALOGUE_RESOURCE_ID, resourceID);
|
||||||
|
Metadata metadata = new Metadata(map);
|
||||||
|
createdFile.setMetadata(metadata);
|
||||||
|
|
||||||
|
URL finalURL = createdFile.getPublicLink();
|
||||||
|
logger.debug("Original File URL was {} - Final URL to ensure persistency is {}", url, finalURL);
|
||||||
|
return finalURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteResourcePersistence(URL url, String itemID) {
|
||||||
|
FileContainer fileContainer = (FileContainer) getContainerByStorageURL(url);
|
||||||
|
FolderContainer destinationFolder = getDestinationFolder(fileContainer.get());
|
||||||
|
if(isItemPersistedFile(fileContainer, destinationFolder, itemID)) {
|
||||||
|
fileContainer.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addRevisionID(FileContainer fileContainer, String resourceID, String revisionID) {
|
||||||
|
Metadata metadata = fileContainer.get().getPropertyMap();
|
||||||
|
Map<String,Object> map = metadata.getValues();
|
||||||
|
map.put(CATALOGUE_RESOURCE_ID, resourceID);
|
||||||
|
map.put(CATALOGUE_RESOURCE_REVISION_ID, revisionID);
|
||||||
|
metadata.setValues(map);
|
||||||
|
fileContainer.setMetadata(metadata);;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRevisionID(String resourceID, String revisionID) {
|
||||||
|
addRevisionID(createdFile, resourceID, revisionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renameFile(String resourceID, String revisionID) {
|
||||||
|
renameFile(createdFile, resourceID);
|
||||||
|
addRevisionID(createdFile, resourceID, revisionID);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void renameFile(FileContainer fileContainer, String newName) {
|
||||||
|
fileContainer.rename(newName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,316 @@
|
||||||
|
gCube System - License
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
European Union Public Licence V. 1.1
|
||||||
|
|
||||||
|
|
||||||
|
EUPL © the European Community 2007
|
||||||
|
|
||||||
|
|
||||||
|
This European Union Public Licence (the “EUPL”) applies to the Work or Software
|
||||||
|
(as defined below) which is provided under the terms of this Licence. Any use of
|
||||||
|
the Work, other than as authorised under this Licence is prohibited (to the
|
||||||
|
extent such use is covered by a right of the copyright holder of the Work).
|
||||||
|
|
||||||
|
The Original Work is provided under the terms of this Licence when the Licensor
|
||||||
|
(as defined below) has placed the following notice immediately following the
|
||||||
|
copyright notice for the Original Work:
|
||||||
|
|
||||||
|
Licensed under the EUPL V.1.1
|
||||||
|
|
||||||
|
or has expressed by any other mean his willingness to license under the EUPL.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
In this Licence, the following terms have the following meaning:
|
||||||
|
|
||||||
|
- The Licence: this Licence.
|
||||||
|
|
||||||
|
- The Original Work or the Software: the software distributed and/or
|
||||||
|
communicated by the Licensor under this Licence, available as Source Code and
|
||||||
|
also as Executable Code as the case may be.
|
||||||
|
|
||||||
|
- Derivative Works: the works or software that could be created by the Licensee,
|
||||||
|
based upon the Original Work or modifications thereof. This Licence does not
|
||||||
|
define the extent of modification or dependence on the Original Work required
|
||||||
|
in order to classify a work as a Derivative Work; this extent is determined by
|
||||||
|
copyright law applicable in the country mentioned in Article 15.
|
||||||
|
|
||||||
|
- The Work: the Original Work and/or its Derivative Works.
|
||||||
|
|
||||||
|
- The Source Code: the human-readable form of the Work which is the most
|
||||||
|
convenient for people to study and modify.
|
||||||
|
|
||||||
|
- The Executable Code: any code which has generally been compiled and which is
|
||||||
|
meant to be interpreted by a computer as a program.
|
||||||
|
|
||||||
|
- The Licensor: the natural or legal person that distributes and/or communicates
|
||||||
|
the Work under the Licence.
|
||||||
|
|
||||||
|
- Contributor(s): any natural or legal person who modifies the Work under the
|
||||||
|
Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||||
|
|
||||||
|
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
||||||
|
Software under the terms of the Licence.
|
||||||
|
|
||||||
|
- Distribution and/or Communication: any act of selling, giving, lending,
|
||||||
|
renting, distributing, communicating, transmitting, or otherwise making
|
||||||
|
available, on-line or off-line, copies of the Work or providing access to its
|
||||||
|
essential functionalities at the disposal of any other natural or legal
|
||||||
|
person.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2. Scope of the rights granted by the Licence
|
||||||
|
|
||||||
|
The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
|
||||||
|
sub-licensable licence to do the following, for the duration of copyright vested
|
||||||
|
in the Original Work:
|
||||||
|
|
||||||
|
- use the Work in any circumstance and for all usage, reproduce the Work, modify
|
||||||
|
- the Original Work, and make Derivative Works based upon the Work, communicate
|
||||||
|
- to the public, including the right to make available or display the Work or
|
||||||
|
- copies thereof to the public and perform publicly, as the case may be, the
|
||||||
|
- Work, distribute the Work or copies thereof, lend and rent the Work or copies
|
||||||
|
- thereof, sub-license rights in the Work or copies thereof.
|
||||||
|
|
||||||
|
Those rights can be exercised on any media, supports and formats, whether now
|
||||||
|
known or later invented, as far as the applicable law permits so.
|
||||||
|
|
||||||
|
In the countries where moral rights apply, the Licensor waives his right to
|
||||||
|
exercise his moral right to the extent allowed by law in order to make effective
|
||||||
|
the licence of the economic rights here above listed.
|
||||||
|
|
||||||
|
The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
|
||||||
|
any patents held by the Licensor, to the extent necessary to make use of the
|
||||||
|
rights granted on the Work under this Licence.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3. Communication of the Source Code
|
||||||
|
|
||||||
|
The Licensor may provide the Work either in its Source Code form, or as
|
||||||
|
Executable Code. If the Work is provided as Executable Code, the Licensor
|
||||||
|
provides in addition a machine-readable copy of the Source Code of the Work
|
||||||
|
along with each copy of the Work that the Licensor distributes or indicates, in
|
||||||
|
a notice following the copyright notice attached to the Work, a repository where
|
||||||
|
the Source Code is easily and freely accessible for as long as the Licensor
|
||||||
|
continues to distribute and/or communicate the Work.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4. Limitations on copyright
|
||||||
|
|
||||||
|
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
||||||
|
any exception or limitation to the exclusive rights of the rights owners in the
|
||||||
|
Original Work or Software, of the exhaustion of those rights or of other
|
||||||
|
applicable limitations thereto.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
5. Obligations of the Licensee
|
||||||
|
|
||||||
|
The grant of the rights mentioned above is subject to some restrictions and
|
||||||
|
obligations imposed on the Licensee. Those obligations are the following:
|
||||||
|
|
||||||
|
Attribution right: the Licensee shall keep intact all copyright, patent or
|
||||||
|
trademarks notices and all notices that refer to the Licence and to the
|
||||||
|
disclaimer of warranties. The Licensee must include a copy of such notices and a
|
||||||
|
copy of the Licence with every copy of the Work he/she distributes and/or
|
||||||
|
communicates. The Licensee must cause any Derivative Work to carry prominent
|
||||||
|
notices stating that the Work has been modified and the date of modification.
|
||||||
|
|
||||||
|
Copyleft clause: If the Licensee distributes and/or communicates copies of the
|
||||||
|
Original Works or Derivative Works based upon the Original Work, this
|
||||||
|
Distribution and/or Communication will be done under the terms of this Licence
|
||||||
|
or of a later version of this Licence unless the Original Work is expressly
|
||||||
|
distributed only under this version of the Licence. The Licensee (becoming
|
||||||
|
Licensor) cannot offer or impose any additional terms or conditions on the Work
|
||||||
|
or Derivative Work that alter or restrict the terms of the Licence.
|
||||||
|
|
||||||
|
Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
|
||||||
|
Works or copies thereof based upon both the Original Work and another work
|
||||||
|
licensed under a Compatible Licence, this Distribution and/or Communication can
|
||||||
|
be done under the terms of this Compatible Licence. For the sake of this clause,
|
||||||
|
“Compatible Licence” refers to the licences listed in the appendix attached to
|
||||||
|
this Licence. Should the Licensee’s obligations under the Compatible Licence
|
||||||
|
conflict with his/her obligations under this Licence, the obligations of the
|
||||||
|
Compatible Licence shall prevail.
|
||||||
|
|
||||||
|
Provision of Source Code: When distributing and/or communicating copies of the
|
||||||
|
Work, the Licensee will provide a machine-readable copy of the Source Code or
|
||||||
|
indicate a repository where this Source will be easily and freely available for
|
||||||
|
as long as the Licensee continues to distribute and/or communicate the Work.
|
||||||
|
|
||||||
|
Legal Protection: This Licence does not grant permission to use the trade names,
|
||||||
|
trademarks, service marks, or names of the Licensor, except as required for
|
||||||
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the copyright notice.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
6. Chain of Authorship
|
||||||
|
|
||||||
|
The original Licensor warrants that the copyright in the Original Work granted
|
||||||
|
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
||||||
|
power and authority to grant the Licence.
|
||||||
|
|
||||||
|
Each Contributor warrants that the copyright in the modifications he/she brings
|
||||||
|
to the Work are owned by him/her or licensed to him/her and that he/she has the
|
||||||
|
power and authority to grant the Licence.
|
||||||
|
|
||||||
|
Each time You accept the Licence, the original Licensor and subsequent
|
||||||
|
Contributors grant You a licence to their contributions to the Work, under the
|
||||||
|
terms of this Licence.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty
|
||||||
|
|
||||||
|
The Work is a work in progress, which is continuously improved by numerous
|
||||||
|
contributors. It is not a finished work and may therefore contain defects or
|
||||||
|
“bugs” inherent to this type of software development.
|
||||||
|
|
||||||
|
For the above reason, the Work is provided under the Licence on an “as is” basis
|
||||||
|
and without warranties of any kind concerning the Work, including without
|
||||||
|
limitation merchantability, fitness for a particular purpose, absence of defects
|
||||||
|
or errors, accuracy, non-infringement of intellectual property rights other than
|
||||||
|
copyright as stated in Article 6 of this Licence.
|
||||||
|
|
||||||
|
This disclaimer of warranty is an essential part of the Licence and a condition
|
||||||
|
for the grant of any rights to the Work.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
8. Disclaimer of Liability
|
||||||
|
|
||||||
|
Except in the cases of wilful misconduct or damages directly caused to natural
|
||||||
|
persons, the Licensor will in no event be liable for any direct or indirect,
|
||||||
|
material or moral, damages of any kind, arising out of the Licence or of the use
|
||||||
|
of the Work, including without limitation, damages for loss of goodwill, work
|
||||||
|
stoppage, computer failure or malfunction, loss of data or any commercial
|
||||||
|
damage, even if the Licensor has been advised of the possibility of such
|
||||||
|
damage. However, the Licensor will be liable under statutory product liability
|
||||||
|
laws as far such laws apply to the Work.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
9. Additional agreements
|
||||||
|
|
||||||
|
While distributing the Original Work or Derivative Works, You may choose to
|
||||||
|
conclude an additional agreement to offer, and charge a fee for, acceptance of
|
||||||
|
support, warranty, indemnity, or other liability obligations and/or services
|
||||||
|
consistent with this Licence. However, in accepting such obligations, You may
|
||||||
|
act only on your own behalf and on your sole responsibility, not on behalf of
|
||||||
|
the original Licensor or any other Contributor, and only if You agree to
|
||||||
|
indemnify, defend, and hold each Contributor harmless for any liability incurred
|
||||||
|
by, or claims asserted against such Contributor by the fact You have accepted
|
||||||
|
any such warranty or additional liability.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
10. Acceptance of the Licence
|
||||||
|
|
||||||
|
The provisions of this Licence can be accepted by clicking on an icon “I agree”
|
||||||
|
placed under the bottom of a window displaying the text of this Licence or by
|
||||||
|
affirming consent in any other similar way, in accordance with the rules of
|
||||||
|
applicable law. Clicking on that icon indicates your clear and irrevocable
|
||||||
|
acceptance of this Licence and all of its terms and conditions.
|
||||||
|
|
||||||
|
Similarly, you irrevocably accept this Licence and all of its terms and
|
||||||
|
conditions by exercising any rights granted to You by Article 2 of this Licence,
|
||||||
|
such as the use of the Work, the creation by You of a Derivative Work or the
|
||||||
|
Distribution and/or Communication by You of the Work or copies thereof.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
11. Information to the public
|
||||||
|
|
||||||
|
In case of any Distribution and/or Communication of the Work by means of
|
||||||
|
electronic communication by You (for example, by offering to download the Work
|
||||||
|
from a remote location) the distribution channel or media (for example, a
|
||||||
|
website) must at least provide to the public the information requested by the
|
||||||
|
applicable law regarding the Licensor, the Licence and the way it may be
|
||||||
|
accessible, concluded, stored and reproduced by the Licensee.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
12. Termination of the Licence
|
||||||
|
|
||||||
|
The Licence and the rights granted hereunder will terminate automatically upon
|
||||||
|
any breach by the Licensee of the terms of the Licence.
|
||||||
|
|
||||||
|
Such a termination will not terminate the licences of any person who has
|
||||||
|
received the Work from the Licensee under the Licence, provided such persons
|
||||||
|
remain in full compliance with the Licence.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
13. Miscellaneous
|
||||||
|
|
||||||
|
Without prejudice of Article 9 above, the Licence represents the complete
|
||||||
|
agreement between the Parties as to the Work licensed hereunder.
|
||||||
|
|
||||||
|
If any provision of the Licence is invalid or unenforceable under applicable
|
||||||
|
law, this will not affect the validity or enforceability of the Licence as a
|
||||||
|
whole. Such provision will be construed and/or reformed so as necessary to make
|
||||||
|
it valid and enforceable.
|
||||||
|
|
||||||
|
The European Commission may publish other linguistic versions and/or new
|
||||||
|
versions of this Licence, so far this is required and reasonable, without
|
||||||
|
reducing the scope of the rights granted by the Licence. New versions of the
|
||||||
|
Licence will be published with a unique version number.
|
||||||
|
|
||||||
|
All linguistic versions of this Licence, approved by the European Commission,
|
||||||
|
have identical value. Parties can take advantage of the linguistic version of
|
||||||
|
their choice.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
14. Jurisdiction
|
||||||
|
|
||||||
|
Any litigation resulting from the interpretation of this License, arising
|
||||||
|
between the European Commission, as a Licensor, and any Licensee, will be
|
||||||
|
subject to the jurisdiction of the Court of Justice of the European Communities,
|
||||||
|
as laid down in article 238 of the Treaty establishing the European Community.
|
||||||
|
|
||||||
|
Any litigation arising between Parties, other than the European Commission, and
|
||||||
|
resulting from the interpretation of this License, will be subject to the
|
||||||
|
exclusive jurisdiction of the competent court where the Licensor resides or
|
||||||
|
conducts its primary business.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
15. Applicable Law
|
||||||
|
|
||||||
|
This Licence shall be governed by the law of the European Union country where
|
||||||
|
the Licensor resides or has his registered office.
|
||||||
|
|
||||||
|
This licence shall be governed by the Belgian law if:
|
||||||
|
|
||||||
|
- a litigation arises between the European Commission, as a Licensor, and any
|
||||||
|
- Licensee; the Licensor, other than the European Commission, has no residence
|
||||||
|
- or registered office inside a European Union country.
|
||||||
|
|
||||||
|
|
||||||
|
===
|
||||||
|
|
||||||
|
|
||||||
|
Appendix
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
“Compatible Licences” according to article 5 EUPL are:
|
||||||
|
|
||||||
|
|
||||||
|
- GNU General Public License (GNU GPL) v. 2
|
||||||
|
|
||||||
|
- Open Software License (OSL) v. 2.1, v. 3.0
|
||||||
|
|
||||||
|
- Common Public License v. 1.0
|
||||||
|
|
||||||
|
- Eclipse Public License v. 1.0
|
||||||
|
|
||||||
|
- Cecill v. 2.0
|
|
@ -0,0 +1,76 @@
|
||||||
|
The gCube System - gCube Catalogue Service
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
This service allows any client to publish on the gCube Catalogue.
|
||||||
|
|
||||||
|
|
||||||
|
This software is part of the gCube Framework (https://www.gcube-system.org/): an
|
||||||
|
open-source software toolkit used for building and operating Hybrid Data
|
||||||
|
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
||||||
|
by favouring the realisation of reuse oriented policies.
|
||||||
|
|
||||||
|
The projects leading to this software have received funding from a series of
|
||||||
|
European Union programmes including:
|
||||||
|
* the Sixth Framework Programme for Research and Technological Development -
|
||||||
|
DILIGENT (grant no. 004260);
|
||||||
|
* the Seventh Framework Programme for research, technological development and
|
||||||
|
demonstration - D4Science (grant no. 212488), D4Science-II (grant no.
|
||||||
|
239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine
|
||||||
|
(grant no. 283644);
|
||||||
|
* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680),
|
||||||
|
EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant
|
||||||
|
no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
|
||||||
|
|
||||||
|
|
||||||
|
Version
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
1.0.0-SNAPSHOT (2018-12-04)
|
||||||
|
|
||||||
|
Please see the file named "changelog.xml" in this directory for the release notes.
|
||||||
|
|
||||||
|
|
||||||
|
Authors
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
* Costantino Perciante (costantino.perciante@isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Maintainers
|
||||||
|
-----------
|
||||||
|
|
||||||
|
* Luca Frosini (luca.frosini-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy).
|
||||||
|
|
||||||
|
Download information
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Source code is available from SVN:
|
||||||
|
https://svn.d4science.research-infrastructures.eu/gcube/trunk/data-catalogue/gcat
|
||||||
|
|
||||||
|
Binaries can be downloaded from the gCube website:
|
||||||
|
https://www.gcube-system.org/
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Installation documentation is available on-line in the gCube Wiki:
|
||||||
|
https://wiki.gcube-system.org/gcube/index.php
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Documentation is available on-line in the gCube Wiki:
|
||||||
|
https://wiki.gcube-system.org/gcube/index.php
|
||||||
|
|
||||||
|
Support
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Bugs and support requests can be reported in the gCube issue tracking tool:
|
||||||
|
https://support.d4science.org/projects/gcube/
|
||||||
|
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<ReleaseNotes>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-4-0" date="2018-12-04">
|
||||||
|
<Change></Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-3-0" date="2018-10-10">
|
||||||
|
<Change>Complete refactoring of code</Change>
|
||||||
|
<Change>Item Port type is now RESTful (old methods are still allowed)</Change>
|
||||||
|
<Change>Added update support for Item #11516</Change>
|
||||||
|
<Change>Changed caching mechanism from ehcache API to JSR-107. Ehcache is still used as runtime library.</Change>
|
||||||
|
<Change>Solved random NullPointer Exception on catalogue-ws related to old caching mechanism #11466</Change>
|
||||||
|
<Change>Fixed normalization of the organization name #12506</Change>
|
||||||
|
<Change>Added the possibility to deny social post on catalogue-ws #12514</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-1-1"
|
||||||
|
date="2018-01-11">
|
||||||
|
<Change>Item purge method enhanced</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-1-0"
|
||||||
|
date="2017-06-20">
|
||||||
|
<Change>Minor fixes while checking user's permissions</Change>
|
||||||
|
<Change>Namespaces are no longer transparently managed</Change>
|
||||||
|
<Change>Fixed 'default' value for metadata</Change>
|
||||||
|
<Change>Improved exception handling</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-catalogue.catalogue-ws.1-0-0"
|
||||||
|
date="2017-05-01">
|
||||||
|
<Change>First Release</Change>
|
||||||
|
</Changeset>
|
||||||
|
</ReleaseNotes>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<assembly
|
||||||
|
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||||
|
<id>servicearchive</id>
|
||||||
|
<formats>
|
||||||
|
<format>tar.gz</format>
|
||||||
|
</formats>
|
||||||
|
<baseDirectory>/</baseDirectory>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>/home/lucafrosini/workspace/gcat/distro</directory>
|
||||||
|
<outputDirectory>/</outputDirectory>
|
||||||
|
<useDefaultExcludes>true</useDefaultExcludes>
|
||||||
|
<includes>
|
||||||
|
<include>README</include>
|
||||||
|
<include>LICENSE</include>
|
||||||
|
<include>changelog.xml</include>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>755</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>target/gcat-1.0.0-SNAPSHOT.war</source>
|
||||||
|
<outputDirectory>/gcat</outputDirectory>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
|
</assembly>
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<application mode='online'>
|
||||||
|
<name>gcat</name>
|
||||||
|
<group>DataCatalogue</group>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<description>This service allows any client to publish on the gCube Catalogue.</description>
|
||||||
|
<local-persistence location='target' />
|
||||||
|
</application>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<Resource>
|
||||||
|
<ID />
|
||||||
|
<Type>Service</Type>
|
||||||
|
<Profile>
|
||||||
|
<Description>This service allows any client to publish on the gCube Catalogue.</Description>
|
||||||
|
<Class>DataCatalogue</Class>
|
||||||
|
<Name>gcat</Name>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Packages>
|
||||||
|
<Main>
|
||||||
|
<Description>This service allows any client to publish on the gCube Catalogue.</Description>
|
||||||
|
<Name>gcat</Name>
|
||||||
|
<Version>1.0.0-SNAPSHOT</Version>
|
||||||
|
<MavenCoordinates>
|
||||||
|
<groupId>org.gcube.data-publishing</groupId>
|
||||||
|
<artifactId>gcat</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</MavenCoordinates>
|
||||||
|
<Files>
|
||||||
|
<File>gcat-1.0.0-SNAPSHOT.war</File>
|
||||||
|
</Files>
|
||||||
|
</Main>
|
||||||
|
</Packages>
|
||||||
|
</Profile>
|
||||||
|
</Resource>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<web-app>
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>org.gcube.datacatalogue.sciencecatalogue.ResourceInitializer</servlet-name>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>org.gcube.datacatalogue.sciencecatalogue.ResourceInitializer</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.gcube.gcat;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.client.Constants;
|
||||||
|
import org.gcube.common.authorization.client.exceptions.ObjectNotFound;
|
||||||
|
import org.gcube.common.authorization.library.AuthorizationEntry;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.authorization.library.provider.ClientInfo;
|
||||||
|
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.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ContextTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ContextTest.class);
|
||||||
|
|
||||||
|
protected static final String PROPERTIES_FILENAME = "token.properties";
|
||||||
|
|
||||||
|
private static final String GCUBE_VARNAME = "GCUBE";
|
||||||
|
public static final String GCUBE;
|
||||||
|
|
||||||
|
private static final String GCUBE_DEVNEXT_VARNAME = "GCUBE_DEVNEXT";
|
||||||
|
public static final String GCUBE_DEVNEXT;
|
||||||
|
|
||||||
|
private static final String GCUBE_DEVNEXT_NEXTNEXT_VARNAME = "GCUBE_DEVNEXT_NEXTNEXT";
|
||||||
|
public static final String GCUBE_DEVNEXT_NEXTNEXT;
|
||||||
|
|
||||||
|
public static final String GCUBE_DEVSEC_VARNAME = "GCUBE_DEVSEC";
|
||||||
|
public static final String GCUBE_DEVSEC;
|
||||||
|
|
||||||
|
public static final String GCUBE_DEVSEC_DEVVRE_VARNAME = "GCUBE_DEVSEC_DEVVRE";
|
||||||
|
public static final String GCUBE_DEVSEC_DEVVRE;
|
||||||
|
|
||||||
|
|
||||||
|
private static final String GCUBE_DEVNEXT_ANOTHER_USER_VARNAME = "GCUBE_DEVNEXT_ANOTHER_USER";
|
||||||
|
public static final String GCUBE_DEVNEXT_ANOTHER_USER;
|
||||||
|
|
||||||
|
public static final String DEFAULT_TEST_SCOPE;
|
||||||
|
|
||||||
|
public static final String GCUBE_PRE_PROD_PREVRE_VARNAME = "GCUBE_PRE_PROD_PREVRE";
|
||||||
|
public static final String GCUBE_PRE_PROD_PREVRE;
|
||||||
|
|
||||||
|
public static final String GCUBE_PRE_PROD_PARTHENOS_REGISTRY_VARNAME = "GCUBE_PRE_PROD_PARTHENOS_REGISTRY";
|
||||||
|
public static final String GCUBE_PRE_PROD_PARTHENOS_REGISTRY;
|
||||||
|
|
||||||
|
public static final String ROOT_VARNAME = "ROOT";
|
||||||
|
public static final String ROOT;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
InputStream input = ContextTest.class.getClassLoader().getResourceAsStream(PROPERTIES_FILENAME);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// load the properties file
|
||||||
|
properties.load(input);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCUBE = properties.getProperty(GCUBE_VARNAME);
|
||||||
|
|
||||||
|
GCUBE_DEVNEXT = properties.getProperty(GCUBE_DEVNEXT_VARNAME);
|
||||||
|
GCUBE_DEVNEXT_NEXTNEXT = properties.getProperty(GCUBE_DEVNEXT_NEXTNEXT_VARNAME);
|
||||||
|
|
||||||
|
GCUBE_DEVSEC = properties.getProperty(GCUBE_DEVSEC_VARNAME);
|
||||||
|
GCUBE_DEVSEC_DEVVRE = properties.getProperty(GCUBE_DEVSEC_DEVVRE_VARNAME);
|
||||||
|
|
||||||
|
GCUBE_DEVNEXT_ANOTHER_USER = properties.getProperty(GCUBE_DEVNEXT_ANOTHER_USER_VARNAME);
|
||||||
|
|
||||||
|
GCUBE_PRE_PROD_PARTHENOS_REGISTRY = properties.getProperty(GCUBE_PRE_PROD_PARTHENOS_REGISTRY_VARNAME);
|
||||||
|
GCUBE_PRE_PROD_PREVRE = properties.getProperty(GCUBE_PRE_PROD_PREVRE_VARNAME);
|
||||||
|
ROOT = properties.getProperty(ROOT_VARNAME);
|
||||||
|
|
||||||
|
DEFAULT_TEST_SCOPE = GCUBE_PRE_PROD_PREVRE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentScope(String token) throws ObjectNotFound, Exception{
|
||||||
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
||||||
|
String context = authorizationEntry.getContext();
|
||||||
|
logger.info("Context of token {} is {}", token, context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setContext(String token) throws ObjectNotFound, Exception{
|
||||||
|
SecurityTokenProvider.instance.set(token);
|
||||||
|
AuthorizationEntry authorizationEntry = Constants.authorizationService().get(token);
|
||||||
|
ClientInfo clientInfo = authorizationEntry.getClientInfo();
|
||||||
|
logger.debug("User : {} - Type : {}", clientInfo.getId(), clientInfo.getType().name());
|
||||||
|
String qualifier = authorizationEntry.getQualifier();
|
||||||
|
Caller caller = new Caller(clientInfo, qualifier);
|
||||||
|
AuthorizationProvider.instance.set(caller);
|
||||||
|
ScopeProvider.instance.set(getCurrentScope(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() throws Exception{
|
||||||
|
setContext(DEFAULT_TEST_SCOPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void afterClass() throws Exception{
|
||||||
|
SecurityTokenProvider.instance.reset();
|
||||||
|
ScopeProvider.instance.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANLicense;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
|
||||||
|
public class CKANLicenseTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANLicenseTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void list() throws Exception {
|
||||||
|
CKANLicense license = new CKANLicense();
|
||||||
|
String ret = license.list();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode gotList = mapper.readTree(ret);
|
||||||
|
Assert.assertTrue(gotList instanceof ArrayNode);
|
||||||
|
logger.debug("List :\n{}", mapper.writeValueAsString(gotList));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANOrganization;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUtility;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class CKANOrganizationTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANOrganizationTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUserRole() throws Exception {
|
||||||
|
CKANOrganization ckanOrganization = new CKANOrganization();
|
||||||
|
ckanOrganization.setApiKey(CKANUtility.getSysAdminAPI());
|
||||||
|
ckanOrganization.setName(CKANOrganization.getCKANOrganizationName());
|
||||||
|
String ret = ckanOrganization.getUserRole("luca.frosini");
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKAN;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANPackage;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANResource;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANPackageTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANPackageTest.class);
|
||||||
|
|
||||||
|
private static final String NOTES_KEY = "notes";
|
||||||
|
private static final String URL_KEY = "url";
|
||||||
|
private static final String PRIVATE_KEY = "private";
|
||||||
|
|
||||||
|
private static final String ITEM_NAME_VALUE = "restful_transaction_model";
|
||||||
|
private static final String LICENSE_VALUE = "CC-BY-SA-4.0";
|
||||||
|
private static final String EXTRAS_TYPE_VALUE_VALUE = "EmptyType";
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void list() throws Exception {
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String ret = ckanPackage.list();
|
||||||
|
JsonNode gotList = mapper.readTree(ret);
|
||||||
|
Assert.assertTrue(gotList instanceof ArrayNode);
|
||||||
|
logger.debug("List :\n{}", mapper.writeValueAsString(gotList));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DEV
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model.pdf
|
||||||
|
* https://data-d.d4science.org/shub/e03355cd-058a-4e3a-8d5b-cf3676a46840
|
||||||
|
* URL url = new URL("https://goo.gl/fSZH1o");
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf
|
||||||
|
* https://data-d.d4science.org/shub/8ad187c4-8f94-4c47-a780-706d0d33c1bb
|
||||||
|
* URL url = new URL("https://goo.gl/6vZSmp");
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf
|
||||||
|
* https://data-d.d4science.org/shub/7b6628e4-b397-4df9-b387-2d643ae0095c
|
||||||
|
* URL url = new URL("https://goo.gl/jvXMcd");
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
protected CKANPackage createPackage(ObjectMapper mapper) throws Exception {
|
||||||
|
|
||||||
|
ObjectNode itemObjectNode = mapper.createObjectNode();
|
||||||
|
itemObjectNode.put(CKAN.NAME_KEY, ITEM_NAME_VALUE);
|
||||||
|
itemObjectNode.put(CKANPackage.TITLE_KEY, "RESTful Transaction Model");
|
||||||
|
itemObjectNode.put(CKANPackage.LICENSE_KEY, LICENSE_VALUE);
|
||||||
|
itemObjectNode.put(PRIVATE_KEY, false);
|
||||||
|
itemObjectNode.put(NOTES_KEY, "A research of Luca Frosini");
|
||||||
|
itemObjectNode.put(URL_KEY, "http://www.d4science.org");
|
||||||
|
|
||||||
|
ArrayNode tagArrayNode = itemObjectNode.putArray(CKANPackage.TAGS_KEY);
|
||||||
|
ObjectNode tagNode = mapper.createObjectNode();
|
||||||
|
tagNode.put(CKANPackage.NAME_KEY, "REST");
|
||||||
|
tagArrayNode.add(tagNode);
|
||||||
|
|
||||||
|
ArrayNode resourceArrayNode = itemObjectNode.putArray(CKANPackage.RESOURCES_KEY);
|
||||||
|
ObjectNode resourceNode = mapper.createObjectNode();
|
||||||
|
resourceNode.put(CKANResource.NAME_KEY, "RESTful Transaction Model");
|
||||||
|
// Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf
|
||||||
|
resourceNode.put(CKANResource.URL_KEY, "https://goo.gl/6vZSmp");
|
||||||
|
resourceArrayNode.add(resourceNode);
|
||||||
|
|
||||||
|
ArrayNode extraArrayNode = itemObjectNode.putArray(CKANPackage.EXTRA_TYPES_KEY);
|
||||||
|
ObjectNode extraNode = mapper.createObjectNode();
|
||||||
|
extraNode.put(CKANPackage.EXTRA_TYPES_KEY_KEY, CKANPackage.EXTRA_TYPES_KEY_VALUE_SYSTEM_TYPE);
|
||||||
|
extraNode.put(CKANPackage.EXTRA_TYPES_VALUE_KEY, EXTRAS_TYPE_VALUE_VALUE);
|
||||||
|
extraArrayNode.add(extraNode);
|
||||||
|
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
//ckanPackage.setApiKey(CKANUtility.getSysAdminAPI());
|
||||||
|
String createdItem = ckanPackage.create(mapper.writeValueAsString(itemObjectNode));
|
||||||
|
logger.debug(createdItem);
|
||||||
|
|
||||||
|
return ckanPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
createPackage(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createReadUpdateUpdatePurge() throws Exception {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
createPackage(mapper);
|
||||||
|
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
String readItem = ckanPackage.read();
|
||||||
|
|
||||||
|
JsonNode readItemObjectNode = mapper.readTree(readItem);
|
||||||
|
String readID = readItemObjectNode.get(CKANPackage.NAME_KEY).asText();
|
||||||
|
Assert.assertNotNull(readID);
|
||||||
|
|
||||||
|
Assert.assertTrue(ITEM_NAME_VALUE.compareTo(readID)==0);
|
||||||
|
|
||||||
|
String updatedNotes = "A research of Luca Frosini made during the PhD";
|
||||||
|
((ObjectNode) readItemObjectNode).put(NOTES_KEY, updatedNotes);
|
||||||
|
|
||||||
|
ArrayNode resources = (ArrayNode) readItemObjectNode.get(CKANPackage.RESOURCES_KEY);
|
||||||
|
ObjectNode objectNode = (ObjectNode) resources.get(0);
|
||||||
|
// Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf
|
||||||
|
objectNode.put(CKANResource.URL_KEY, "https://goo.gl/jvXMcd");
|
||||||
|
resources.set(0, objectNode);
|
||||||
|
|
||||||
|
((ObjectNode) readItemObjectNode).replace(CKANPackage.RESOURCES_KEY, resources);
|
||||||
|
|
||||||
|
ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
String updatedItem = ckanPackage.update(mapper.writeValueAsString(readItemObjectNode));
|
||||||
|
logger.trace(updatedItem);
|
||||||
|
JsonNode updatedItemObjectNode = mapper.readTree(updatedItem);
|
||||||
|
String gotUpdatedNotes = updatedItemObjectNode.get(NOTES_KEY).asText();
|
||||||
|
Assert.assertTrue(gotUpdatedNotes.compareTo(updatedNotes)==0);
|
||||||
|
|
||||||
|
|
||||||
|
ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
((ObjectNode) updatedItemObjectNode).remove(CKANPackage.RESOURCES_KEY);
|
||||||
|
String secondUpdateItem = ckanPackage.update(mapper.writeValueAsString(updatedItemObjectNode));
|
||||||
|
logger.trace(secondUpdateItem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
ObjectNode patchObjectNode = mapper.createObjectNode();
|
||||||
|
String patchedNotes = updatedNotes + " in October 2018";
|
||||||
|
patchObjectNode.put(NOTES_KEY, patchedNotes);
|
||||||
|
patchObjectNode.put(CKANPackage.NAME_KEY, ITEM_NAME_VALUE);
|
||||||
|
|
||||||
|
ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
String patchedItem = ckanPackage.patch(mapper.writeValueAsString(patchObjectNode));
|
||||||
|
logger.trace(patchedItem);
|
||||||
|
JsonNode patchedItemObjectNode = mapper.readTree(patchedItem);
|
||||||
|
String gotPatchedNotes = patchedItemObjectNode.get(NOTES_KEY).asText();
|
||||||
|
Assert.assertTrue(gotPatchedNotes.compareTo(patchedNotes)==0);
|
||||||
|
*/
|
||||||
|
|
||||||
|
ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
ckanPackage.purge();
|
||||||
|
logger.debug("Item {} purge successfully", ITEM_NAME_VALUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
//(expected = NotFoundException.class)
|
||||||
|
public void read() throws Exception {
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
String ret = ckanPackage.read();
|
||||||
|
logger.debug(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
//(expected = NotFoundException.class)
|
||||||
|
public void delete() throws Exception {
|
||||||
|
CKANPackage ckanPackage = new CKANPackage();
|
||||||
|
ckanPackage.setName(ITEM_NAME_VALUE);
|
||||||
|
ckanPackage.delete(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANResource;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
public class CKANResourceTest extends ContextTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CKANResourceTest.class);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PROD
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model.pdf
|
||||||
|
* https://data.d4science.org/shub/ab4daec8-2ce4-43d7-9d37-00b2051e3530
|
||||||
|
* URL url = new URL("https://goo.gl/bFME6Q");
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DEV
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model.pdf
|
||||||
|
* https://data-d.d4science.org/shub/e03355cd-058a-4e3a-8d5b-cf3676a46840
|
||||||
|
* URL url = new URL("https://goo.gl/fSZH1o");
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.0.pdf
|
||||||
|
* https://data-d.d4science.org/shub/5df695ea-986a-437d-abaf-ed1542a7f5af
|
||||||
|
* URL url = new URL("https://goo.gl/7ofQwn");
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Workspace(luca.frosini) > RESTful Transaction Model v 1.1.pdf
|
||||||
|
* https://data-d.d4science.org/shub/7b6628e4-b397-4df9-b387-2d643ae0095c
|
||||||
|
* URL url = new URL("https://goo.gl/jvXMcd");
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCopyStorageResource() throws Exception {
|
||||||
|
URL url = new URL("https://goo.gl/fSZH1o");
|
||||||
|
|
||||||
|
String itemID = UUID.randomUUID().toString();
|
||||||
|
CKANResource ckanResource = new CKANResource(itemID);
|
||||||
|
ckanResource.resourceID = UUID.randomUUID().toString();
|
||||||
|
URL finalURL = ckanResource.copyStorageResource(url);
|
||||||
|
logger.debug("Initial URL is {} - Final URL is {}", url, finalURL);
|
||||||
|
ckanResource.deleteStorageResource(finalURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
public void testCreate() throws Exception {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
ObjectNode objectNode = objectMapper.createObjectNode();
|
||||||
|
objectNode.put(CKANResource.URL_KEY, "https://data.d4science.org/shub/ab4daec8-2ce4-43d7-9d37-00b2051e3530");
|
||||||
|
objectNode.put(CKANResource.ID_KEY, "8422b5d4-626b-46f2-9121-bbc6d443071d");
|
||||||
|
|
||||||
|
CKANResource ckanResource = new CKANResource("f9221556-4b1f-49f2-8951-a4c30d71cd37");
|
||||||
|
String json = ckanResource.getAsString(objectNode);
|
||||||
|
logger.debug("Going to create Resource {}", json);
|
||||||
|
ckanResource.create(json);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUser;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUtility;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
|
||||||
|
public class CKANUserTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANUserTest.class);
|
||||||
|
|
||||||
|
private static final String USERNAME = "pippo";
|
||||||
|
|
||||||
|
private CKANUser getCKANUser() {
|
||||||
|
CKANUser user = new CKANUser();
|
||||||
|
user.setApiKey(CKANUtility.getSysAdminAPI());
|
||||||
|
user.setName(USERNAME);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void list() throws Exception {
|
||||||
|
CKANUser ckanUser = getCKANUser();
|
||||||
|
String ret = ckanUser.list();
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create() throws Exception {
|
||||||
|
CKANUser ckanUser = getCKANUser();
|
||||||
|
String ret = ckanUser.create();
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read() throws Exception {
|
||||||
|
CKANUser ckanUser = getCKANUser();
|
||||||
|
String ret = ckanUser.read();
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static String DISPLAY_NAME = "display_name";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void update() throws Exception {
|
||||||
|
CKANUser ckanUser = getCKANUser();
|
||||||
|
String ret = ckanUser.read();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode readUser = mapper.readTree(ret);
|
||||||
|
((ObjectNode) readUser).put(CKANUser.EMAIL, USERNAME+"@gcube.ckan.org");
|
||||||
|
((ObjectNode) readUser).put("state", "active");
|
||||||
|
ret = ckanUser.update(ckanUser.getAsString(readUser));
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void delete() throws Exception {
|
||||||
|
CKANUser ckanUser = getCKANUser();
|
||||||
|
ckanUser.delete(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.gcube.gcat.persistence.ckan;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.persistence.ckan.CKANUtility;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Luca Frosini (ISTI - CNR)
|
||||||
|
*/
|
||||||
|
public class CKANUtilityTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(CKANPackageTest.class);
|
||||||
|
|
||||||
|
private static final String USERNAME = "luca_frosini";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetApiKey() throws Exception {
|
||||||
|
String ckanAPI = CKANUtility.getApiKey(USERNAME);
|
||||||
|
logger.debug("User {} has the following API key {}", USERNAME, ckanAPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddUserToOrganization() throws Exception {
|
||||||
|
CKANUtility.addUserToOrganization(USERNAME, CKANUtility.MEMBER_ROLE, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddSpecialUserToOrganization() throws Exception {
|
||||||
|
CKANUtility.addUserToOrganization("luca_frosini", "editor", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.rest.Namespace;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NamespaceTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(NamespaceTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void list() throws Exception {
|
||||||
|
Namespace namespace = new Namespace();
|
||||||
|
String ret = namespace.list();
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.gcube.gcat.rest;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.rest.Profile;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
|
||||||
|
public class ProfileTest extends ContextTest {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(ProfileTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void list() throws Exception {
|
||||||
|
Profile profile = new Profile();
|
||||||
|
String ret = profile.list();
|
||||||
|
logger.debug("{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void read() throws Exception {
|
||||||
|
String profileID = "SoBigData.eu: Dataset Metadata NextNext";
|
||||||
|
Profile profile = new Profile();
|
||||||
|
String ret = profile.read(profileID, MediaType.APPLICATION_XML);
|
||||||
|
logger.debug("XML :\n{}", ret);
|
||||||
|
ret = profile.read(profileID, MediaType.APPLICATION_JSON);
|
||||||
|
logger.debug("JSON : \n{}", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listRead() throws Exception {
|
||||||
|
Profile profile = new Profile();
|
||||||
|
String ret = profile.list();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
ArrayNode arrayNode = (ArrayNode) mapper.readTree(ret);
|
||||||
|
logger.debug("Found {} profiles", arrayNode.size());
|
||||||
|
Iterator<JsonNode> iterator = arrayNode.iterator();
|
||||||
|
while(iterator.hasNext()) {
|
||||||
|
String profileID = iterator.next().asText();
|
||||||
|
ret = profile.read(profileID, MediaType.APPLICATION_XML);
|
||||||
|
logger.debug("XML :\n{}", ret);
|
||||||
|
ret = profile.read(profileID, MediaType.APPLICATION_JSON);
|
||||||
|
logger.debug("JSON : \n{}", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.gcube.gcat.social;
|
||||||
|
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.social.SocialService;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
public class SocialServiceTest extends ContextTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SocialServiceTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetUserProfile() throws Exception {
|
||||||
|
SocialService socialService = new SocialService();
|
||||||
|
JsonNode jsonNode = socialService.getGCubeUserProfile();
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
logger.debug("gCube User Profile is {}", objectMapper.writeValueAsString(jsonNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
package org.gcube.gcat.workspace;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.gcube.common.homelibrary.home.Home;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeLibrary;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManager;
|
||||||
|
import org.gcube.common.homelibrary.home.HomeManagerFactory;
|
||||||
|
import org.gcube.common.homelibrary.home.User;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.Workspace;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder;
|
||||||
|
import org.gcube.common.homelibrary.home.workspace.WorkspaceItem;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.FileContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.FolderContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ItemContainer;
|
||||||
|
import org.gcube.common.storagehub.client.dsl.ListResolver;
|
||||||
|
import org.gcube.common.storagehub.model.Metadata;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.service.Version;
|
||||||
|
import org.gcube.gcat.ContextTest;
|
||||||
|
import org.gcube.gcat.utils.ApplicationMode;
|
||||||
|
import org.gcube.gcat.utils.ContextUtility;
|
||||||
|
import org.gcube.gcat.workspace.StorageHubManagement;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StorageHubManagementTest extends ContextTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(StorageHubManagementTest.class);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHL() throws Exception {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
String username = ContextUtility.getUsername();
|
||||||
|
HomeManagerFactory factory = HomeLibrary.getHomeManagerFactory();
|
||||||
|
HomeManager manager = factory.getHomeManager();
|
||||||
|
User user = manager.createUser(username);
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
Home home = manager.getHome(user);
|
||||||
|
Workspace ws = home.getWorkspace();
|
||||||
|
WorkspaceFolder workspaceFolder = ws.getRoot();
|
||||||
|
List<WorkspaceItem> workspaceItems = workspaceFolder.getChildren(true);
|
||||||
|
for(WorkspaceItem workspaceItem : workspaceItems) {
|
||||||
|
logger.debug("{} {}{}", workspaceFolder.getType(), workspaceItem.getName(), workspaceItem.isHidden()? " (hidden)":"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void myTest() throws Exception {
|
||||||
|
String folderName = StorageHubManagement.getFolderName();
|
||||||
|
logger.debug(folderName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws Exception {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
StorageHubManagement storageHubManagement = new StorageHubManagement();
|
||||||
|
FolderContainer root = storageHubManagement.getWorkspaceRoot();
|
||||||
|
storageHubManagement.tree(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void listFolders() throws Exception {
|
||||||
|
ApplicationMode applicationMode = new ApplicationMode();
|
||||||
|
applicationMode.start();
|
||||||
|
StorageHubManagement storageHubManagement = new StorageHubManagement();
|
||||||
|
FolderContainer root = storageHubManagement.getWorkspaceRoot();
|
||||||
|
storageHubManagement.getCatalogueFolder();
|
||||||
|
storageHubManagement.tree(root);
|
||||||
|
applicationMode.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Test
|
||||||
|
public void deleteFile() throws Exception {
|
||||||
|
StorageHubManagement storageHubManagement = new StorageHubManagement();
|
||||||
|
String id = "";
|
||||||
|
storageHubManagement.deleteFileByID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFileInfo() throws Exception {
|
||||||
|
StorageHubManagement storageHubManagement = new StorageHubManagement();
|
||||||
|
String id = "";
|
||||||
|
FileContainer fileContainer = storageHubManagement.getFileByID(id);
|
||||||
|
logger.debug("StorageHub ID {} - File Name {}", id, fileContainer.get().getName());
|
||||||
|
ListResolver listResolver = fileContainer.getAnchestors();
|
||||||
|
List<ItemContainer<? extends Item>> itemContainers = listResolver.getContainers();
|
||||||
|
for(ItemContainer<? extends Item> itemContainer : itemContainers) {
|
||||||
|
logger.debug("{}", itemContainer.get().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata metadata = fileContainer.get().getPropertyMap();
|
||||||
|
Map<String,Object> map = metadata.getValues();
|
||||||
|
logger.debug("{}", map);
|
||||||
|
|
||||||
|
List<Version> versions = fileContainer.getVersions();
|
||||||
|
for(Version version : versions){
|
||||||
|
logger.debug("Version {} {}", version.getId(), version.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE xml>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{0}: %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
|
||||||
|
<logger name="org.gcube" level="ERROR" />
|
||||||
|
<logger name="org.gcube.datacatalogue" level="TRACE" />
|
||||||
|
|
||||||
|
<root level="WARN">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
Loading…
Reference in New Issue