Compare commits
No commits in common. "master" and "v1.0.8" have entirely different histories.
|
@ -13,15 +13,15 @@
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="test" value="true"/>
|
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="test" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
@ -35,6 +35,5 @@
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
|
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||||
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
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.problem.forbiddenReference=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
|
||||||
org.eclipse.jdt.core.compiler.release=disabled
|
org.eclipse.jdt.core.compiler.release=disabled
|
||||||
org.eclipse.jdt.core.compiler.source=1.8
|
org.eclipse.jdt.core.compiler.source=1.8
|
||||||
|
|
|
@ -1,226 +1,16 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<wb-module deploy-name="storagehub">
|
<wb-module deploy-name="storagehub">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
<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="/" 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/java"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||||
|
<dependent-module archiveName="authorization-control-library-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/authorization-control-library/authorization-control-library">
|
||||||
|
<dependency-type>uses</dependency-type>
|
||||||
|
</dependent-module>
|
||||||
|
<dependent-module archiveName="storagehub-model-1.0.5.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
|
||||||
|
<dependency-type>uses</dependency-type>
|
||||||
|
</dependent-module>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<property name="context-root" value="storagehub"/>
|
<property name="context-root" value="storagehub"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
|
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</wb-module>
|
</wb-module>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</project-modules>
|
</project-modules>
|
||||||
|
|
78
CHANGELOG.md
78
CHANGELOG.md
|
@ -1,78 +0,0 @@
|
||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [v1.4.2] - [2023-05-22]
|
|
||||||
|
|
||||||
- added enunciate libraries for documentation
|
|
||||||
|
|
||||||
## [v1.4.1] - [2022-11-14]
|
|
||||||
|
|
||||||
- added libraries to manage different image format
|
|
||||||
|
|
||||||
## [v1.4.0] - [2021-10-07]
|
|
||||||
|
|
||||||
- slow query removed from VRE retrieving and recents
|
|
||||||
- incident #22184 solved
|
|
||||||
|
|
||||||
## [v1.3.2] - [2021-09-28]
|
|
||||||
- fix 22087
|
|
||||||
|
|
||||||
## [v1.3.1] - [2021-09-08]
|
|
||||||
|
|
||||||
- solved bug on attachment rights
|
|
||||||
|
|
||||||
## [v1.3.0] - [2021-03-31]
|
|
||||||
|
|
||||||
- possibility to impersonate people added
|
|
||||||
|
|
||||||
## [v1.2.5] - [2021-03-11]
|
|
||||||
|
|
||||||
use of query (indexes are not working well in jackrabbit) to retrieve shared folder removed on delete user
|
|
||||||
|
|
||||||
## [v1.2.4] - [2021-01-11]
|
|
||||||
|
|
||||||
mimetype set also on non parsable pdf
|
|
||||||
|
|
||||||
method add and remove admin on a VREFolder enabled also for admin role
|
|
||||||
|
|
||||||
fixed bug on unsharing folder on user removal
|
|
||||||
|
|
||||||
added method exist user
|
|
||||||
|
|
||||||
## [v1.2.2] - [2020-10-12]
|
|
||||||
|
|
||||||
method for description update added
|
|
||||||
|
|
||||||
## [v1.2.1] - [2020-06-20]
|
|
||||||
|
|
||||||
bug on Archive uploader solved
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.2.0] - [2020-04-15]
|
|
||||||
|
|
||||||
trash items changes owner on restore
|
|
||||||
|
|
||||||
restore with new destination folder added
|
|
||||||
|
|
||||||
move between shared and private or different shared folder enabled
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.0.8] - [2019-09-20]
|
|
||||||
|
|
||||||
Bug on ushare owner fixed
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.0.5] - [2019-04-04]
|
|
||||||
|
|
||||||
Active wait for lock in case of item creation added
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [v1.0.0] - [2015-07-01]
|
|
||||||
|
|
||||||
First commit
|
|
26
FUNDING.md
26
FUNDING.md
|
@ -1,26 +0,0 @@
|
||||||
# Acknowledgments
|
|
||||||
|
|
||||||
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](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
|
|
||||||
- the Seventh Framework Programme for research, technological development and demonstration
|
|
||||||
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
|
|
||||||
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
|
|
||||||
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
|
|
||||||
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
|
|
||||||
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
|
|
||||||
- the H2020 research and innovation programme
|
|
||||||
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
|
|
||||||
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
|
|
||||||
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
|
|
||||||
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
|
|
||||||
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
|
|
||||||
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
|
|
||||||
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
|
|
||||||
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
|
|
||||||
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
|
|
||||||
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
|
|
||||||
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
|
|
||||||
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
|
|
||||||
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
|
|
|
@ -1,4 +1,4 @@
|
||||||
#European Union Public Licence V.1.2
|
#European Union Public Licence V.1.1
|
||||||
|
|
||||||
##*EUPL © the European Community 2007*
|
##*EUPL © the European Community 2007*
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ 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
|
(as defined below) has placed the following notice immediately following the
|
||||||
copyright notice for the Original Work:
|
copyright notice for the Original Work:
|
||||||
|
|
||||||
**Licensed under the EUPL V.1.2**
|
**Licensed under the EUPL V.1.1**
|
||||||
|
|
||||||
or has expressed by any other mean his willingness to license under the EUPL.
|
or has expressed by any other mean his willingness to license under the EUPL.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<ReleaseNotes>
|
||||||
|
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.8"
|
||||||
|
date="2019-09-20">
|
||||||
|
<Change>Bug on ushare owner fixed</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.5"
|
||||||
|
date="2019-04-04">
|
||||||
|
<Change>Active wait for lock in case of item creation added</Change>
|
||||||
|
</Changeset>
|
||||||
|
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.0"
|
||||||
|
date="2015-07-01">
|
||||||
|
<Change>First commit</Change>
|
||||||
|
</Changeset>
|
||||||
|
</ReleaseNotes>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<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>.</directory>
|
||||||
|
<outputDirectory>/</outputDirectory>
|
||||||
|
<useDefaultExcludes>true</useDefaultExcludes>
|
||||||
|
<includes>
|
||||||
|
<include>README.md</include>
|
||||||
|
<include>LICENSE.md</include>
|
||||||
|
<include>changelog.xml</include>
|
||||||
|
<include>profile.xml</include>
|
||||||
|
</includes>
|
||||||
|
<fileMode>755</fileMode>
|
||||||
|
<filtered>true</filtered>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
<files>
|
||||||
|
<file>
|
||||||
|
<source>target/${build.finalName}.war</source>
|
||||||
|
<outputDirectory>/${artifactId}</outputDirectory>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
|
|
||||||
|
</assembly>
|
|
@ -1,8 +1,7 @@
|
||||||
<application mode='online'>
|
<application mode='online'>
|
||||||
<name>StorageHub</name>
|
<name>StorageHub</name>
|
||||||
<group>DataAccess</group>
|
<group>DataAccess</group>
|
||||||
<version>1.4.2</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<description>Storage Hub webapp</description>
|
<description>Storage Hub webapp</description>
|
||||||
<local-persistence location='target' />
|
<local-persistence location='target' />
|
||||||
<exclude>/workspace/api-docs/*</exclude>
|
|
||||||
</application>
|
</application>
|
|
@ -1,24 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<enunciate
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.14.0.xsd">
|
|
||||||
<api-classes>
|
|
||||||
<!-- Use patterns to exclude classes... e.g. for URI-Resolver <exclude
|
|
||||||
pattern="org.gcube.datatransfer.resolver.services.DocsGenerator" /> -->
|
|
||||||
</api-classes>
|
|
||||||
<modules>
|
|
||||||
<gwt-json-overlay disabled="true" />
|
|
||||||
<php-json-client disabled="true" />
|
|
||||||
<ruby-json-client disabled="true" />
|
|
||||||
<java-json-client disabled="true" />
|
|
||||||
<javascript-client disabled="true" />
|
|
||||||
<docs docsDir="${project.build.directory}" docsSubdir="api-docs" />
|
|
||||||
|
|
||||||
<docs
|
|
||||||
freemarkerTemplate="${project.basedir}/src/main/resources/META-INF/enunciate/d4science_docs.fmt">
|
|
||||||
<additional-css
|
|
||||||
file="css/d4science_enunciate_custom.css" />
|
|
||||||
</docs>
|
|
||||||
<swagger basePath="/workspace" />
|
|
||||||
</modules>
|
|
||||||
</enunciate>
|
|
274
pom.xml
274
pom.xml
|
@ -1,44 +1,53 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>maven-parent</artifactId>
|
<artifactId>maven-parent</artifactId>
|
||||||
<groupId>org.gcube.tools</groupId>
|
<groupId>org.gcube.tools</groupId>
|
||||||
<version>1.1.0</version>
|
<version>1.1.0</version>
|
||||||
<relativePath />
|
<relativePath />
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.gcube.data.access</groupId>
|
<groupId>org.gcube.data.access</groupId>
|
||||||
<artifactId>storagehub</artifactId>
|
<artifactId>storagehub</artifactId>
|
||||||
<version>1.4.2</version>
|
<version>1.0.8</version>
|
||||||
<name>storagehub</name>
|
<name>storagehub</name>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection>
|
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection>
|
||||||
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
|
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
|
||||||
<url>https://code-repo.d4science.org/gCubeSystem/storagehub</url>
|
<url>https://code-repo.d4science.org/gCubeSystem/storagehub</url>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
|
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
|
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
|
||||||
<jackrabbit.version>2.20.2</jackrabbit.version>
|
<jackrabbit.version>2.16.0</jackrabbit.version>
|
||||||
<jackson.version>2.8.11</jackson.version>
|
|
||||||
<slf4j.version>1.7.4</slf4j.version>
|
|
||||||
<tomcat.version>7.0.40</tomcat.version>
|
<tomcat.version>7.0.40</tomcat.version>
|
||||||
<jetty.version>6.1.26</jetty.version>
|
<jetty.version>6.1.26</jetty.version>
|
||||||
<tika.version>1.21</tika.version>
|
<tika.version>1.21</tika.version>
|
||||||
|
<slf4j.api.version>1.6.6</slf4j.api.version>
|
||||||
|
<slf4j.version>1.7.4</slf4j.version> <!-- sync with logback version -->
|
||||||
|
<logback.version>1.0.12</logback.version>
|
||||||
|
|
||||||
<distroDirectory>${project.basedir}/distro</distroDirectory>
|
<distroDirectory>${project.basedir}/distro</distroDirectory>
|
||||||
<description>REST web service for Jackrabbit</description>
|
<description>REST web service for Jackrabbit</description>
|
||||||
<warname>storagehub</warname>
|
<warname>storagehub</warname>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<enunciate.version>2.14.0</enunciate.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.distribution</groupId>
|
<groupId>org.gcube.distribution</groupId>
|
||||||
<artifactId>gcube-smartgears-bom</artifactId>
|
<artifactId>maven-smartgears-bom</artifactId>
|
||||||
<version>2.1.1</version>
|
<version>LATEST</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@ -49,85 +58,82 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjrt</artifactId>
|
<artifactId>aspectjrt</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
<artifactId>common-smartgears</artifactId>
|
<artifactId>common-smartgears</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.gcube.core</groupId>
|
|
||||||
<artifactId>common-smartgears-app</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.common</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
<artifactId>authorization-control-library</artifactId>
|
<artifactId>authorization-control-library</artifactId>
|
||||||
<version>[1.0.0,2.0.0-SNAPSHOT)</version>
|
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.common</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
<artifactId>common-authorization</artifactId>
|
<artifactId>common-authorization</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
<artifactId>common-encryption</artifactId>
|
<artifactId>common-encryption</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
<artifactId>common-scope-maps</artifactId>
|
<artifactId>common-scope-maps</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
<artifactId>common-scope</artifactId>
|
<artifactId>common-scope</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.core</groupId>
|
||||||
|
<artifactId>common-encryption</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.common</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
<artifactId>storagehub-model</artifactId>
|
<artifactId>storagehub-model</artifactId>
|
||||||
|
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.gcube.data.access</groupId>
|
|
||||||
<artifactId>storagehub-script-utils</artifactId>
|
|
||||||
<version>[1.0.0, 2.0.0-SNAPSHOT)</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.itextpdf</groupId>
|
<groupId>com.itextpdf</groupId>
|
||||||
<artifactId>itextpdf</artifactId>
|
<artifactId>itextpdf</artifactId>
|
||||||
<version>5.5.13.2</version>
|
<version>5.5.13.1</version>
|
||||||
</dependency>
|
|
||||||
<!-- needed to manage strange image types -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
|
||||||
<artifactId>imageio-jpeg</artifactId>
|
|
||||||
<version>3.3.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
|
||||||
<artifactId>imageio-bmp</artifactId>
|
|
||||||
<version>3.3.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
|
||||||
<artifactId>imageio-core</artifactId>
|
|
||||||
<version>3.3.2</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
|
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
<version>1.62</version>
|
<version>1.62</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.common</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
<artifactId>gxJRS</artifactId>
|
<artifactId>gxJRS</artifactId>
|
||||||
|
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JCR dependencies -->
|
<!-- JCR dependencies -->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.jcr</groupId>
|
<groupId>javax.jcr</groupId>
|
||||||
<artifactId>jcr</artifactId>
|
<artifactId>jcr</artifactId>
|
||||||
|
@ -136,7 +142,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.jackrabbit</groupId>
|
<groupId>org.apache.jackrabbit</groupId>
|
||||||
<artifactId>jackrabbit-api</artifactId>
|
<artifactId>jackrabbit-api</artifactId>
|
||||||
<version>2.19.3</version>
|
<version>${jackrabbit.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.jackrabbit</groupId>
|
<groupId>org.apache.jackrabbit</groupId>
|
||||||
|
@ -148,159 +154,139 @@
|
||||||
<artifactId>jackrabbit-jcr-server</artifactId>
|
<artifactId>jackrabbit-jcr-server</artifactId>
|
||||||
<version>${jackrabbit.version}</version>
|
<version>${jackrabbit.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-annotations</artifactId>
|
|
||||||
<version>${jackson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-core</artifactId>
|
|
||||||
<version>${jackson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
<version>${jackson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
|
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tika</groupId>
|
<groupId>org.apache.tika</groupId>
|
||||||
<artifactId>tika-parsers</artifactId>
|
<artifactId>tika-parsers</artifactId>
|
||||||
<version>1.21</version>
|
<version>1.21</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
|
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tika</groupId>
|
<groupId>org.apache.tika</groupId>
|
||||||
<artifactId>tika-core</artifactId>
|
<artifactId>tika-core</artifactId>
|
||||||
<version>1.21</version>
|
<version>1.21</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/net.bull.javamelody/javamelody-core -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>net.bull.javamelody</groupId>
|
<!-- jersey -->
|
||||||
<artifactId>javamelody-core</artifactId>
|
|
||||||
<version>1.82.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.18.2</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- jersey & weld -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.servlet</groupId>
|
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
|
||||||
<version>3.0.1</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.interceptor</groupId>
|
|
||||||
<artifactId>javax.interceptor-api</artifactId>
|
|
||||||
<version>1.2.2</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.enterprise</groupId>
|
|
||||||
<artifactId>cdi-api</artifactId>
|
|
||||||
<version>2.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.ws.rs</groupId>
|
<groupId>javax.ws.rs</groupId>
|
||||||
<artifactId>javax.ws.rs-api</artifactId>
|
<artifactId>javax.ws.rs-api</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.containers</groupId>
|
<groupId>org.glassfish.jersey.containers</groupId>
|
||||||
<artifactId>jersey-container-servlet</artifactId>
|
<artifactId>jersey-container-servlet</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.containers</groupId>
|
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
|
||||||
<artifactId>jersey-container-servlet-core</artifactId>
|
<artifactId>jersey-gf-cdi</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.inject</groupId>
|
<groupId>javax.transaction</groupId>
|
||||||
<artifactId>jersey-hk2</artifactId>
|
<artifactId>javax.transaction-api</artifactId>
|
||||||
<version>2.30.1</version>
|
<version>1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.core</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>jersey-server</artifactId>
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- weld -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.ext.cdi</groupId>
|
<groupId>javax.enterprise</groupId>
|
||||||
<artifactId>jersey-cdi1x</artifactId>
|
<artifactId>cdi-api</artifactId>
|
||||||
</dependency>
|
<version>1.1</version>
|
||||||
<dependency>
|
|
||||||
<groupId>org.glassfish.jersey.ext.cdi</groupId>
|
|
||||||
<artifactId>jersey-cdi1x-servlet</artifactId>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.weld.servlet</groupId>
|
<groupId>org.jboss.weld.servlet</groupId>
|
||||||
<artifactId>weld-servlet-core</artifactId>
|
<artifactId>weld-servlet</artifactId>
|
||||||
<version>3.1.0.Final</version>
|
<version>2.2.10.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss</groupId>
|
<groupId>org.jboss</groupId>
|
||||||
<artifactId>jandex</artifactId>
|
<artifactId>jandex</artifactId>
|
||||||
<version>2.2.2.Final</version>
|
<version>1.2.2.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.core</groupId>
|
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||||
<artifactId>jersey-common</artifactId>
|
<artifactId>jackson-jaxrs-json-provider</artifactId>
|
||||||
|
<version>2.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.media</groupId>
|
<groupId>org.glassfish.jersey.media</groupId>
|
||||||
<artifactId>jersey-media-json-jackson</artifactId>
|
<artifactId>jersey-media-json-jackson</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.media</groupId>
|
<groupId>org.glassfish.jersey.media</groupId>
|
||||||
<artifactId>jersey-media-multipart</artifactId>
|
<artifactId>jersey-media-multipart</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>postgresql</groupId>
|
<groupId>postgresql</groupId>
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<version>9.1-901.jdbc4</version>
|
<version>9.1-901.jdbc4</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Storage dependencies -->
|
<!-- Storage dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.contentmanagement</groupId>
|
<groupId>org.gcube.contentmanagement</groupId>
|
||||||
<artifactId>storage-manager-core</artifactId>
|
<artifactId>storage-manager-core</artifactId>
|
||||||
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
|
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.contentmanagement</groupId>
|
<groupId>org.gcube.contentmanagement</groupId>
|
||||||
<artifactId>storage-manager-wrapper</artifactId>
|
<artifactId>storage-manager-wrapper</artifactId>
|
||||||
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
|
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>org.reflections</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
<version>0.9.10</version>
|
<version>0.9.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>16.0</version>
|
<version>16.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.17</version>
|
<version>1.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.tukaani</groupId>
|
<groupId>org.tukaani</groupId>
|
||||||
<artifactId>xz</artifactId>
|
<artifactId>xz</artifactId>
|
||||||
<version>1.5</version>
|
<version>1.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||||
<artifactId>jersey-test-framework-provider-simple</artifactId>
|
<artifactId>jersey-test-framework-provider-simple</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.derby</groupId>
|
<groupId>org.apache.derby</groupId>
|
||||||
<artifactId>derby</artifactId>
|
<artifactId>derby</artifactId>
|
||||||
|
@ -313,6 +299,7 @@
|
||||||
<version>10.8.2.2</version>
|
<version>10.8.2.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.jeeunit</groupId>
|
<groupId>com.googlecode.jeeunit</groupId>
|
||||||
<artifactId>jeeunit</artifactId>
|
<artifactId>jeeunit</artifactId>
|
||||||
|
@ -325,29 +312,21 @@
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.7</version>
|
<version>2.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ch.qos.logback</groupId>
|
<groupId>ch.qos.logback</groupId>
|
||||||
<artifactId>logback-classic</artifactId>
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.0.13</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.vlkan.rfos</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>rotating-fos</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>0.9.2</version>
|
<version>4.10</version>
|
||||||
</dependency>
|
<scope>test</scope>
|
||||||
<!-- enunciate deps -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.webcohesion.enunciate</groupId>
|
|
||||||
<artifactId>enunciate-core-annotations</artifactId>
|
|
||||||
<version>${enunciate.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.webcohesion.enunciate</groupId>
|
|
||||||
<artifactId>enunciate-rt-util</artifactId>
|
|
||||||
<version>${enunciate.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
|
@ -355,11 +334,14 @@
|
||||||
<version>1.9.5</version>
|
<version>1.9.5</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jul-to-slf4j</artifactId>
|
<artifactId>jul-to-slf4j</artifactId>
|
||||||
<version>${slf4j.version}</version>
|
<version>${slf4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.weld.se</groupId>
|
<groupId>org.jboss.weld.se</groupId>
|
||||||
<artifactId>weld-se</artifactId>
|
<artifactId>weld-se</artifactId>
|
||||||
|
@ -372,19 +354,24 @@
|
||||||
<version>4.11</version>
|
<version>4.11</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework</groupId>
|
<groupId>org.glassfish.jersey.test-framework</groupId>
|
||||||
<artifactId>jersey-test-framework-core</artifactId>
|
<artifactId>jersey-test-framework-core</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||||
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
|
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
|
||||||
|
<version>2.13</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<finalName>${project.artifactId}</finalName>
|
<finalName>${artifactId}</finalName>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
@ -398,6 +385,7 @@
|
||||||
<pluginExecutionFilter>
|
<pluginExecutionFilter>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>aspectj-maven-plugin</artifactId>
|
<artifactId>aspectj-maven-plugin</artifactId>
|
||||||
|
|
||||||
<versionRange>[1.0,)</versionRange>
|
<versionRange>[1.0,)</versionRange>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>test-compile</goal>
|
<goal>test-compile</goal>
|
||||||
|
@ -415,7 +403,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>aspectj-maven-plugin</artifactId>
|
<artifactId>aspectj-maven-plugin</artifactId>
|
||||||
<version>1.14.0</version>
|
<version>1.7</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<complianceLevel>1.8</complianceLevel>
|
<complianceLevel>1.8</complianceLevel>
|
||||||
<source>1.8</source>
|
<source>1.8</source>
|
||||||
|
@ -445,6 +433,7 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -465,53 +454,32 @@
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
<directory>${distroDirectory}</directory>
|
<directory>${distroDirectory}</directory>
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- Enunciate Maven plugin -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>com.webcohesion.enunciate</groupId>
|
|
||||||
<artifactId>enunciate-maven-plugin</artifactId>
|
|
||||||
<version>${enunciate.version}</version>
|
|
||||||
<configuration></configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>assemble</id>
|
|
||||||
<goals>
|
|
||||||
<goal>assemble</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!-- Copy Enunciate Documentation from your-application/docs to your-application.war -->
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<version>2.5</version>
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>descriptor.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>copy-enunciate-docs</id>
|
<id>servicearchive</id>
|
||||||
<phase>process-resources</phase>
|
<phase>install</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>copy-resources</goal>
|
<goal>single</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
|
||||||
<outputDirectory>target</outputDirectory>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<targetPath>${project.build.directory}/${project.artifactId}/api-docs</targetPath>
|
|
||||||
<directory>${project.build.directory}/api-docs</directory>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<ID></ID>
|
||||||
|
<Type>Service</Type>
|
||||||
|
<Profile>
|
||||||
|
<Description>Storage Hub Webapp</Description>
|
||||||
|
<Class>DataAccess</Class>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Packages>
|
||||||
|
<Software>
|
||||||
|
<Name>${artifactId}</Name>
|
||||||
|
<Version>${version}</Version>
|
||||||
|
<MavenCoordinates>
|
||||||
|
<groupId>${groupId}</groupId>
|
||||||
|
<artifactId>${artifactId}</artifactId>
|
||||||
|
<version>${version}</version>
|
||||||
|
</MavenCoordinates>
|
||||||
|
<Files>
|
||||||
|
<File>${build.finalName}.jar</File>
|
||||||
|
</Files>
|
||||||
|
</Software>
|
||||||
|
</Packages>
|
||||||
|
</Profile>
|
||||||
|
</Resource>
|
|
@ -1,154 +1,112 @@
|
||||||
package org.gcube.data.access.storagehub;
|
package org.gcube.data.access.storagehub;
|
||||||
|
|
||||||
import java.util.List;
|
import org.apache.jackrabbit.api.security.user.Group;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.security.AccessControlEntry;
|
||||||
|
import javax.jcr.security.Privilege;
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||||
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
import org.apache.jackrabbit.api.security.user.Authorizable;
|
import org.apache.jackrabbit.api.security.user.Authorizable;
|
||||||
import org.apache.jackrabbit.api.security.user.Group;
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
import org.apache.jackrabbit.api.security.user.UserManager;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.acls.ACL;
|
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
import lombok.extern.java.Log;
|
||||||
*
|
import lombok.extern.log4j.Log4j;
|
||||||
*
|
|
||||||
* the caller must be authorized, so i'm not passing the login also if it works on behalf of an user
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AuthorizationChecker {
|
public class AuthorizationChecker {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(AuthorizationChecker.class);
|
private static Logger log = LoggerFactory.getLogger(AuthorizationChecker.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Node2ItemConverter node2Item;
|
Node2ItemConverter node2Item;
|
||||||
|
|
||||||
@Inject
|
public void checkReadAuthorizationControl(Session session, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
||||||
PathUtil pathUtil;
|
Node node = session.getNodeByIdentifier(id);
|
||||||
|
|
||||||
@Inject
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ACLManagerInterface aclManager;
|
|
||||||
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
public void checkReadAuthorizationControl(Session session, String userToCheck, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
|
||||||
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id+": it's not a valid StorageHub node");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (item.isShared()) {
|
||||||
|
SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
|
||||||
|
|
||||||
|
if (parentShared.getUsers().getMap().keySet().contains(login)) return;
|
||||||
|
|
||||||
|
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
||||||
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentShared.getPath());
|
||||||
|
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||||
|
Authorizable userAuthorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(login);
|
||||||
|
for (AccessControlEntry entry: entries) {
|
||||||
|
log.debug("checking access right for {} with compared with {}",login, entry.getPrincipal());
|
||||||
|
Authorizable authorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(entry.getPrincipal());
|
||||||
|
//TODO; check why sometimes the next line gets a nullpointer
|
||||||
|
if (!authorizable.isGroup() && entry.getPrincipal().getName().equals(login)) return;
|
||||||
|
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
|
||||||
|
}
|
||||||
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
|
||||||
|
|
||||||
|
} else if (item.getOwner()==null || !item.getOwner().equals(login))
|
||||||
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
|
||||||
|
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
|
||||||
|
else
|
||||||
|
return retrieveSharedFolderParent(node.getParent(), session);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkWriteAuthorizationControl(Session session, String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
||||||
|
//in case of newItem the id is the parent otherwise the old node to replace
|
||||||
Node node = session.getNodeByIdentifier(id);
|
Node node = session.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id+": it's not a valid StorageHub node");
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
//checking if the item is in the owner trash folder
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's not a valid StorageHub node");
|
||||||
if(item instanceof TrashItem && item.getParentPath().equals(pathUtil.getTrashPath(userToCheck, session).toPath()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!item.isShared() && item.getOwner()!=null && item.getOwner().equals(userToCheck)) return;
|
|
||||||
|
|
||||||
if (hasParentPublicFolder(session, item)) return;
|
|
||||||
|
|
||||||
//TODO: remove when messages will be passed to a new system
|
|
||||||
String parentPath = item.getParentPath();
|
|
||||||
if (parentPath.endsWith("hl:attachments") && (parentPath.contains("/OutBox/") || parentPath.contains("/InBox/"))) {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.isShared()) {
|
|
||||||
//SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
|
|
||||||
//if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return;
|
|
||||||
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
|
||||||
List<ACL> acls = aclManager.get(item, session);
|
|
||||||
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
|
||||||
Authorizable userAuthorizable = userManager.getAuthorizable(userToCheck);
|
|
||||||
for (ACL entry: acls) {
|
|
||||||
log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPricipal());
|
|
||||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
|
||||||
|
|
||||||
if (authorizable==null) {
|
|
||||||
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPricipal());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) return;
|
|
||||||
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
|
|
||||||
}catch (Throwable e) {
|
|
||||||
log.warn("someting went wrong checking authorizations",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean hasParentPublicFolder(Session session, Item item) {
|
|
||||||
if(item==null || item.getParentPath()==null) return false;
|
|
||||||
if (item.getParentPath().replaceAll("/Home/[^/]*/"+Constants.WORKSPACE_ROOT_FOLDER_NAME,"").isEmpty() || item.getParentPath().replaceAll(Constants.SHARED_FOLDER_PATH, "").isEmpty()) {
|
|
||||||
if (item instanceof FolderItem)
|
|
||||||
return ((FolderItem) item).isPublicItem();
|
|
||||||
else return false;
|
|
||||||
} else {
|
|
||||||
if (item instanceof FolderItem)
|
|
||||||
try {
|
|
||||||
return ((FolderItem) item).isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
|
|
||||||
}catch (Throwable e) {
|
|
||||||
log.warn("error checking public parents",e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
try {
|
|
||||||
return hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
|
|
||||||
}catch (Throwable e) {
|
|
||||||
log.warn("error checking public parents",e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//newItem means that a new item will be created and id is the destination directory
|
|
||||||
public void checkWriteAuthorizationControl(Session session, String userToCheck, Item item, Node node, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
||||||
if (item==null) throw new UserNotAuthorizedException("Not valid StorageHub node");
|
|
||||||
|
|
||||||
if (Constants.WRITE_PROTECTED_FOLDER.contains(item.getName()) || Constants.WRITE_PROTECTED_FOLDER.contains(item.getTitle()))
|
if (Constants.WRITE_PROTECTED_FOLDER.contains(item.getName()) || Constants.WRITE_PROTECTED_FOLDER.contains(item.getTitle()))
|
||||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId()+": it's a protected folder");
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's a protected folder");
|
||||||
|
|
||||||
if (item.isShared()) {
|
if (item.isShared()) {
|
||||||
|
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||||
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||||
List<ACL> acls = aclManager.get(item, session);
|
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||||
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
Authorizable UserAuthorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(login);
|
||||||
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
|
|
||||||
//put it in a different method
|
//put it in a different method
|
||||||
for (ACL entry: acls) {
|
for (AccessControlEntry entry: entries) {
|
||||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
Authorizable authorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(entry.getPrincipal());
|
||||||
if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
if ((!authorizable.isGroup() && entry.getPrincipal().getName().equals(login)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
||||||
for (AccessType privilege : entry.getAccessTypes()){
|
for (Privilege privilege : entry.getPrivileges()){
|
||||||
if (isNewItem && privilege!=AccessType.READ_ONLY)
|
AccessType access = AccessType.fromValue(privilege.getName());
|
||||||
|
if (isNewItem && access!=AccessType.READ_ONLY)
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
if (!isNewItem &&
|
if (!isNewItem &&
|
||||||
(privilege==AccessType.ADMINISTRATOR || privilege==AccessType.WRITE_ALL || (privilege==AccessType.WRITE_OWNER && item.getOwner().equals(userToCheck))))
|
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(login))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -156,56 +114,72 @@ public class AuthorizationChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if(item.getOwner().equals(userToCheck))
|
if(item.getOwner().equals(login))
|
||||||
return;
|
return;
|
||||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId());
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id);
|
||||||
}
|
|
||||||
|
|
||||||
//newItem means that a new item will be created and id is the destination directory
|
|
||||||
public void checkWriteAuthorizationControl(Session session, String userToCheck , String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
||||||
//in case of newItem the id is the parent otherwise the old node to replace
|
|
||||||
Node node = session.getNodeByIdentifier(id);
|
|
||||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
|
||||||
checkWriteAuthorizationControl(session, userToCheck, item, node, isNewItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* checks if item with {id} can be moved
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void checkMoveOpsForProtectedFolders(Session session, String id) throws InvalidCallParameters, BackendGenericError, RepositoryException {
|
public void checkMoveOpsForProtectedFolders(Session session, String id) throws InvalidCallParameters, BackendGenericError, RepositoryException {
|
||||||
Node node = session.getNodeByIdentifier(id);
|
Node node = session.getNodeByIdentifier(id);
|
||||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
|
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
|
||||||
throw new InvalidCallParameters("protected folder cannot be moved or deleted");
|
throw new InvalidCallParameters("protected folder cannot be moved or deleted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
public void checkAdministratorControl(Session session, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
||||||
*
|
//TODO: riguardare questo pezzo di codice
|
||||||
* checks if {userToCheck} is an admin for {item}
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
*
|
|
||||||
*/
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+": it's not a valid StorageHub node");
|
||||||
public void checkAdministratorControl(Session session, String userToCheck, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
|
||||||
|
Node node = session.getNodeByIdentifier(item.getId());
|
||||||
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+": it's not a valid StorageHub node");
|
|
||||||
|
|
||||||
if (item.isShared()) {
|
if (item.isShared()) {
|
||||||
List<ACL> acls = aclManager.get(item, session);
|
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||||
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||||
for (ACL entry: acls) {
|
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||||
if (entry.getPricipal().equals(userToCheck)) {
|
//put it in a different method
|
||||||
for (AccessType privilege : entry.getAccessTypes()){
|
|
||||||
if (privilege==AccessType.ADMINISTRATOR)
|
SharedFolder parentShared = node2Item.getItem(parentSharedNode, Excludes.EXCLUDE_ACCOUNTING);
|
||||||
|
for (AccessControlEntry entry: entries) {
|
||||||
|
if (entry.getPrincipal().getName().equals(login) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
|
||||||
|
for (Privilege privilege : entry.getPrivileges()){
|
||||||
|
AccessType access = AccessType.fromValue(privilege.getName());
|
||||||
|
if (access==AccessType.ADMINISTRATOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
throw new UserNotAuthorizedException("The user "+userToCheck+" is not an administrator of node with id "+item.getId());
|
}
|
||||||
|
|
||||||
|
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
private String retrieveOwner(Node node) {
|
||||||
|
Node nodeOwner;
|
||||||
|
//get Owner
|
||||||
|
try{
|
||||||
|
return node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString();
|
||||||
|
}catch (Exception e) {
|
||||||
|
try {
|
||||||
|
nodeOwner = node.getNode(NodeProperty.OWNER.toString());
|
||||||
|
return nodeOwner.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString();
|
||||||
|
// this.userId = nodeOwner.getProperty(USER_ID).getString();
|
||||||
|
// this.portalLogin = nodeOwner.getProperty(PORTAL_LOGIN).getString();
|
||||||
|
// node.getSession().save();
|
||||||
|
} catch (Exception e1) {
|
||||||
|
throw new RuntimeException(e1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,7 @@ import java.util.List;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
|
public static final String VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
|
||||||
|
|
||||||
public static final String PERSONAL_VRES_FOLDER_PARENT_NAME = "VREs";
|
|
||||||
|
|
||||||
public static final String INBOX_FOLDER_NAME = "InBox";
|
|
||||||
|
|
||||||
public static final String OUTBOX_FOLDER_NAME = "OutBox";
|
|
||||||
|
|
||||||
public static final String ATTACHMENTNODE_NAME = "hl:attachments";
|
|
||||||
|
|
||||||
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe";
|
|
||||||
|
|
||||||
public static final String SHARED_FOLDER_PATH = "/Share";
|
public static final String SHARED_FOLDER_PATH = "/Share";
|
||||||
|
|
||||||
|
@ -29,11 +19,9 @@ public class Constants {
|
||||||
|
|
||||||
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
||||||
|
|
||||||
public static final String HOME_VERSION_PROP = "hl:version";
|
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
|
||||||
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
public static final List<String> WRITE_PROTECTED_FOLDER = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
|
||||||
public static final List<String> WRITE_PROTECTED_FOLDER = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.WORKSPACE_ROOT_FOLDER_NAME, Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
|
||||||
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.WORKSPACE_ROOT_FOLDER_NAME, Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PipedInputStream;
|
import java.io.PipedInputStream;
|
||||||
import java.io.PipedOutputStream;
|
import java.io.PipedOutputStream;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.ws.rs.ext.Provider;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitRepository;
|
|
||||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
|
||||||
import org.glassfish.jersey.server.monitoring.ApplicationEvent;
|
|
||||||
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
|
|
||||||
import org.glassfish.jersey.server.monitoring.RequestEvent;
|
|
||||||
import org.glassfish.jersey.server.monitoring.RequestEventListener;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Provider
|
|
||||||
public class MyApplicationListener implements ApplicationEventListener {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
RepositoryInitializer repository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEvent(ApplicationEvent event) {
|
|
||||||
log.info("StorageHub - event called");
|
|
||||||
switch (event.getType()) {
|
|
||||||
case DESTROY_FINISHED:
|
|
||||||
log.info("Destroying application storageHub");
|
|
||||||
((JackrabbitRepository) repository.getRepository()).shutdown();
|
|
||||||
log.info("Jackrabbit repository stopped");
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RequestEventListener onRequest(RequestEvent requestEvent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.NodeIterator;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
|
||||||
|
|
||||||
public class NodeChildrenFilterIterator implements Iterator<Node> {
|
|
||||||
|
|
||||||
private NodeIterator it;
|
|
||||||
|
|
||||||
public NodeChildrenFilterIterator(Node node) throws BackendGenericError{
|
|
||||||
super();
|
|
||||||
try {
|
|
||||||
it = node.getNodes();
|
|
||||||
} catch (RepositoryException e) {
|
|
||||||
throw new BackendGenericError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeChildrenFilterIterator(NodeIterator iterator) throws BackendGenericError{
|
|
||||||
it = iterator;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node currentNode = null;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
try {
|
|
||||||
while (it.hasNext()) {
|
|
||||||
currentNode=it.nextNode();
|
|
||||||
if (ClassHandler.instance().get(currentNode.getPrimaryNodeType().getName())!=null)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}catch (RepositoryException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Node next() {
|
|
||||||
return currentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.Path;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class PathUtil {
|
|
||||||
|
|
||||||
public Path getWorkspacePath(String login){
|
|
||||||
return Paths.getPath(String.format("/Home/%s/%s",login,Constants.WORKSPACE_ROOT_FOLDER_NAME));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getHome(String login){
|
|
||||||
return Paths.getPath(String.format("/Home/%s",login));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getInboxPath(String login) {
|
|
||||||
return Paths.append(getHome(login),Constants.INBOX_FOLDER_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getOutboxPath(String login) {
|
|
||||||
return Paths.append(getHome(login),Constants.OUTBOX_FOLDER_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
private Path getOldTrashPath(String login){
|
|
||||||
return Paths.append(getWorkspacePath(login),Constants.TRASH_ROOT_FOLDER_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path getNewTrashPath(String login){
|
|
||||||
return Paths.append(getHome(login), Constants.TRASH_ROOT_FOLDER_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
private Path getOldVREsPath(String login){
|
|
||||||
return Paths.append(getWorkspacePath(login),Constants.OLD_VRE_FOLDER_PARENT_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path getNewVREsPath(String login){
|
|
||||||
return Paths.append(getHome(login),Constants.PERSONAL_VRES_FOLDER_PARENT_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getSharedWithMePath(String login){
|
|
||||||
return Paths.append(getWorkspacePath(login),Constants.SHARED_WITH_ME_PARENT_NAME);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getVREsPath(String login, Session session) throws RepositoryException {
|
|
||||||
Path home = getHome(login);
|
|
||||||
Node node = session.getNode(home.toPath());
|
|
||||||
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
|
|
||||||
return getNewVREsPath(login);
|
|
||||||
else
|
|
||||||
return getOldVREsPath(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getTrashPath(String login, Session session) throws RepositoryException {
|
|
||||||
Path home = getHome(login);
|
|
||||||
Node node = session.getNode(home.toPath());
|
|
||||||
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
|
|
||||||
return getNewTrashPath(login);
|
|
||||||
else
|
|
||||||
return getOldTrashPath(login);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import javax.jcr.Repository;
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitRepository;
|
|
||||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
@ -13,22 +12,19 @@ public class RepositoryInitializerImpl implements RepositoryInitializer{
|
||||||
|
|
||||||
private Repository repository;
|
private Repository repository;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized Repository getRepository(){
|
public Repository getRepository(){
|
||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RepositoryInitializerImpl() throws Exception{
|
public RepositoryInitializerImpl() throws Exception{
|
||||||
InitialContext context = new InitialContext();
|
InitialContext context = new InitialContext();
|
||||||
Context environment = (Context) context.lookup("java:comp/env");
|
Context environment = (Context) context.lookup("java:comp/env");
|
||||||
repository = (Repository) environment.lookup("jcr/repository");
|
repository = (Repository) environment.lookup("jcr/repository");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void shutdown() {
|
|
||||||
((JackrabbitRepository)repository).shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub;
|
|
||||||
|
|
||||||
public class Roles {
|
|
||||||
|
|
||||||
public static final String VREMANAGER_ROLE = "VRE-Manager";
|
|
||||||
public static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
|
|
||||||
}
|
|
|
@ -8,16 +8,12 @@ import javax.ws.rs.core.Application;
|
||||||
|
|
||||||
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
|
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
|
||||||
import org.gcube.data.access.storagehub.services.ACLManager;
|
import org.gcube.data.access.storagehub.services.ACLManager;
|
||||||
import org.gcube.data.access.storagehub.services.DocManager;
|
|
||||||
import org.gcube.data.access.storagehub.services.GroupManager;
|
import org.gcube.data.access.storagehub.services.GroupManager;
|
||||||
import org.gcube.data.access.storagehub.services.Impersonable;
|
|
||||||
import org.gcube.data.access.storagehub.services.ItemSharing;
|
import org.gcube.data.access.storagehub.services.ItemSharing;
|
||||||
import org.gcube.data.access.storagehub.services.ItemsCreator;
|
import org.gcube.data.access.storagehub.services.ItemsCreator;
|
||||||
import org.gcube.data.access.storagehub.services.ItemsManager;
|
import org.gcube.data.access.storagehub.services.ItemsManager;
|
||||||
import org.gcube.data.access.storagehub.services.MessageManager;
|
|
||||||
import org.gcube.data.access.storagehub.services.UserManager;
|
import org.gcube.data.access.storagehub.services.UserManager;
|
||||||
import org.gcube.data.access.storagehub.services.WorkspaceManager;
|
import org.gcube.data.access.storagehub.services.WorkspaceManager;
|
||||||
import org.gcube.data.access.storagehub.services.admin.ScriptManager;
|
|
||||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||||
|
|
||||||
@Path("workspace")
|
@Path("workspace")
|
||||||
|
@ -27,7 +23,7 @@ public class StorageHub extends Application {
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
final Set<Class<?>> classes = new HashSet<Class<?>>();
|
final Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||||
// register resources and features
|
// register resources and features
|
||||||
classes.add(Impersonable.class);
|
classes.add(MultiPartFeature.class);
|
||||||
classes.add(WorkspaceManager.class);
|
classes.add(WorkspaceManager.class);
|
||||||
classes.add(ItemsManager.class);
|
classes.add(ItemsManager.class);
|
||||||
classes.add(ItemsCreator.class);
|
classes.add(ItemsCreator.class);
|
||||||
|
@ -35,12 +31,7 @@ public class StorageHub extends Application {
|
||||||
classes.add(ItemSharing.class);
|
classes.add(ItemSharing.class);
|
||||||
classes.add(UserManager.class);
|
classes.add(UserManager.class);
|
||||||
classes.add(GroupManager.class);
|
classes.add(GroupManager.class);
|
||||||
classes.add(ScriptManager.class);
|
|
||||||
classes.add(MessageManager.class);
|
|
||||||
classes.add(MultiPartFeature.class);
|
|
||||||
classes.add(SerializableErrorEntityTextWriter.class);
|
classes.add(SerializableErrorEntityTextWriter.class);
|
||||||
classes.add(MyApplicationListener.class);
|
|
||||||
classes.add(DocManager.class);
|
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub;
|
|
||||||
|
|
||||||
|
|
||||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
|
||||||
import org.gcube.smartgears.ApplicationManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class StorageHubAppllicationManager implements ApplicationManager {
|
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(StorageHubAppllicationManager.class);
|
|
||||||
|
|
||||||
private boolean alreadyShutDown = false;
|
|
||||||
|
|
||||||
|
|
||||||
public static RepositoryInitializer repository;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void onInit() {
|
|
||||||
logger.info("jackrabbit initialization started");
|
|
||||||
try {
|
|
||||||
repository = new RepositoryInitializerImpl();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("ERROR INITIALIZING REPOSITORY",e);
|
|
||||||
}
|
|
||||||
repository.getRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void onShutdown() {
|
|
||||||
if (!alreadyShutDown)
|
|
||||||
try {
|
|
||||||
logger.info("jackrabbit is shutting down");
|
|
||||||
repository.shutdown();
|
|
||||||
alreadyShutDown= true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("the database was not shutdown properly",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.gcube.data.access.storagehub;
|
package org.gcube.data.access.storagehub;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -7,10 +8,12 @@ import java.net.URL;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashSet;
|
import java.util.Deque;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
|
@ -19,36 +22,39 @@ import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.lock.Lock;
|
import javax.jcr.lock.Lock;
|
||||||
import javax.jcr.lock.LockException;
|
import javax.jcr.lock.LockException;
|
||||||
import javax.jcr.query.Query;
|
import javax.jcr.version.Version;
|
||||||
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.apache.jackrabbit.util.ISO9075;
|
|
||||||
import org.apache.jackrabbit.util.Text;
|
import org.apache.jackrabbit.util.Text;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
|
||||||
import org.gcube.common.storagehub.model.items.ExternalLink;
|
import org.gcube.common.storagehub.model.items.ExternalLink;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.RootItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
|
import org.gcube.contentmanager.storageclient.wrapper.AccessType;
|
||||||
|
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
|
||||||
|
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
|
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
public final static String SERVICE_NAME = "home-library";
|
public final static String SERVICE_NAME = "home-library";
|
||||||
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||||
private static final String FOLDERS_TYPE = "nthl:workspaceItem";
|
private static final String FOLDERS_TYPE = "nthl:workspaceItem";
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
|
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
|
||||||
|
@ -72,7 +78,7 @@ public class Utils {
|
||||||
return digest;
|
return digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
|
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
|
||||||
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
|
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,82 +107,36 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <T extends Item> List<T> searchByNameOnFolder(Session ses, String user, AuthorizationChecker authChecker, Node parent, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude, String nameParam) throws RepositoryException, BackendGenericError{
|
|
||||||
String xpath = String.format("/jcr:root%s//element(*,nthl:workspaceItem)[jcr:like(fn:lower-case(@jcr:title), '%s')]",ISO9075.encodePath(parent.getPath()), nameParam.toLowerCase());
|
|
||||||
|
|
||||||
//String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
|
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
||||||
logger.trace("query for search is {}",xpath);
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(xpath, Query.XPATH);
|
|
||||||
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(jcrQuery.execute().getNodes());
|
|
||||||
logger.trace("[SEARCH] real search took {} millis",(System.currentTimeMillis()-start));
|
|
||||||
Predicate<Node> checker = new Predicate<Node>() {
|
|
||||||
|
|
||||||
@Override
|
logger.debug("getting children of node {}", parent.getIdentifier());
|
||||||
public boolean test(Node t) {
|
|
||||||
try {
|
|
||||||
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
|
|
||||||
return true;
|
|
||||||
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, nodeTypeToInclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
|
||||||
return getItemList(null, parent, excludes, range, showHidden, nodeTypeToInclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
|
||||||
logger.trace("getting children of node {}", parent.getIdentifier());
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent);
|
|
||||||
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
|
|
||||||
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, nodeTypeToInclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
|
||||||
List<T> returnList = new ArrayList<T>();
|
List<T> returnList = new ArrayList<T>();
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
NodeIterator iterator = parent.getNodes();
|
||||||
|
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
|
||||||
logger.trace("nodeType is {}",nodeTypeToInclude);
|
logger.trace("nodeType is {}",nodeTypeToInclude);
|
||||||
int count =0;
|
int count =0;
|
||||||
logger.trace("selected range is {}", range);
|
logger.trace("selected range is {}", range);
|
||||||
Node2ItemConverter node2Item= new Node2ItemConverter();
|
Node2ItemConverter node2Item= new Node2ItemConverter();
|
||||||
Set<String> duplicateId = new HashSet<String>();
|
|
||||||
while (iterator.hasNext()){
|
while (iterator.hasNext()){
|
||||||
Node current = iterator.next();
|
Node current = iterator.nextNode();
|
||||||
|
|
||||||
logger.trace("[SEARCH] evaluating node {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
|
|
||||||
|
|
||||||
//REMOVE duplicate nodes, in case the indexes are not working
|
|
||||||
if (duplicateId.contains(current.getIdentifier())) {
|
|
||||||
logger.warn("duplicated node found");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//EXCLUDES node from predicate
|
|
||||||
if (checker!=null && !checker.test(current))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
|
logger.debug("current node "+current.getName());
|
||||||
|
|
||||||
if (isToExclude(current, showHidden))
|
if (isToExclude(current, showHidden))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
logger.trace("[SEARCH] current node not excluded {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
|
logger.debug("current node not excluded "+current.getName());
|
||||||
|
|
||||||
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
|
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
|
||||||
T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
|
T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
|
||||||
if (item==null || (item.isTrashed() && excludeTrashed)) continue;
|
if (item==null) continue;
|
||||||
returnList.add(item);
|
returnList.add(item);
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
duplicateId.add(current.getIdentifier());
|
|
||||||
}
|
}
|
||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
@ -187,10 +147,83 @@ public class Utils {
|
||||||
(node.getPrimaryNodeType().getName().equals(FOLDERS_TYPE) && Constants.FOLDERS_TO_EXLUDE.contains(node.getName())));
|
(node.getPrimaryNodeType().getName().equals(FOLDERS_TYPE) && Constants.FOLDERS_TO_EXLUDE.contains(node.getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static org.gcube.common.storagehub.model.Path getWorkspacePath(){
|
||||||
|
return Paths.getPath(String.format("/Home/%s/Workspace",AuthorizationProvider.instance.get().getClient().getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static org.gcube.common.storagehub.model.Path getWorkspacePath(String login){
|
||||||
|
return Paths.getPath(String.format("/Home/%s/Workspace",login));
|
||||||
|
}
|
||||||
|
|
||||||
public static void copyStream(InputStream in, OutputStream out) throws IOException {
|
public static org.gcube.common.storagehub.model.Path getHome(String login){
|
||||||
|
return Paths.getPath(String.format("/Home/%s",login));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Deque<Item> getAllNodesForZip(FolderItem directory, Session session, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||||
|
Deque<Item> queue = new LinkedList<Item>();
|
||||||
|
Node currentNode = session.getNodeByIdentifier(directory.getId());
|
||||||
|
queue.push(directory);
|
||||||
|
Deque<Item> tempQueue = new LinkedList<Item>();
|
||||||
|
logger.debug("adding directory {}",currentNode.getPath());
|
||||||
|
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
|
||||||
|
if (excludes.contains(item.getId())) continue;
|
||||||
|
if (item instanceof FolderItem)
|
||||||
|
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler, excludes));
|
||||||
|
else if (item instanceof AbstractFileItem){
|
||||||
|
logger.debug("adding file {}",item.getPath());
|
||||||
|
AbstractFileItem fileItem = (AbstractFileItem) item;
|
||||||
|
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), false);
|
||||||
|
queue.addLast(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queue.addAll(tempQueue);
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath, StorageBackendHandler storageHandler) throws Exception{
|
||||||
|
logger.trace("originalPath is {}",originalPath.toPath());
|
||||||
|
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
Item item = queue.pop();
|
||||||
|
if (item instanceof FolderItem) {
|
||||||
|
actualPath = Paths.getPath(item.getPath());
|
||||||
|
logger.debug("actualPath is {}",actualPath.toPath());
|
||||||
|
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
|
||||||
|
logger.debug("writing dir {}",name);
|
||||||
|
if (name.isEmpty()) continue;
|
||||||
|
try {
|
||||||
|
zos.putNextEntry(new ZipEntry(name));
|
||||||
|
}finally {
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
} else if (item instanceof AbstractFileItem){
|
||||||
|
try {
|
||||||
|
InputStream streamToWrite = storageHandler.download(((AbstractFileItem)item).getContent().getStorageId());
|
||||||
|
if (streamToWrite == null){
|
||||||
|
logger.warn("discarding item {} ",item.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
|
||||||
|
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
|
||||||
|
logger.debug("writing file {}",name);
|
||||||
|
zos.putNextEntry(new ZipEntry(name));
|
||||||
|
copyStream(is, zos);
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.warn("error writing item {}", item.getName(),e);
|
||||||
|
} finally{
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
zos.flush();
|
||||||
|
}catch (Throwable e) {
|
||||||
|
logger.warn("error reading content for item {}", item.getPath(),e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||||
byte[] buffer = new byte[2048];
|
byte[] buffer = new byte[2048];
|
||||||
int readcount = 0;
|
int readcount = 0;
|
||||||
while ((readcount=in.read(buffer))!=-1) {
|
while ((readcount=in.read(buffer))!=-1) {
|
||||||
|
@ -201,17 +234,40 @@ public class Utils {
|
||||||
|
|
||||||
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
|
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
|
||||||
Node2ItemConverter node2Item = new Node2ItemConverter();
|
Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||||
NodeChildrenFilterIterator children = new NodeChildrenFilterIterator(node);
|
NodeIterator children = node.getNodes();
|
||||||
|
|
||||||
while (children.hasNext()) {
|
while (children.hasNext()) {
|
||||||
Node child= children.next();
|
Node child= children.nextNode();
|
||||||
if (node2Item.checkNodeType(child, SharedFolder.class)) return true;
|
if (node2Item.checkNodeType(child, SharedFolder.class)) return true;
|
||||||
if (node2Item.checkNodeType(child, FolderItem.class) && hasSharedChildren(child)) return true;
|
if (node2Item.checkNodeType(child, FolderItem.class) && hasSharedChildren(child)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void getAllContentIds(Session ses, Set<String> idsToDelete, Item itemToDelete, VersionHandler versionHandler) throws Exception{
|
||||||
|
if (itemToDelete instanceof AbstractFileItem) {
|
||||||
|
List<Version> versions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(itemToDelete.getId()), ses);
|
||||||
|
|
||||||
|
versions.forEach(v -> {
|
||||||
|
try {
|
||||||
|
String storageId =v.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
|
||||||
|
idsToDelete.add(storageId);
|
||||||
|
logger.info("retrieved StorageId {} for version {}", storageId, v.getName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("error retreiving sotrageId version for item with id {}",itemToDelete.getId(),e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
idsToDelete.add(((AbstractFileItem) itemToDelete).getContent().getStorageId());
|
||||||
|
}else if (itemToDelete instanceof FolderItem) {
|
||||||
|
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(itemToDelete.getId()), Excludes.GET_ONLY_CONTENT , null, true, null);
|
||||||
|
for (Item item: items)
|
||||||
|
getAllContentIds(ses, idsToDelete, item, versionHandler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
|
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
|
||||||
try {
|
try {
|
||||||
destination.getNode(name);
|
destination.getNode(name);
|
||||||
|
@ -227,7 +283,7 @@ public class Utils {
|
||||||
|
|
||||||
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
|
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
|
||||||
|
|
||||||
logger.trace("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
|
logger.debug("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
|
||||||
|
|
||||||
NodeIterator ni = destination.getNodes(nameTocheck);
|
NodeIterator ni = destination.getNodes(nameTocheck);
|
||||||
int maxval = 0;
|
int maxval = 0;
|
||||||
|
@ -246,46 +302,32 @@ public class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Node createFolderInternally(Session ses, Node destinationNode, String name, String description, boolean hidden, String login, AccountingHandler accountingHandler) throws BackendGenericError {
|
||||||
|
|
||||||
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler) throws StorageHubException {
|
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
|
||||||
logger.debug("creating folder {} in {}", params.getName(), params.getParentId());
|
|
||||||
|
|
||||||
Node destinationNode;
|
|
||||||
try {
|
|
||||||
destinationNode = params.getSession().getNodeByIdentifier(params.getParentId());
|
|
||||||
}catch (RepositoryException e) {
|
|
||||||
throw new IdNotFoundException(params.getParentId());
|
|
||||||
}
|
|
||||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName());
|
|
||||||
|
|
||||||
FolderItem item = new FolderItem();
|
FolderItem item = new FolderItem();
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
item.setName(uniqueName);
|
item.setName(uniqueName);
|
||||||
item.setTitle(uniqueName);
|
item.setTitle(uniqueName);
|
||||||
item.setDescription(params.getDescription());
|
item.setDescription(description);
|
||||||
//TODO: item.setExternalStorage();
|
|
||||||
//item.setCreationTime(now);
|
//item.setCreationTime(now);
|
||||||
|
item.setHidden(hidden);
|
||||||
boolean hiddenDestNode= false;
|
|
||||||
try {
|
|
||||||
hiddenDestNode = destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean();
|
|
||||||
}catch (Throwable e) {}
|
|
||||||
|
|
||||||
item.setHidden(params.isHidden() || hiddenDestNode);
|
|
||||||
item.setLastAction(ItemAction.CREATED);
|
item.setLastAction(ItemAction.CREATED);
|
||||||
item.setLastModificationTime(now);
|
item.setLastModificationTime(now);
|
||||||
item.setLastModifiedBy(params.getUser());
|
item.setLastModifiedBy(login);
|
||||||
item.setOwner(params.getUser());
|
item.setOwner(login);
|
||||||
item.setPublicItem(false);
|
item.setPublicItem(false);
|
||||||
|
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
||||||
if (accountingHandler!=null) {
|
if (accountingHandler!=null)
|
||||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), null, params.getSession(), params.getUser(), destinationNode, false);
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||||
accountingHandler.createEntryCreate(item.getTitle(), params.getSession(), newNode, params.getUser(), false);
|
|
||||||
}
|
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Node createURLInternally(Session ses, Node destinationNode, String name, URL value, String description, String login, AccountingHandler accountingHandler) throws BackendGenericError {
|
public static Node createURLInternally(Session ses, Node destinationNode, String name, URL value, String description, String login, AccountingHandler accountingHandler) throws BackendGenericError {
|
||||||
|
|
||||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
|
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
|
||||||
|
@ -302,20 +344,13 @@ public class Utils {
|
||||||
item.setOwner(login);
|
item.setOwner(login);
|
||||||
item.setPublicItem(false);
|
item.setPublicItem(false);
|
||||||
item.setValue(value);
|
item.setValue(value);
|
||||||
|
|
||||||
try {
|
//to inherit hidden property
|
||||||
item.setHidden(destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean());
|
//item.setHidden(destinationItem.isHidden());
|
||||||
} catch (Throwable e) {
|
|
||||||
item.setHidden(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
||||||
if (accountingHandler!=null) {
|
if (accountingHandler!=null)
|
||||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||||
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
|
|
||||||
}
|
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +380,4 @@ public class Utils {
|
||||||
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), login);
|
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), login);
|
||||||
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import javax.jcr.version.VersionHistory;
|
||||||
import javax.jcr.version.VersionIterator;
|
import javax.jcr.version.VersionIterator;
|
||||||
import javax.jcr.version.VersionManager;
|
import javax.jcr.version.VersionManager;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
|
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -36,7 +37,7 @@ public class AccountingHandler {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
||||||
|
|
||||||
public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
public void createReadObj(String title, Session ses, Node node, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -46,7 +47,7 @@ public class AccountingHandler {
|
||||||
|
|
||||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.READ.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.READ.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
|
|
||||||
|
@ -69,26 +70,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createEntryCreate(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
public void createFileUpdated(String title, Session ses, Node node, boolean saveHistory ) {
|
||||||
try {
|
|
||||||
|
|
||||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
|
||||||
node.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.CREATE.getNodeTypeDefinition());
|
|
||||||
accountingNode.setProperty(USER, login);
|
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
|
||||||
|
|
||||||
if (saveHistory) ses.save();
|
|
||||||
} catch (RepositoryException e) {
|
|
||||||
logger.warn("error trying to retrieve accountign node",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createFileUpdated(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -98,7 +80,7 @@ public class AccountingHandler {
|
||||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
|
||||||
|
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
|
|
||||||
|
@ -125,17 +107,17 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
|
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, Node node, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
Node directoryNode = node.getParent();
|
||||||
|
|
||||||
|
if (!directoryNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
directoryNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
||||||
parentNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = directoryNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.ADD.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.ADD.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
accountingNode.setProperty(ITEM_TYPE, itemType);
|
accountingNode.setProperty(ITEM_TYPE, itemType);
|
||||||
|
@ -148,7 +130,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
|
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, Node parentNode, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -157,7 +139,7 @@ public class AccountingHandler {
|
||||||
|
|
||||||
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.REMOVAL.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.REMOVAL.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
accountingNode.setProperty(ITEM_TYPE, itemType);
|
accountingNode.setProperty(ITEM_TYPE, itemType);
|
||||||
|
@ -170,7 +152,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, String login, boolean saveHistory ) {
|
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -179,7 +161,7 @@ public class AccountingHandler {
|
||||||
|
|
||||||
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
accountingNode.setProperty(MEMBERS, users.toArray(new String[users.size()]));
|
accountingNode.setProperty(MEMBERS, users.toArray(new String[users.size()]));
|
||||||
|
@ -190,7 +172,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createUnshareFolder(String title, Session ses, String user, Node sharedNode, boolean saveHistory ) {
|
public void createUnshareFolder(String title, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -198,8 +180,8 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UNSHARE.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, user);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(ITEM_NAME, title);
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
|
|
||||||
|
@ -209,7 +191,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRename(String oldTitle, String newTitle, Node node, String login, Session ses, boolean saveHistory ) {
|
public void createRename(String oldTitle, String newTitle, Node node, Session ses, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -218,7 +200,7 @@ public class AccountingHandler {
|
||||||
|
|
||||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.RENAMING.getNodeTypeDefinition());
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.RENAMING.getNodeTypeDefinition());
|
||||||
accountingNode.setProperty(USER, login);
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
accountingNode.setProperty(OLD_ITEM_NAME, oldTitle);
|
accountingNode.setProperty(OLD_ITEM_NAME, oldTitle);
|
||||||
accountingNode.setProperty(NEW_ITEM_NAME, newTitle);
|
accountingNode.setProperty(NEW_ITEM_NAME, newTitle);
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package org.gcube.data.access.storagehub.handlers;
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
import org.gcube.common.storagehub.model.annotations.RootNode;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.RootItem;
|
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -27,37 +24,31 @@ public class ClassHandler {
|
||||||
|
|
||||||
private Reflections reflection = new Reflections();
|
private Reflections reflection = new Reflections();
|
||||||
|
|
||||||
private List<String> deprecatedNode = Arrays.asList("nthl:query", "nthl:aquamapsItem", "nthl:timeSeriesItem", "nthl:report", "nthl:reportTemplate", "nthl:workflowReport",
|
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
|
||||||
"nthl:workflowTemplate", "nthl:gCubeMetadata", "nthl:gCubeDocument", "nthl:gCubeDocumentLink", "nthl:gCubeImageDocumentLink", "nthl:gCubePDFDocumentLink",
|
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
|
||||||
"nthl:gCubeImageDocument", "nthl:gCubePDFDocument", "nthl:gCubeURLDocument", "nthl:gCubeAnnotation", "nthl:externalResourceLink", "nthl:tabularDataLink");
|
|
||||||
|
|
||||||
private Map<String, Class<? extends RootItem>> classMap = new HashMap<String, Class<? extends RootItem>>();
|
|
||||||
private Map<Class<? extends RootItem>, String> typeMap = new HashMap<Class<? extends RootItem>, String>();
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private ClassHandler() {
|
private ClassHandler() {
|
||||||
|
|
||||||
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
||||||
for (Class<?> clazz: classesAnnotated ){
|
for (Class<?> clazz: classesAnnotated ){
|
||||||
if (RootItem.class.isAssignableFrom(clazz)) {
|
if (Item.class.isAssignableFrom(clazz)) {
|
||||||
String value = clazz.getAnnotation(RootNode.class).value();
|
String value = clazz.getAnnotation(RootNode.class).value();
|
||||||
log.debug("loading class {} with value {} ", clazz, value );
|
log.debug("loading class {} with value {} ", clazz, value );
|
||||||
classMap.put(value, (Class<? extends RootItem>) clazz);
|
classMap.put(value, (Class<? extends Item>) clazz);
|
||||||
typeMap.put((Class<? extends RootItem>) clazz, value);
|
typeMap.put((Class<? extends Item>) clazz, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Class<? extends RootItem> get(String nodeType){
|
public Class<? extends Item> get(String nodeType){
|
||||||
if (classMap.containsKey(nodeType)) return classMap.get(nodeType);
|
if (classMap.containsKey(nodeType)) return classMap.get(nodeType);
|
||||||
if (deprecatedNode.contains(nodeType)) return Item.class;
|
else return Item.class;
|
||||||
return null;
|
|
||||||
//throw new RuntimeException("mapping not found for nodetype "+ nodeType);
|
//throw new RuntimeException("mapping not found for nodetype "+ nodeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNodeType(Class<? extends RootItem> clazz){
|
public String getNodeType(Class<? extends Item> clazz){
|
||||||
if (typeMap.containsKey(clazz)) return typeMap.get(clazz);
|
if (typeMap.containsKey(clazz)) return typeMap.get(clazz);
|
||||||
throw new RuntimeException("mapping not found for nodetype "+ clazz.getSimpleName());
|
throw new RuntimeException("mapping not found for nodetype "+ clazz.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class CompressHandler {
|
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(CompressHandler.class);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
FolderPluginHandler pluginHandler;
|
|
||||||
|
|
||||||
public Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
|
|
||||||
Deque<Item> queue = new LinkedList<Item>();
|
|
||||||
Node currentNode = session.getNodeByIdentifier(directory.getId());
|
|
||||||
queue.push(directory);
|
|
||||||
Deque<Item> tempQueue = new LinkedList<Item>();
|
|
||||||
logger.trace("adding directory {}",currentNode.getPath());
|
|
||||||
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
|
|
||||||
if (excludes.contains(item.getId())) continue;
|
|
||||||
if (item instanceof FolderItem)
|
|
||||||
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, login, accountingHandler, excludes));
|
|
||||||
else if (item instanceof AbstractFileItem){
|
|
||||||
logger.trace("adding file {}",item.getPath());
|
|
||||||
AbstractFileItem fileItem = (AbstractFileItem) item;
|
|
||||||
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
|
|
||||||
queue.addLast(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queue.addAll(tempQueue);
|
|
||||||
return queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath) throws Exception{
|
|
||||||
logger.trace("originalPath is {}",originalPath.toPath());
|
|
||||||
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
|
|
||||||
while (!queue.isEmpty()) {
|
|
||||||
Item item = queue.pop();
|
|
||||||
if (item instanceof FolderItem) {
|
|
||||||
actualPath = Paths.getPath(item.getPath());
|
|
||||||
logger.trace("actualPath is {}",actualPath.toPath());
|
|
||||||
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
|
|
||||||
logger.trace("writing dir {}",name);
|
|
||||||
if (name.isEmpty()) continue;
|
|
||||||
try {
|
|
||||||
zos.putNextEntry(new ZipEntry(name));
|
|
||||||
}finally {
|
|
||||||
zos.closeEntry();
|
|
||||||
}
|
|
||||||
} else if (item instanceof AbstractFileItem){
|
|
||||||
try {
|
|
||||||
AbstractFileItem fileItem = (AbstractFileItem)item;
|
|
||||||
FolderManager manager = pluginHandler.getFolderManager(fileItem);
|
|
||||||
InputStream streamToWrite = manager.getStorageBackend().download(fileItem.getContent());
|
|
||||||
if (streamToWrite == null){
|
|
||||||
logger.warn("discarding item {} ",item.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
|
|
||||||
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
|
|
||||||
logger.trace("writing file {}",name);
|
|
||||||
zos.putNextEntry(new ZipEntry(name));
|
|
||||||
Utils.copyStream(is, zos);
|
|
||||||
}catch (Exception e) {
|
|
||||||
logger.warn("error writing item {}", item.getName(),e);
|
|
||||||
} finally{
|
|
||||||
zos.closeEntry();
|
|
||||||
}
|
|
||||||
zos.flush();
|
|
||||||
}catch (Throwable e) {
|
|
||||||
logger.warn("error reading content for item {}", item.getPath(),e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zos.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.ItemNotFoundException;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.NodeIterator;
|
|
||||||
import javax.jcr.PathNotFoundException;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
||||||
import org.apache.jackrabbit.api.security.user.Group;
|
|
||||||
import org.apache.jackrabbit.api.security.user.User;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.services.GroupManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class GroupHandler {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
public boolean removeUserFromGroup(String groupId, String userId, JackrabbitSession session) throws StorageHubException, RepositoryException {
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
|
||||||
|
|
||||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
|
||||||
User user = (User)usrManager.getAuthorizable(userId);
|
|
||||||
|
|
||||||
if (!group.isMember(user))
|
|
||||||
throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId);
|
|
||||||
|
|
||||||
//delete folder on user
|
|
||||||
String folderName = group.getPrincipal().getName();
|
|
||||||
Node folder = getFolderNodeRelatedToGroup(session, folderName);
|
|
||||||
|
|
||||||
NodeIterator ni = folder.getSharedSet();
|
|
||||||
while (ni.hasNext()) {
|
|
||||||
Node node = ni.nextNode();
|
|
||||||
if (node.getPath().startsWith(pathUtil.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
|
|
||||||
node.removeShare();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return group.removeMember(user);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Node getFolderNodeRelatedToGroup(JackrabbitSession session, String name) throws ItemNotFoundException, RepositoryException {
|
|
||||||
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
|
||||||
|
|
||||||
Node vreFolder = null;
|
|
||||||
try {
|
|
||||||
vreFolder = sharedRootNode.getNode(name);
|
|
||||||
}catch (PathNotFoundException e) {
|
|
||||||
log.debug("is an old HL VRE");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vreFolder==null) {
|
|
||||||
NodeIterator nodes = sharedRootNode.getNodes();
|
|
||||||
while (nodes.hasNext()) {
|
|
||||||
Node node = nodes.nextNode();
|
|
||||||
if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
|
|
||||||
vreFolder= node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vreFolder==null) throw new ItemNotFoundException("vre folder not found for group "+name);
|
|
||||||
return vreFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items;
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -31,16 +31,11 @@ import org.gcube.common.storagehub.model.annotations.ListNodes;
|
||||||
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
import org.gcube.common.storagehub.model.annotations.RootNode;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.RootItem;
|
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.data.access.storagehub.NodeChildrenFilterIterator;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -49,7 +44,7 @@ public class Item2NodeConverter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
|
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
|
||||||
|
|
||||||
public <T extends RootItem> Node getNode(Node parentNode, T item){
|
public <T extends Item> Node getNode(Node parentNode, T item){
|
||||||
try {
|
try {
|
||||||
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
|
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
|
||||||
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
||||||
|
@ -61,7 +56,7 @@ public class Item2NodeConverter {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
try{
|
try{
|
||||||
//Class<?> returnType = field.getType();
|
//Class<?> returnType = field.getType();
|
||||||
logger.trace("creating node - added field {}",field.getName());
|
logger.debug("creating node - added field {}",field.getName());
|
||||||
Values values = getObjectValue(field.getType(), field.get(item));
|
Values values = getObjectValue(field.getType(), field.get(item));
|
||||||
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||||
else newNode.setProperty(attribute.value(), values.getValue());
|
else newNode.setProperty(attribute.value(), values.getValue());
|
||||||
|
@ -72,14 +67,14 @@ public class Item2NodeConverter {
|
||||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||||
if (nodeAttribute.isReadOnly()) continue;
|
if (nodeAttribute.isReadOnly()) continue;
|
||||||
String nodeName = nodeAttribute.value();
|
String nodeName = nodeAttribute.value();
|
||||||
logger.trace("retrieving field node "+field.getName());
|
logger.debug("retrieving field node "+field.getName());
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
try{
|
try{
|
||||||
Object obj = field.get(item);
|
Object obj = field.get(item);
|
||||||
if (obj!=null)
|
if (obj!=null)
|
||||||
iterateItemNodeAttributeFields(obj, newNode, nodeName);
|
iterateItemNodeAttributeFields(obj, newNode, nodeName);
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value",e);
|
logger.warn("error setting value",e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,7 +113,7 @@ public class Item2NodeConverter {
|
||||||
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||||
else newNode.setProperty(attribute.value(), values.getValue());
|
else newNode.setProperty(attribute.value(), values.getValue());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value",e);
|
logger.warn("error setting value",e);
|
||||||
}
|
}
|
||||||
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
||||||
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
||||||
|
@ -130,11 +125,11 @@ public class Item2NodeConverter {
|
||||||
if (values.isMulti()) newNode.setProperty(entry.getKey(), values.getValues());
|
if (values.isMulti()) newNode.setProperty(entry.getKey(), values.getValues());
|
||||||
else newNode.setProperty(entry.getKey(), values.getValue());
|
else newNode.setProperty(entry.getKey(), values.getValue());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value",e);
|
logger.warn("error setting value",e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (field.isAnnotationPresent(ListNodes.class)){
|
} else if (field.isAnnotationPresent(ListNodes.class)){
|
||||||
logger.trace("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
List<Object> toSetList = (List<Object>) field.get(object);
|
List<Object> toSetList = (List<Object>) field.get(object);
|
||||||
|
|
||||||
|
@ -150,7 +145,7 @@ public class Item2NodeConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes" })
|
@SuppressWarnings({ "rawtypes" })
|
||||||
public static Values getObjectValue(Class returnType, Object value) throws Exception{
|
private Values getObjectValue(Class returnType, Object value) throws Exception{
|
||||||
|
|
||||||
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
|
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
|
||||||
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
|
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
|
||||||
|
@ -209,7 +204,7 @@ public class Item2NodeConverter {
|
||||||
else contentNode.setProperty(attribute.value(), values.getValue());
|
else contentNode.setProperty(attribute.value(), values.getValue());
|
||||||
|
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value for attribute "+attribute.value(),e);
|
logger.warn("error setting value for attribute "+attribute.value(),e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,41 +216,11 @@ public class Item2NodeConverter {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateHidden(Node node, Boolean hidden,String login) throws RepositoryException {
|
|
||||||
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
|
||||||
node.setProperty(NodeProperty.HIDDEN.toString(), hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDescription(Node node, String description,String login) throws RepositoryException {
|
|
||||||
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
|
||||||
node.setProperty(NodeProperty.DESCRIPTION.toString(), description);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateOwnerOnSubTree(Node node, String owner) throws RepositoryException, BackendGenericError {
|
|
||||||
Class<? extends Item> classToHandle = (Class<? extends Item>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
|
||||||
if (classToHandle==null) return;
|
|
||||||
if (classToHandle.isAssignableFrom(FolderItem.class)) {
|
|
||||||
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(node);
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Node nextNode = iterator.next();
|
|
||||||
updateOwnerOnSubTree(nextNode, owner);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateOwner(node, owner);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateOwner(Node node, String owner) throws RepositoryException {
|
|
||||||
//Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
|
||||||
if (node.hasProperty(NodeProperty.PORTAL_LOGIN.toString()))
|
|
||||||
node.setProperty(NodeProperty.PORTAL_LOGIN.toString(), owner);
|
|
||||||
else logger.debug("cannot set new owner to {} "+node.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
public <I extends Item> void updateMetadataNode(Node node, Map<String, Object> meta, String login){
|
public <I extends Item> void updateMetadataNode(Node node, Map<String, Object> meta, String login){
|
||||||
try {
|
try {
|
||||||
|
|
||||||
//TODO: make a method to update item not only metadata, check if the new metadata has an intersection with the old one to remove properties not needed
|
//TODO: make a method to update item not only metadata, check if the new metadata has an intersection with the old one to remove properties not needed
|
||||||
|
|
||||||
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
||||||
|
|
||||||
Node metadataNode;
|
Node metadataNode;
|
||||||
|
@ -281,7 +246,7 @@ public class Item2NodeConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value",e);
|
logger.warn("error setting value",e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items;
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -21,27 +21,21 @@ import javax.jcr.Property;
|
||||||
import javax.jcr.PropertyIterator;
|
import javax.jcr.PropertyIterator;
|
||||||
import javax.jcr.PropertyType;
|
import javax.jcr.PropertyType;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.jcr.Value;
|
import javax.jcr.Value;
|
||||||
import javax.jcr.version.Version;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.jackrabbit.util.Text;
|
import org.apache.jackrabbit.util.Text;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.annotations.Attribute;
|
import org.gcube.common.storagehub.model.annotations.Attribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
|
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
|
||||||
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
||||||
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.items.ExternalFolder;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.RootItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.common.storagehub.model.messages.Message;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
|
||||||
import org.reflections.Configuration;
|
import org.reflections.Configuration;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
import org.reflections.util.ConfigurationBuilder;
|
||||||
|
@ -49,55 +43,34 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public class Node2ItemConverter {
|
public class Node2ItemConverter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
|
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
|
||||||
|
|
||||||
|
private static HashMap<Class, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
|
||||||
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
|
|
||||||
|
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
||||||
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||||
if (classToHandle==null) return null;
|
|
||||||
if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
|
if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
|
||||||
else return retrieveItem(node, excludes, classToHandle);
|
else return retrieveItem(node, excludes, classToHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends Item> T getItem(String nodeIdentifier, Session session, List<String> excludes) throws RepositoryException, BackendGenericError{
|
|
||||||
Node node = session.getNodeByIdentifier(nodeIdentifier);
|
|
||||||
return getItem(node, excludes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Item> T getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError{
|
public <T extends Item> T getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||||
if (classToHandle==null) return null;
|
/*Node nodeToRetrieve= node;
|
||||||
T item = retrieveItem(node, excludes, classToHandle);
|
if (SharedFolder.class.isAssignableFrom(classToHandle)) {
|
||||||
return item;
|
NodeIterator it= node.getSharedSet();
|
||||||
}
|
while (it.hasNext()) {
|
||||||
|
Node sharedNode = it.nextNode();
|
||||||
public Content getContentFromVersion(Version node) throws RepositoryException, BackendGenericError{
|
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath().toPath())) {
|
||||||
Content content = new Content();
|
nodeToRetrieve = sharedNode;
|
||||||
setGenericFields(node.getFrozenNode(), Content.class, null, content);
|
}
|
||||||
return content;
|
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
public Message getMessageItem(Node node) throws RepositoryException{
|
return retrieveItem(node, excludes, classToHandle);
|
||||||
if (!(node.getPrimaryNodeType().getName().equals("nthl:itemSentRequest")
|
|
||||||
|| node.getPrimaryNodeType().getName().equals("nthl:itemSentRequestSH")))
|
|
||||||
return null;
|
|
||||||
Message msg = new Message();
|
|
||||||
try {
|
|
||||||
Node attachmentNode = node.getNode(Constants.ATTACHMENTNODE_NAME);
|
|
||||||
msg.setWithAttachments(attachmentNode.hasNodes());
|
|
||||||
}catch (Throwable e) {
|
|
||||||
msg.setWithAttachments(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setRootItemCommonFields(node, Collections.emptyList(), Message.class, msg);
|
|
||||||
return msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,99 +81,79 @@ public class Node2ItemConverter {
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
throw new BackendGenericError(e);
|
throw new BackendGenericError(e);
|
||||||
}
|
}
|
||||||
|
item.setId(node.getIdentifier());
|
||||||
try {
|
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
|
||||||
item.setShared(SharedFolder.class.isInstance(item) ||
|
|
||||||
hasTypedParent(node, SharedFolder.class));
|
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
|
||||||
}catch (Exception e) {
|
|
||||||
item.setShared(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
item.setTrashed(TrashItem.class.isInstance(item) ||
|
|
||||||
hasTypedParent(node, TrashItem.class));
|
|
||||||
}catch (Exception e) {
|
|
||||||
item.setTrashed(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
item.setExternalManaged(hasTypedParent(node, ExternalFolder.class));
|
|
||||||
}catch (Exception e) {
|
|
||||||
item.setExternalManaged(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
item.setLocked(node.isLocked());
|
item.setLocked(node.isLocked());
|
||||||
|
item.setPrimaryType(node.getPrimaryNodeType().getName());
|
||||||
|
Item parent = null ;
|
||||||
|
if (item instanceof SharedFolder) {
|
||||||
|
logger.trace("I'm in a Shared Folder");
|
||||||
|
item.setShared(true);
|
||||||
|
}else {
|
||||||
|
try {
|
||||||
|
parent = getItem(node.getParent(), Excludes.ALL);
|
||||||
|
item.setShared(parent.isShared());
|
||||||
|
} catch(Exception e) {
|
||||||
|
item.setShared(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setRootItemCommonFields(node, excludes, classToHandle, item);
|
if (item instanceof TrashItem)
|
||||||
|
item.setTrashed(true);
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
if (parent==null)
|
||||||
|
parent = getItem(node.getParent(), Excludes.ALL);
|
||||||
|
item.setTrashed(parent.isTrashed());
|
||||||
|
} catch(Exception e) {
|
||||||
|
item.setTrashed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
|
|
||||||
if(node==null) return false;
|
|
||||||
return checkNodeType(node, parentType) || hasTypedParent(node.getParent(), parentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private <T extends RootItem> void setRootItemCommonFields(Node node, List<String> excludes, Class<T> classToHandle, T instance) throws RepositoryException{
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
instance.setParentId(node.getParent().getIdentifier());
|
item.setParentId(node.getParent().getIdentifier());
|
||||||
instance.setParentPath(node.getParent().getPath());
|
item.setParentPath(node.getParent().getPath());
|
||||||
}catch (Throwable e) {
|
}catch (Throwable e) {
|
||||||
logger.trace("Root node doesn't have a parent");
|
logger.trace("Root node doesn't have a parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.setRelatedNode(node);
|
|
||||||
|
|
||||||
instance.setId(node.getIdentifier());
|
|
||||||
instance.setName(Text.unescapeIllegalJcrChars(node.getName()));
|
|
||||||
|
|
||||||
instance.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
|
|
||||||
|
|
||||||
instance.setPrimaryType(node.getPrimaryNodeType().getName());
|
|
||||||
|
|
||||||
setGenericFields(node, classToHandle, excludes, instance);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void setGenericFields(Node node, Class<T> classToHandle,List<String> excludes, T instance){
|
|
||||||
for (Field field : retrieveAllFields(classToHandle)){
|
for (Field field : retrieveAllFields(classToHandle)){
|
||||||
if (field.isAnnotationPresent(Attribute.class)){
|
if (field.isAnnotationPresent(Attribute.class)){
|
||||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
try{
|
try{
|
||||||
Class<?> returnType = field.getType();
|
Class<?> returnType = field.getType();
|
||||||
field.set(instance, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||||
logger.trace("retrieve item - added field {}",field.getName());
|
logger.debug("retrieve item - added field {}",field.getName());
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value for property {} ",attribute.value());
|
logger.warn("error setting value for property {} ",attribute.value());
|
||||||
}
|
}
|
||||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||||
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
|
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
|
||||||
//for now it excludes only first level node
|
//for now it excludes only first level node
|
||||||
if (excludes!=null && excludes.contains(fieldNodeName)) continue;
|
if (excludes!=null && excludes.contains(fieldNodeName)) continue;
|
||||||
//for now it excludes only first level node
|
|
||||||
logger.trace("retrieving field node "+field.getName());
|
logger.trace("retrieving field node "+field.getName());
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
try{
|
try{
|
||||||
Node fieldNode = node.getNode(fieldNodeName);
|
Node fieldNode = node.getNode(fieldNodeName);
|
||||||
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
|
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
|
||||||
field.set(instance, iterateNodeAttributeFields(field.getType(), fieldNode));
|
field.set(item, iterateNodeAttributeFields(field.getType(), fieldNode));
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.trace("the current node dosn't contain {} node",fieldNodeName);
|
logger.trace("the current node dosn't contain {} node",fieldNodeName);
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value",e);
|
logger.warn("error setting value",e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
||||||
|
@ -210,12 +163,13 @@ public class Node2ItemConverter {
|
||||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
try{
|
try{
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
Class returnType = field.getType();
|
Class returnType = field.getType();
|
||||||
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value {}",e.getMessage());
|
logger.warn("error setting value {}",e.getMessage());
|
||||||
}
|
}
|
||||||
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
||||||
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
|
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
|
||||||
|
@ -234,7 +188,7 @@ public class Node2ItemConverter {
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.warn("the property {} is not mapped",prop.getName());
|
logger.warn("the property {} is not mapped",prop.getName());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.debug("error setting value {}",e.getMessage());
|
logger.warn("error setting value {}",e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -298,7 +252,7 @@ public class Node2ItemConverter {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
||||||
if (returnType.equals(String.class)) return prop.getString();
|
if (returnType.equals(String.class)) return prop.getString();
|
||||||
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
|
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
|
||||||
|
@ -329,7 +283,7 @@ public class Node2ItemConverter {
|
||||||
}while ((currentClass =currentClass.getSuperclass())!=null);
|
}while ((currentClass =currentClass.getSuperclass())!=null);
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getPropertyValue(Property prop) throws Exception{
|
private Object getPropertyValue(Property prop) throws Exception{
|
||||||
if (prop.isMultiple()){
|
if (prop.isMultiple()){
|
||||||
Object[] values = new Object[prop.getValues().length];
|
Object[] values = new Object[prop.getValues().length];
|
||||||
|
@ -341,7 +295,7 @@ public class Node2ItemConverter {
|
||||||
return getSingleValue(prop.getValue());
|
return getSingleValue(prop.getValue());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object getSingleValue(Value value) throws Exception{
|
private Object getSingleValue(Value value) throws Exception{
|
||||||
switch (value.getType()) {
|
switch (value.getType()) {
|
||||||
case PropertyType.DATE:
|
case PropertyType.DATE:
|
||||||
|
@ -354,7 +308,7 @@ public class Node2ItemConverter {
|
||||||
return value.getString();
|
return value.getString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object[] getArrayValue(Property prop) throws Exception{
|
private Object[] getArrayValue(Property prop) throws Exception{
|
||||||
Object[] values = new Object[prop.getValues().length];
|
Object[] values = new Object[prop.getValues().length];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -363,18 +317,17 @@ public class Node2ItemConverter {
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks if a node is a subtype of classToCompare
|
|
||||||
public boolean checkNodeType(Node node, Class<? extends Item> classToCompare) throws BackendGenericError{
|
public boolean checkNodeType(Node node, Class<? extends Item> classToCompare) throws BackendGenericError{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
logger.trace("class from nodetype is {} and class to compare is {}",ClassHandler.instance().get(node.getPrimaryNodeType().getName()), classToCompare);
|
logger.info("class from nodetype is {} and class to compare is {}",ClassHandler.instance().get(node.getPrimaryNodeType().getName()), classToCompare);
|
||||||
|
|
||||||
return classToCompare.isAssignableFrom(ClassHandler.instance().get(node.getPrimaryNodeType().getName()));
|
return classToCompare.isAssignableFrom(ClassHandler.instance().get(node.getPrimaryNodeType().getName()));
|
||||||
|
|
||||||
//(node.isNodeType(ClassHandler.instance().getNodeType(classToCompare)));
|
//(node.isNodeType(ClassHandler.instance().getNodeType(classToCompare)));
|
||||||
}catch (Throwable e) {
|
}catch (Throwable e) {
|
||||||
throw new BackendGenericError(e);
|
throw new BackendGenericError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||||
|
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
|
||||||
|
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class StorageBackendHandler {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private GCubeStorageBackend defaultBackend;
|
||||||
|
|
||||||
|
|
||||||
|
public String move(Item item, FolderItem destination) {
|
||||||
|
//if item is a folder we have to move everything
|
||||||
|
return defaultBackend.move(((AbstractFileItem) item).getContent().getStorageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String copy(AbstractFileItem item) {
|
||||||
|
return defaultBackend.copy(item.getContent().getStorageId(), item.getContent().getRemotePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetaInfo upload(InputStream stream, String itemPath) {
|
||||||
|
return defaultBackend.upload(stream, itemPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream download(String id) {
|
||||||
|
return defaultBackend.getContent(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(String id) {
|
||||||
|
defaultBackend.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTotalVolume() {
|
||||||
|
return defaultBackend.getTotalSizeStored();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTotalItemsCount() {
|
||||||
|
return defaultBackend.getTotalItemsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,45 +1,35 @@
|
||||||
package org.gcube.data.access.storagehub.handlers;
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.jcr.ItemNotFoundException;
|
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.lock.LockException;
|
import javax.jcr.lock.LockException;
|
||||||
import javax.jcr.version.Version;
|
|
||||||
|
|
||||||
import org.gcube.common.authorization.library.AuthorizedTasks;
|
import org.gcube.common.authorization.library.AuthorizedTasks;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.gcube.data.access.storagehub.types.ContentPair;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -48,128 +38,65 @@ public class TrashHandler {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(TrashHandler.class);
|
private static Logger log = LoggerFactory.getLogger(TrashHandler.class);
|
||||||
|
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(100);
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VersionHandler versionHandler;
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AccountingHandler accountingHandler;
|
AccountingHandler accountingHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Item2NodeConverter item2Node;
|
Item2NodeConverter item2Node;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Node2ItemConverter node2Item;
|
StorageBackendHandler storageHandler;
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject FolderPluginHandler managerHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
FolderPluginHandler folderHandler;
|
|
||||||
|
|
||||||
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
|
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
|
||||||
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
||||||
for (Item item: itemsToDelete) {
|
for (Item item: itemsToDelete) {
|
||||||
removeNodesInternally(ses, item, false);
|
removeNodesInternally(ses, item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeOnlyNodesContent(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
|
private void removeNodesInternally(Session ses, Item itemToDelete) throws RepositoryException, StorageHubException {
|
||||||
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
|
||||||
for (Item item: itemsToDelete) {
|
|
||||||
removeNodesInternally(ses, item, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void retrieveItemsToDelete(Set<AbstractFileItem> itemsToDelete, Item itemToDelete) throws Exception{
|
|
||||||
if (itemToDelete instanceof AbstractFileItem) {
|
|
||||||
itemsToDelete.add(((AbstractFileItem) itemToDelete));
|
|
||||||
}else if (itemToDelete instanceof FolderItem) {
|
|
||||||
//only to be sure to not delete shared content
|
|
||||||
if (itemToDelete.isShared()) return;
|
|
||||||
|
|
||||||
List<Item> items = Utils.getItemList((Node) itemToDelete.getRelatedNode(), Excludes.GET_ONLY_CONTENT , null, true, null);
|
|
||||||
for (Item item: items)
|
|
||||||
retrieveItemsToDelete(itemsToDelete, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<ContentPair> retrieveContentToDelete(Collection<AbstractFileItem> itemsToDelete) {
|
|
||||||
Set<ContentPair> contentSet = new HashSet<ContentPair>();
|
|
||||||
for (AbstractFileItem item: itemsToDelete) {
|
|
||||||
if (item.getContent()== null || item.getContent().getStorageId()==null) {
|
|
||||||
log.warn("item with id {} contains null content",item.getId());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
FolderManager manager = folderHandler.getFolderManager(item);
|
|
||||||
contentSet.add(new ContentPair(item.getContent(), manager.getStorageBackend()));
|
|
||||||
|
|
||||||
List<Version> versions = versionHandler.getContentVersionHistory((Node)item.getRelatedNode());
|
|
||||||
|
|
||||||
for (Version version: versions) {
|
|
||||||
try {
|
|
||||||
Content content = node2Item.getContentFromVersion(version);
|
|
||||||
if (content!= null && content.getStorageId()!=null)
|
|
||||||
contentSet.add(new ContentPair(content, manager.getStorageBackend()));
|
|
||||||
else log.warn("invalid version {}",version.getName());
|
|
||||||
}catch (Throwable t) {
|
|
||||||
log.warn("error retrieving version content for {}",version.getName(),t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch (Exception e) {
|
|
||||||
log.warn("item with id {} cannot be deleted",item.getId(),e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return contentSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void removeNodesInternally(Session ses, Item itemToDelete, boolean onlyContent) throws RepositoryException, StorageHubException {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Set<AbstractFileItem> itemsToDelete = new HashSet<>();
|
Set<String> contentIdsToDelete = new HashSet<>();
|
||||||
Node nodeToDelete = (Node) itemToDelete.getRelatedNode();
|
|
||||||
|
Node nodeToDelete = ses.getNodeByIdentifier(itemToDelete.getId());
|
||||||
|
|
||||||
if (itemToDelete instanceof TrashItem) {
|
if (itemToDelete instanceof TrashItem) {
|
||||||
List<Item> trashChildren = Utils.getItemList(nodeToDelete, Excludes.GET_ONLY_CONTENT, null, true, null);
|
List<Item> trashChildren = Utils.getItemList(nodeToDelete, Excludes.GET_ONLY_CONTENT, null, true, null);
|
||||||
for (Item itemContentToRetrieve: trashChildren)
|
for (Item itemContentToRetrieve: trashChildren)
|
||||||
retrieveItemsToDelete(itemsToDelete, itemContentToRetrieve);
|
Utils.getAllContentIds(ses, contentIdsToDelete, itemContentToRetrieve, versionHandler);
|
||||||
} else
|
} else {
|
||||||
retrieveItemsToDelete(itemsToDelete, itemToDelete);
|
Utils.getAllContentIds(ses, contentIdsToDelete, itemToDelete, versionHandler);
|
||||||
|
}
|
||||||
if (!onlyContent)
|
nodeToDelete.remove();
|
||||||
nodeToDelete.remove();
|
|
||||||
|
log.debug("content ids to remove are {}",contentIdsToDelete);
|
||||||
String ids = itemsToDelete.stream().map((i) -> i.getId()).collect(Collectors.joining(","));
|
|
||||||
log.debug("content ids to remove are {}",ids);
|
|
||||||
|
|
||||||
Set<ContentPair> contentToDelete = retrieveContentToDelete(itemsToDelete);
|
|
||||||
|
|
||||||
|
String user = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
Runnable deleteFromStorageRunnable = AuthorizedTasks.bind(new Runnable() {
|
Runnable deleteFromStorageRunnable = AuthorizedTasks.bind(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (ContentPair cp: contentToDelete ) {
|
for (String id: contentIdsToDelete) {
|
||||||
try {
|
try {
|
||||||
cp.getStorageBackend().onDelete(cp.getContent());
|
storageHandler.delete(id);
|
||||||
log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName());
|
log.debug("file with id {} correctly removed on storage",id);
|
||||||
}catch(Throwable t) {
|
}catch(Throwable t) {
|
||||||
log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t);
|
log.warn("error removing file on storage with id {}",id, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
executor.execute(deleteFromStorageRunnable);
|
new Thread(deleteFromStorageRunnable).start();
|
||||||
if (!onlyContent)
|
|
||||||
ses.save();
|
ses.save();
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException("the selected node or his parent is locked", e);
|
throw new ItemLockedException("the selected node or his parent is locked", e);
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
|
@ -177,20 +104,20 @@ public class TrashHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void moveToTrash(Session ses, Node nodeToDelete, Item item) throws RepositoryException, BackendGenericError{
|
||||||
public void moveToTrash(Session ses, Node nodeToDelete, Item item, String login) throws RepositoryException, BackendGenericError{
|
|
||||||
log.debug("moving node {} to trash ",item.getId());
|
log.debug("moving node {} to trash ",item.getId());
|
||||||
|
final Node trashFolder = ses.getNode(Paths.append(Utils.getWorkspacePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
||||||
|
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
final Node trashFolder = ses.getNode(pathUtil.getTrashPath(login, ses).toPath());
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
|
||||||
|
|
||||||
log.debug("preparing thrash item");
|
log.debug("preparing thrash item");
|
||||||
|
|
||||||
TrashItem trashItem = new TrashItem();
|
TrashItem trashItem = new TrashItem();
|
||||||
trashItem.setDeletedBy(login);
|
trashItem.setDeletedBy(AuthorizationProvider.instance.get().getClient().getId());
|
||||||
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
|
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
trashItem.setDeletedTime(now);
|
trashItem.setDeletedTime(now);
|
||||||
|
@ -204,7 +131,7 @@ public class TrashHandler {
|
||||||
trashItem.setName(item.getId());
|
trashItem.setName(item.getId());
|
||||||
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
|
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
|
||||||
|
|
||||||
trashItem.setOwner(login);
|
trashItem.setOwner(item.getOwner());
|
||||||
trashItem.setLastModificationTime(item.getLastModificationTime());
|
trashItem.setLastModificationTime(item.getLastModificationTime());
|
||||||
trashItem.setLastModifiedBy(item.getLastModifiedBy());
|
trashItem.setLastModifiedBy(item.getLastModifiedBy());
|
||||||
|
|
||||||
|
@ -234,7 +161,7 @@ public class TrashHandler {
|
||||||
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
||||||
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
|
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
|
||||||
}
|
}
|
||||||
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true);
|
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, ses.getNodeByIdentifier(item.getParentId()), true);
|
||||||
}catch(Throwable t) {
|
}catch(Throwable t) {
|
||||||
log.error("error exceuting move to trash",t);
|
log.error("error exceuting move to trash",t);
|
||||||
throw new BackendGenericError(t);
|
throw new BackendGenericError(t);
|
||||||
|
@ -245,69 +172,27 @@ public class TrashHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String restoreItem(Session ses, TrashItem item, FolderItem destination, String login) throws RepositoryException, StorageHubException, BackendGenericError{
|
public String restoreItem(Session ses, TrashItem item) throws RepositoryException, BackendGenericError, UserNotAuthorizedException{
|
||||||
log.debug("restoring node from trash with user ");
|
log.debug("restoring node from trash");
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
//final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
//final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
||||||
|
Node originalParent = ses.getNodeByIdentifier(item.getOriginalParentId());
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, originalParent.getIdentifier(), false );
|
||||||
|
|
||||||
Node destinationNode= null;
|
ses.getWorkspace().getLockManager().lock(originalParent.getPath(), true, true, 0,login);
|
||||||
if (destination==null) {
|
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(item.getId()), Excludes.ALL, null, false, null);
|
||||||
boolean originalParentExists = true;
|
if (items.size()!=1) {
|
||||||
boolean originalParentTrashed = false;
|
log.warn("a problem occurred restoring item from trash");
|
||||||
Node originalParent = null;
|
throw new BackendGenericError("An error occurred on trash item");
|
||||||
try {
|
|
||||||
originalParent = ses.getNodeByIdentifier(item.getOriginalParentId());
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
originalParentExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Item originalParentItem = null;
|
|
||||||
if (originalParentExists) {
|
|
||||||
originalParentItem = node2Item.getItem(originalParent, Excludes.ALL);
|
|
||||||
originalParentTrashed = originalParentItem.isTrashed();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(originalParentExists && !originalParentTrashed) {
|
|
||||||
destinationNode = originalParent;
|
|
||||||
}else {
|
|
||||||
String homeWS = pathUtil.getWorkspacePath(login).toPath();
|
|
||||||
Node node = ses.getNode(homeWS);
|
|
||||||
destinationNode = node;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Node node = (Node)destination.getRelatedNode();
|
|
||||||
|
|
||||||
if (!node2Item.checkNodeType(node, FolderItem.class))
|
|
||||||
throw new InvalidCallParameters("destination Node is not a folder");
|
|
||||||
|
|
||||||
destinationNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true );
|
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(destinationNode.getPath(), true, true, 0,login);
|
|
||||||
String newNodePath = null;
|
|
||||||
try {
|
|
||||||
//the real node is a child of the Trash node
|
|
||||||
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(item.getId()), Excludes.ALL, null, false, null);
|
|
||||||
if (items.size()!=1) {
|
|
||||||
log.warn("a problem occurred restoring item from trash");
|
|
||||||
throw new BackendGenericError("An error occurred on trash item");
|
|
||||||
}
|
|
||||||
Item itemToMove = items.get(0);
|
|
||||||
|
|
||||||
item2Node.updateOwnerOnSubTree(ses.getNodeByIdentifier(itemToMove.getId()), login);
|
|
||||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, itemToMove.getName());
|
|
||||||
newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()),uniqueName).toPath();
|
|
||||||
ses.move(itemToMove.getPath(), newNodePath);
|
|
||||||
Utils.setPropertyOnChangeNode(ses.getNode(newNodePath), login, ItemAction.MOVED);
|
|
||||||
ses.removeItem(item.getPath());
|
|
||||||
ses.save();
|
|
||||||
}catch (Exception e) {
|
|
||||||
if (ses.getWorkspace().getLockManager().isLocked(destinationNode.getPath()))
|
|
||||||
ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
|
|
||||||
}
|
}
|
||||||
|
Item itemToMove = items.get(0);
|
||||||
|
String newNodePath = Paths.append(Paths.getPath(originalParent.getPath()), itemToMove.getName()).toPath();
|
||||||
|
ses.move(itemToMove.getPath(), newNodePath);
|
||||||
|
Utils.setPropertyOnChangeNode(ses.getNode(newNodePath), login, ItemAction.MOVED);
|
||||||
|
ses.removeItem(item.getPath());
|
||||||
|
ses.save();
|
||||||
return ses.getNode(newNodePath).getIdentifier();
|
return ses.getNode(newNodePath).getIdentifier();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.lock.LockException;
|
import javax.jcr.lock.LockException;
|
||||||
|
@ -28,13 +27,9 @@ import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -52,41 +47,28 @@ public class UnshareHandler {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AuthorizationChecker authChecker;
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Item2NodeConverter item2Node;
|
Item2NodeConverter item2Node;
|
||||||
|
|
||||||
public String unshare(Session ses, Set<String> users, Node sharedNode, String login) throws RepositoryException, StorageHubException{
|
public String unshare(Session ses, Set<String> users, Node sharedNode, String login) throws RepositoryException, StorageHubException{
|
||||||
return _unshare(ses, users, sharedNode, login, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String unshareForRemoval(Session ses, Set<String> users, Node sharedNode, String login) throws RepositoryException, StorageHubException{
|
|
||||||
return _unshare(ses, users, sharedNode, login, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String _unshare(Session ses, Set<String> users, Node sharedNode, String login, boolean withCopyOnUnshare) throws RepositoryException, StorageHubException{
|
|
||||||
Item item = node2Item.getItem(sharedNode, Excludes.ALL);
|
Item item = node2Item.getItem(sharedNode, Excludes.ALL);
|
||||||
if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder()) {
|
if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder())
|
||||||
log.warn("this item type cannot be unshared {}",item.getClass().getSimpleName());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
SharedFolder sharedItem =(SharedFolder) item;
|
SharedFolder sharedItem =(SharedFolder) item;
|
||||||
|
|
||||||
Set<String> usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getMap().keySet());
|
Set<String> usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getMap().keySet());
|
||||||
usersInSharedFolder.removeAll(users);
|
usersInSharedFolder.removeAll(users);
|
||||||
|
|
||||||
if (users==null || users.size()==0)
|
if (users==null || users.size()==0)
|
||||||
return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
|
return unshareAll(login, ses, sharedItem);
|
||||||
|
|
||||||
if (usersInSharedFolder.size()<=1) {
|
if (usersInSharedFolder.size()<=1) {
|
||||||
if (users.size()==1 && users.contains(login))
|
if (users.size()==1 && users.contains(login))
|
||||||
return unshareAll(sharedItem.getOwner(), ses , sharedItem, withCopyOnUnshare);
|
return unshareAll(sharedItem.getOwner(), ses , sharedItem);
|
||||||
else return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
|
else return unshareAll(login, ses, sharedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(sharedNode.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(sharedNode.getPath(), true, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
|
@ -103,10 +85,9 @@ public class UnshareHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String unshareAll(String login, Session ses, SharedFolder item) throws StorageHubException, BackendGenericError, RepositoryException{
|
||||||
private String unshareAll(String login, Session ses, SharedFolder item, boolean withCopyCreation) throws StorageHubException, BackendGenericError, RepositoryException{
|
|
||||||
log.info("unshare all called");
|
log.info("unshare all called");
|
||||||
|
|
||||||
if (!login.equals(item.getOwner()))
|
if (!login.equals(item.getOwner()))
|
||||||
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare all");
|
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare all");
|
||||||
|
|
||||||
|
@ -118,66 +99,37 @@ public class UnshareHandler {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String unsharedNodeIdentifier =null;
|
Node unsharedNode;
|
||||||
try {
|
try {
|
||||||
log.debug("user list is empty, I'm going to remove also the shared dir");
|
log.debug("user list is empty, I'm going to remove also the shared dir");
|
||||||
|
//take the admin folder and remove his clone then move the shared folder from share to the user home and change the folder type
|
||||||
|
String adminDirPath = (String)item.getUsers().getMap().get(login);
|
||||||
|
String[] splitString = adminDirPath.split("/");
|
||||||
|
String parentDirectoryId = splitString[0];
|
||||||
|
String directoryName = splitString[1];
|
||||||
|
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||||
|
log.debug("parent node path is {}/{}",parentNode.getPath(), directoryName);
|
||||||
|
|
||||||
if (withCopyCreation) {
|
Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||||
|
adminNode.removeShare();
|
||||||
|
|
||||||
Node sharedOwnerNode = null;
|
unsharedNode = createUnsharedFolder(ses, parentNode, directoryName, item.getDescription(), login);
|
||||||
NodeIterator it = sharedItemNode.getSharedSet();
|
|
||||||
while(it.hasNext()) {
|
|
||||||
Node node = it.nextNode();
|
|
||||||
|
|
||||||
log.info("[UNSHARE] checking node {} starts with {} ",node.getPath(),pathUtil.getHome(login).toPath());
|
List<Item> itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null);
|
||||||
|
|
||||||
if (node.getPath().startsWith(pathUtil.getHome(login).toPath())) {
|
for (Item itemCopy: itemsToCopy) {
|
||||||
sharedOwnerNode =node;
|
Node itemToCopyNode = ses.getNodeByIdentifier(itemCopy.getId());
|
||||||
break;
|
log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath());
|
||||||
}
|
ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName()));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Node shareParent = sharedOwnerNode.getParent();
|
|
||||||
|
|
||||||
sharedOwnerNode.removeShare();
|
|
||||||
|
|
||||||
Node unsharedNode = createUnsharedFolder(ses, shareParent , item.getTitle() , item.getDescription(), login);
|
|
||||||
|
|
||||||
List<Item> itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null);
|
|
||||||
|
|
||||||
for (Item itemCopy: itemsToCopy) {
|
|
||||||
Node itemToCopyNode = ses.getNodeByIdentifier(itemCopy.getId());
|
|
||||||
log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath());
|
|
||||||
ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsharedNode.getNode(NodeProperty.ACCOUNTING.toString()).remove();
|
|
||||||
ses.move(sharedItemNode.getNode(NodeProperty.ACCOUNTING.toString()).getPath(), String.format("%s/%s",unsharedNode.getPath(), NodeProperty.ACCOUNTING.toString()));
|
|
||||||
|
|
||||||
//set owner of all the unshared items to the caller
|
|
||||||
item2Node.updateOwnerOnSubTree(unsharedNode, login);
|
|
||||||
|
|
||||||
accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), ses, "ALL", unsharedNode, false);
|
|
||||||
|
|
||||||
unsharedNodeIdentifier = unsharedNode.getIdentifier();
|
|
||||||
log.info("[UNSHARE] unshared node id {}",unsharedNodeIdentifier);
|
|
||||||
ses.save();
|
|
||||||
}
|
}
|
||||||
|
ses.save();
|
||||||
log.debug("all the users have been removed, the folder is totally unshared");
|
|
||||||
|
|
||||||
}catch(Throwable t) {
|
|
||||||
log.error("erro unsharing all",t);
|
|
||||||
throw t;
|
|
||||||
}finally {
|
}finally {
|
||||||
ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath());
|
ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedItemNode.removeSharedSet();
|
sharedItemNode.removeSharedSet();
|
||||||
ses.save();
|
ses.save();
|
||||||
|
log.debug("all the users have been removed, the folder is totally unshared");
|
||||||
return unsharedNodeIdentifier;
|
return unsharedNode.getIdentifier();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,30 +137,17 @@ public class UnshareHandler {
|
||||||
|
|
||||||
|
|
||||||
private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{
|
private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{
|
||||||
log.info("unshare caller");
|
|
||||||
if (login.equals(item.getOwner()))
|
if (login.equals(item.getOwner()))
|
||||||
throw new InvalidCallParameters("the caller is the owner, the folder cannot be unshared");
|
throw new InvalidCallParameters("the caller is the owner, the folder cannot be unshared");
|
||||||
|
|
||||||
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
|
if (item.getUsers().getMap().get(login)==null)
|
||||||
if (item.getUsers().getMap().get(login)!=null) {
|
throw new InvalidCallParameters("the folder is not shared with user "+login);
|
||||||
Node usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
|
|
||||||
usersNode.remove();
|
|
||||||
Node newUsersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
|
|
||||||
|
|
||||||
item.getUsers().getMap().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try {
|
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
|
||||||
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("error adding property to shared node users node under {}",item.getId());
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
Node shareNode = getUserSharingNode(login, ses, item);
|
String parentId = removeSharingForUser(login, ses, item);
|
||||||
String parentId = shareNode.getParent().getIdentifier();
|
|
||||||
|
|
||||||
//not returning an error to correct all the old ACL
|
|
||||||
if (shareNode != null)
|
|
||||||
shareNode.removeShare();
|
|
||||||
|
|
||||||
AccessControlManager acm = ses.getAccessControlManager();
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||||
|
|
||||||
|
@ -223,11 +162,19 @@ public class UnshareHandler {
|
||||||
if (entryToDelete!=null)
|
if (entryToDelete!=null)
|
||||||
acls.removeAccessControlEntry(entryToDelete);
|
acls.removeAccessControlEntry(entryToDelete);
|
||||||
|
|
||||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
|
||||||
|
|
||||||
log.debug("removed Access control entry for user {}",login);
|
log.debug("removed Access control entry for user {}",login);
|
||||||
|
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||||
accountingHandler.createUnshareFolder(item.getTitle(), ses, login, sharedFolderNode, false);
|
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
|
||||||
|
usersNode.remove();
|
||||||
|
Node newUsersNode = sharedItemNode.addNode(NodeConstants.USERS_NAME);
|
||||||
|
|
||||||
|
item.getUsers().getMap().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try {
|
||||||
|
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("error adding property to shared node users node under {}",item.getId());
|
||||||
|
}});
|
||||||
|
|
||||||
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
|
@ -235,10 +182,11 @@ public class UnshareHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private String unsharePartial(Set<String> usersToUnshare, String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException {
|
private String unsharePartial(Set<String> usersToUnshare, String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException {
|
||||||
log.info("unshare partial");
|
authChecker.checkAdministratorControl(ses, (SharedFolder)item);
|
||||||
authChecker.checkAdministratorControl(ses, login, (SharedFolder)item);
|
|
||||||
if (usersToUnshare.contains(item.getOwner()))
|
if (usersToUnshare.contains(item.getOwner()))
|
||||||
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare owner");
|
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare owner");
|
||||||
|
|
||||||
|
@ -248,11 +196,7 @@ public class UnshareHandler {
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||||
|
|
||||||
for (String user : usersToUnshare) {
|
for (String user : usersToUnshare) {
|
||||||
Node userShareNode = getUserSharingNode(user, ses, item);
|
removeSharingForUser(user, ses, item);
|
||||||
|
|
||||||
//not returning an error to correct all the old ACL
|
|
||||||
if (userShareNode != null)
|
|
||||||
userShareNode.removeShare();
|
|
||||||
|
|
||||||
AccessControlEntry entryToDelete= null;
|
AccessControlEntry entryToDelete= null;
|
||||||
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
||||||
|
@ -264,11 +208,11 @@ public class UnshareHandler {
|
||||||
}
|
}
|
||||||
if (entryToDelete!=null)
|
if (entryToDelete!=null)
|
||||||
acls.removeAccessControlEntry(entryToDelete);
|
acls.removeAccessControlEntry(entryToDelete);
|
||||||
|
|
||||||
log.debug("removed Access control entry for user {}",user);
|
log.debug("removed Access control entry for user {}",user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||||
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
|
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
|
||||||
usersNode.remove();
|
usersNode.remove();
|
||||||
|
@ -282,10 +226,6 @@ public class UnshareHandler {
|
||||||
|
|
||||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
for (String user: usersToUnshare) {
|
|
||||||
accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), ses, user, sharedItemNode, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
return item.getId();
|
return item.getId();
|
||||||
|
@ -293,34 +233,18 @@ public class UnshareHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Node getUserSharingNode(String user, Session ses, SharedFolder item) throws RepositoryException {
|
private String removeSharingForUser(String user, Session ses, SharedFolder item) throws RepositoryException {
|
||||||
Node shareNode = null;
|
String userDirPath = (String)item.getUsers().getMap().get(user);
|
||||||
try {
|
if (userDirPath==null) return null;
|
||||||
String userDirPath = (String)item.getUsers().getMap().get(user);
|
String[] splitString = userDirPath.split("/");
|
||||||
if (userDirPath==null) return null;
|
String parentDirectoryId = splitString[0];
|
||||||
String[] splitString = userDirPath.split("/");
|
String directoryName = splitString[1];
|
||||||
String parentDirectoryId = splitString[0];
|
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||||
String directoryName = splitString[1];
|
Node userNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||||
Node parentNode = null;
|
userNode.removeShare();
|
||||||
parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
accountingHandler.createUnshareFolder(directoryName, ses, parentNode, false);
|
||||||
shareNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
log.debug("directory removed for user {}",user);
|
||||||
}catch (Throwable e) {
|
return parentDirectoryId;
|
||||||
log.warn("users map is not containing a valid value");
|
|
||||||
}
|
|
||||||
|
|
||||||
Node sharedFolderNode = ses.getNodeByIdentifier(item.getId());
|
|
||||||
if (shareNode==null) {
|
|
||||||
NodeIterator it = sharedFolderNode.getSharedSet();
|
|
||||||
while(it.hasNext()) {
|
|
||||||
Node node = it.nextNode();
|
|
||||||
if (node.getPath().startsWith(pathUtil.getHome(user).toPath())) {
|
|
||||||
shareNode =node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return shareNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.vres;
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
@ -9,7 +9,6 @@ import javax.jcr.SimpleCredentials;
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -22,11 +21,11 @@ public class VRE {
|
||||||
private VREQueryRetriever vreQueryRetriever;
|
private VREQueryRetriever vreQueryRetriever;
|
||||||
private ExecutorService executor;
|
private ExecutorService executor;
|
||||||
|
|
||||||
protected VRE(Item item, Repository repository, SimpleCredentials credentials, Node2ItemConverter node2Item, ExecutorService executor) {
|
public VRE(Item item, Repository repository, SimpleCredentials credentials, ExecutorService executor) {
|
||||||
super();
|
super();
|
||||||
this.vreFolder = item;
|
this.vreFolder = item;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
vreQueryRetriever = new VREQueryRetriever(repository, credentials, node2Item, vreFolder);
|
vreQueryRetriever = new VREQueryRetriever(repository, credentials, vreFolder);
|
||||||
result = executor.submit(vreQueryRetriever);
|
result = executor.submit(vreQueryRetriever);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.jcr.SimpleCredentials;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
|
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class VREManager {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
|
||||||
|
|
||||||
|
private Map<String, VRE> vreMap = new HashMap<>();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||||
|
|
||||||
|
SimpleCredentials credentials;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public VREManager(ServletContext context) {
|
||||||
|
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized VRE getVRE(String completeName) {
|
||||||
|
logger.trace("requesting VRE {}",completeName);
|
||||||
|
if (vreMap.containsKey(completeName))
|
||||||
|
return vreMap.get(completeName);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized VRE putVRE(Item vreFolder) {
|
||||||
|
logger.trace("inserting VRE {}",vreFolder.getTitle());
|
||||||
|
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
|
||||||
|
else {
|
||||||
|
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, executor);
|
||||||
|
vreMap.put(vreFolder.getTitle(), toReturn);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,192 @@
|
||||||
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import javax.jcr.Credentials;
|
||||||
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.NodeIterator;
|
||||||
|
import javax.jcr.Property;
|
||||||
|
import javax.jcr.Repository;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.observation.Event;
|
||||||
|
import javax.jcr.observation.EventJournal;
|
||||||
|
import javax.jcr.query.Query;
|
||||||
|
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class VREQueryRetriever implements Callable<List<Item>> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
|
||||||
|
|
||||||
|
private static final int CACHE_DIMENSION = 50;
|
||||||
|
|
||||||
|
private Repository repository;
|
||||||
|
private Credentials credentials;
|
||||||
|
private Item vreFolder;
|
||||||
|
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
|
||||||
|
long lastTimestamp =0;
|
||||||
|
|
||||||
|
private Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||||
|
|
||||||
|
|
||||||
|
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
|
||||||
|
super();
|
||||||
|
this.repository = repository;
|
||||||
|
this.credentials = credentials;
|
||||||
|
this.vreFolder = vreFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Item> call() {
|
||||||
|
logger.trace("executing recents task");
|
||||||
|
Session ses = null;
|
||||||
|
if (lastTimestamp==0) {
|
||||||
|
try {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
ses = repository.login(credentials);
|
||||||
|
String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
|
||||||
|
logger.trace("query for recents is {}",query);
|
||||||
|
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
|
||||||
|
jcrQuery.setLimit(CACHE_DIMENSION);
|
||||||
|
lastTimestamp = System.currentTimeMillis();
|
||||||
|
NodeIterator it = jcrQuery.execute().getNodes();
|
||||||
|
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Node node = it.nextNode();
|
||||||
|
Item item =node2Item.getItem(node, Excludes.EXCLUDE_ACCOUNTING);
|
||||||
|
cachedList.add(item);
|
||||||
|
logger.trace("adding item {} with node {}",item.getTitle(), node.getName());
|
||||||
|
}
|
||||||
|
logger.trace("creating objects took {}",System.currentTimeMillis()-start);
|
||||||
|
if (cachedList.size()<=10) return cachedList;
|
||||||
|
else return cachedList.subList(0, 10);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("error querying vre {}",vreFolder.getTitle(),e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
logger.trace("recents task finished");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
|
||||||
|
long timestampToUse = lastTimestamp;
|
||||||
|
lastTimestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
ses = repository.login(credentials);
|
||||||
|
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
|
||||||
|
|
||||||
|
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
|
||||||
|
journalChanged.skipTo(timestampToUse);
|
||||||
|
|
||||||
|
logger.trace("getting the journal took {}",System.currentTimeMillis()-start);
|
||||||
|
|
||||||
|
int events = 0;
|
||||||
|
|
||||||
|
while (journalChanged.hasNext()) {
|
||||||
|
events++;
|
||||||
|
Event event = journalChanged.nextEvent();
|
||||||
|
switch(event.getType()) {
|
||||||
|
|
||||||
|
case Event.NODE_ADDED:
|
||||||
|
if (ses.nodeExists(event.getPath())) {
|
||||||
|
Node nodeAdded = ses.getNode(event.getPath());
|
||||||
|
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
||||||
|
logger.trace("node added event received with name {}", nodeAdded.getName());
|
||||||
|
Item item = node2Item.getItem(nodeAdded, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
||||||
|
insertItemInTheRightPlace(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Event.PROPERTY_CHANGED:
|
||||||
|
if (ses.propertyExists(event.getPath())) {
|
||||||
|
Property property = ses.getProperty(event.getPath());
|
||||||
|
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
|
||||||
|
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
||||||
|
String identifier = property.getParent().getIdentifier();
|
||||||
|
cachedList.removeIf(i -> i.getId().equals(identifier));
|
||||||
|
Item item = node2Item.getItem(property.getParent(), Excludes.EXCLUDE_ACCOUNTING);
|
||||||
|
insertItemInTheRightPlace(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Event.NODE_REMOVED:
|
||||||
|
logger.trace("node removed event received with type {}", event.getIdentifier());
|
||||||
|
cachedList.removeIf(i -> {
|
||||||
|
try {
|
||||||
|
return i.getId().equals(event.getIdentifier()) && i.getLastModificationTime().getTime().getTime()<event.getDate();
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case Event.NODE_MOVED:
|
||||||
|
Node nodeMoved = ses.getNode(event.getPath());
|
||||||
|
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
|
||||||
|
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
|
||||||
|
logger.trace("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
|
||||||
|
String identifier = nodeMoved.getIdentifier();
|
||||||
|
cachedList.removeIf(i -> i.getId().equals(identifier) && !i.getPath().startsWith(vreFolder.getPath()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("error in event handling");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedList.size()>CACHE_DIMENSION)
|
||||||
|
cachedList.subList(51, cachedList.size()).clear();
|
||||||
|
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
|
||||||
|
if (cachedList.size()<=10) return cachedList;
|
||||||
|
else return cachedList.subList(0, 10);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertItemInTheRightPlace(Item item) {
|
||||||
|
Iterator<Item> it = cachedList.iterator();
|
||||||
|
int index =0;
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Item inListItem = it.next();
|
||||||
|
if (item.getLastModificationTime().getTime().getTime()>=inListItem.getLastModificationTime().getTime().getTime()) break;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if (index<CACHE_DIMENSION)
|
||||||
|
cachedList.add(index, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @Override
|
||||||
|
public void onEvent(EventIterator events) {
|
||||||
|
logger.trace("on event called");
|
||||||
|
while (events.hasNext()) {
|
||||||
|
Event event = events.nextEvent();
|
||||||
|
try {
|
||||||
|
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.error("error reading event",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ public class VersionHandler {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(VersionHandler.class);
|
private static final Logger logger = LoggerFactory.getLogger(VersionHandler.class);
|
||||||
|
|
||||||
public void makeVersionableContent(Node node){
|
public void makeVersionableContent(Node node, Session session){
|
||||||
try {
|
try {
|
||||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||||
contentNode.addMixin(JcrConstants.MIX_VERSIONABLE);
|
contentNode.addMixin(JcrConstants.MIX_VERSIONABLE);
|
||||||
|
@ -31,9 +31,8 @@ public class VersionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkinContentNode(Node node){
|
public void checkinContentNode(Node node, Session session){
|
||||||
try {
|
try {
|
||||||
Session session = node.getSession();
|
|
||||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||||
versionManager.checkin(contentNode.getPath());
|
versionManager.checkin(contentNode.getPath());
|
||||||
|
@ -42,9 +41,8 @@ public class VersionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkoutContentNode(Node node){
|
public void checkoutContentNode(Node node, Session session){
|
||||||
try {
|
try {
|
||||||
Session session = node.getSession();
|
|
||||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||||
versionManager.checkout(contentNode.getPath());
|
versionManager.checkout(contentNode.getPath());
|
||||||
|
@ -53,9 +51,8 @@ public class VersionHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Version> getContentVersionHistory(Node node) {
|
public List<Version> getContentVersionHistory(Node node, Session session) {
|
||||||
try {
|
try {
|
||||||
Session session = node.getSession();
|
|
||||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||||
VersionHistory history = versionManager.getVersionHistory(contentNode.getPath());
|
VersionHistory history = versionManager.getVersionHistory(contentNode.getPath());
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.gcube.data.access.storagehub.handlers.content;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.apache.tika.metadata.Metadata;
|
||||||
import org.apache.tika.parser.ParseContext;
|
import org.apache.tika.parser.ParseContext;
|
||||||
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
|
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
|
||||||
import org.apache.tika.sax.BodyContentHandler;
|
import org.apache.tika.sax.BodyContentHandler;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||||
import org.gcube.common.storagehub.model.items.GenericFileItem;
|
import org.gcube.common.storagehub.model.items.GenericFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
import org.gcube.common.storagehub.model.items.nodes.Content;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
|
|
@ -8,8 +8,6 @@ import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||||
import org.gcube.common.storagehub.model.items.PDFFileItem;
|
import org.gcube.common.storagehub.model.items.PDFFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.PDFContent;
|
import org.gcube.common.storagehub.model.items.nodes.PDFContent;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.itextpdf.text.pdf.PdfReader;
|
import com.itextpdf.text.pdf.PdfReader;
|
||||||
|
|
||||||
|
@ -24,23 +22,20 @@ public class PdfHandler implements ContentHandler {
|
||||||
|
|
||||||
PDFContent content = new PDFContent();
|
PDFContent content = new PDFContent();
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
|
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
|
||||||
try {
|
PdfReader reader = new PdfReader(is);
|
||||||
PdfReader reader = new PdfReader(is);
|
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
||||||
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
||||||
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
HashMap<String, String> fileInfo = reader.getInfo();
|
||||||
HashMap<String, String> fileInfo = reader.getInfo();
|
content.setAuthor(fileInfo.containsKey(AUTHOR)?fileInfo.get(AUTHOR):"n/a");
|
||||||
content.setAuthor(fileInfo.containsKey(AUTHOR)?fileInfo.get(AUTHOR):"n/a");
|
content.setProducer(fileInfo.containsKey(PRODUCER)?fileInfo.get(PRODUCER):"n/a");
|
||||||
content.setProducer(fileInfo.containsKey(PRODUCER)?fileInfo.get(PRODUCER):"n/a");
|
content.setTitle(fileInfo.containsKey(TITLE)?fileInfo.get(TITLE):"n/a");
|
||||||
content.setTitle(fileInfo.containsKey(TITLE)?fileInfo.get(TITLE):"n/a");
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.warn("{} is not a valid pdf", fileName, e);
|
|
||||||
}
|
|
||||||
content.setMimeType(mimeType);
|
content.setMimeType(mimeType);
|
||||||
} @Override
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public PDFContent getContent() {
|
public PDFContent getContent() {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,400 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.jcr.lock.LockException;
|
|
||||||
|
|
||||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
|
||||||
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
|
||||||
import org.apache.tika.config.TikaConfig;
|
|
||||||
import org.apache.tika.detect.Detector;
|
|
||||||
import org.apache.tika.io.TikaInputStream;
|
|
||||||
import org.apache.tika.metadata.Metadata;
|
|
||||||
import org.gcube.common.authorization.library.AuthorizedTasks;
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
|
||||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
|
||||||
import org.gcube.data.access.storagehub.MultipleOutputStream;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.CreateParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class ItemHandler {
|
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AccountingHandler accountingHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
ContentHandlerFactory contenthandlerFactory;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
VersionHandler versionHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
FolderPluginHandler pluginHandler;
|
|
||||||
|
|
||||||
private static ExecutorService executor = Executors.newFixedThreadPool(100);
|
|
||||||
|
|
||||||
@Inject Node2ItemConverter node2Item;
|
|
||||||
@Inject Item2NodeConverter item2Node;
|
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(ItemHandler.class);
|
|
||||||
|
|
||||||
|
|
||||||
public <T extends CreateParameters> String create(T parameters) throws Exception{
|
|
||||||
Session ses = parameters.getSession();
|
|
||||||
|
|
||||||
Node destination;
|
|
||||||
try {
|
|
||||||
destination = ses.getNodeByIdentifier(parameters.getParentId());
|
|
||||||
}catch(RepositoryException inf) {
|
|
||||||
throw new IdNotFoundException(parameters.getParentId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
||||||
throw new InvalidItemException("the destination item is not a folder");
|
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, parameters.getUser(), destination.getIdentifier(), true);
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
Node newNode = null;
|
|
||||||
switch (parameters.getMangedType()) {
|
|
||||||
case FILE:
|
|
||||||
newNode = create((FileCreationParameters)parameters, destination);
|
|
||||||
break;
|
|
||||||
case FOLDER:
|
|
||||||
newNode = create((FolderCreationParameters)parameters, destination);
|
|
||||||
break;
|
|
||||||
case ARCHIVE:
|
|
||||||
newNode = create((ArchiveStructureCreationParameter)parameters, destination);
|
|
||||||
break;
|
|
||||||
case URL:
|
|
||||||
newNode = create((URLCreationParameters) parameters, destination);
|
|
||||||
break;
|
|
||||||
case GCUBEITEM:
|
|
||||||
newNode = create((GCubeItemCreationParameters) parameters, destination);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new InvalidCallParameters("Item not supported");
|
|
||||||
}
|
|
||||||
log.debug("item with id {} correctly created",newNode.getIdentifier());
|
|
||||||
return newNode.getIdentifier();
|
|
||||||
} finally {
|
|
||||||
if (parameters.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
|
|
||||||
parameters.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Node create(FolderCreationParameters params, Node destination) throws Exception{
|
|
||||||
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
|
|
||||||
Node newNode = Utils.createFolderInternally(params, accountingHandler);
|
|
||||||
params.getSession().save();
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node create(FileCreationParameters params, Node destination) throws Exception{
|
|
||||||
Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(), params.getDescription(), params.getUser(), true);
|
|
||||||
params.getSession().save();
|
|
||||||
versionHandler.checkinContentNode(newNode);
|
|
||||||
log.info("file with id {} correctly created",newNode.getIdentifier());
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node create(URLCreationParameters params, Node destination) throws Exception{
|
|
||||||
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
|
|
||||||
Node newNode = Utils.createURLInternally(params.getSession(), destination, params.getName(), params.getUrl(), params.getDescription(), params.getUser(), accountingHandler);
|
|
||||||
params.getSession().save();
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node create(ArchiveStructureCreationParameter params, Node destination) throws Exception{
|
|
||||||
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
|
|
||||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(params.getParentFolderName()).author(params.getUser()).on(destination.getIdentifier()).with(params.getSession()).build();
|
|
||||||
Node parentDirectoryNode = Utils.createFolderInternally(folderParameters, accountingHandler);
|
|
||||||
params.getSession().save();
|
|
||||||
try {
|
|
||||||
if (params.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
|
|
||||||
params.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
|
|
||||||
} catch (Throwable t){
|
|
||||||
log.warn("error unlocking {}", destination.getPath(), t);
|
|
||||||
}
|
|
||||||
|
|
||||||
Set<Node> fileNodes = new HashSet<>();
|
|
||||||
|
|
||||||
|
|
||||||
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
|
||||||
|
|
||||||
try (ArchiveInputStream input = new ArchiveStreamFactory()
|
|
||||||
.createArchiveInputStream(new BufferedInputStream(params.getStream(), 1024*64))){
|
|
||||||
ArchiveEntry entry;
|
|
||||||
while ((entry = input.getNextEntry()) != null) {
|
|
||||||
String entirePath = entry.getName();
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
log.debug("creating directory with entire path {} ", entirePath);
|
|
||||||
createPath(entirePath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
|
|
||||||
String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2");
|
|
||||||
String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1");
|
|
||||||
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
|
||||||
Node fileNode = null;
|
|
||||||
if (parentPath.isEmpty())
|
|
||||||
fileNode = createFileItemInternally(params.getSession(), parentDirectoryNode, input, name, "", params.getUser(), false);
|
|
||||||
else {
|
|
||||||
Node parentNode = directoryNodeMap.get(parentPath);
|
|
||||||
if (parentNode ==null)
|
|
||||||
parentNode = createPath(parentPath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
|
|
||||||
|
|
||||||
fileNode = createFileItemInternally(params.getSession(), parentNode, input, name, "", params.getUser(), false);
|
|
||||||
}
|
|
||||||
fileNodes.add(fileNode);
|
|
||||||
}catch(Exception e) {
|
|
||||||
log.warn("error getting file {}",entry.getName(),e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
params.getSession().save();
|
|
||||||
for (Node node : fileNodes)
|
|
||||||
versionHandler.checkinContentNode(node);
|
|
||||||
return parentDirectoryNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node createPath(String parentPath, Map<String, Node> directoryNodeMap, Node rootNode, Session ses, String user) throws StorageHubException, RepositoryException{
|
|
||||||
String[] parentPathSplit = parentPath.split("/");
|
|
||||||
String name = parentPathSplit[parentPathSplit.length-1];
|
|
||||||
StringBuilder relParentPath = new StringBuilder();
|
|
||||||
for (int i = 0 ; i<=parentPathSplit.length-2; i++)
|
|
||||||
relParentPath.append(parentPathSplit[i]).append("/");
|
|
||||||
|
|
||||||
if (relParentPath.toString().isEmpty()) {
|
|
||||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(rootNode.getIdentifier()).with(ses).build();
|
|
||||||
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
|
|
||||||
directoryNodeMap.put(name+"/", createdNode);
|
|
||||||
return createdNode;
|
|
||||||
}else {
|
|
||||||
Node relParentNode = directoryNodeMap.get(relParentPath.toString());
|
|
||||||
if (relParentNode==null) {
|
|
||||||
relParentNode = createPath(relParentPath.toString(), directoryNodeMap, rootNode, ses, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(relParentNode.getIdentifier()).with(ses).build();
|
|
||||||
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
|
|
||||||
directoryNodeMap.put(relParentPath.append(name).append("/").toString(), createdNode);
|
|
||||||
return createdNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Node create(GCubeItemCreationParameters params, Node destination) throws Exception{
|
|
||||||
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
|
|
||||||
Node newNode = Utils.createGcubeItemInternally(params.getSession(), destination, params.getItem().getName(), params.getItem().getDescription(), params.getUser(), params.getItem(), accountingHandler);
|
|
||||||
params.getSession().save();
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, StorageHubException{
|
|
||||||
|
|
||||||
Node newNode;
|
|
||||||
FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL);
|
|
||||||
FolderManager folderManager = pluginHandler.getFolderManager(destinationItem);
|
|
||||||
StorageBackend storageBackend = folderManager.getStorageBackend();
|
|
||||||
String relativePath = destinationNode.getPath();
|
|
||||||
|
|
||||||
if (destinationItem.isExternalManaged())
|
|
||||||
relativePath = relativePath.replace(folderManager.getRootFolder().getPath(), "");
|
|
||||||
|
|
||||||
|
|
||||||
String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath();
|
|
||||||
|
|
||||||
if (ses.nodeExists(newNodePath)) {
|
|
||||||
|
|
||||||
if (!folderManager.manageVersion())
|
|
||||||
throw new InvalidCallParameters("storage for plugin "+folderManager.getClass().getName()+" doesn't support versioning");
|
|
||||||
newNode = ses.getNode(newNodePath);
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, login, newNode.getIdentifier(), false);
|
|
||||||
|
|
||||||
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath,login);
|
|
||||||
|
|
||||||
if (withLock) {
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
|
|
||||||
}catch (LockException le) {
|
|
||||||
throw new ItemLockedException(le);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
versionHandler.checkoutContentNode(newNode);
|
|
||||||
log.trace("replacing content of class {}",item.getContent().getClass());
|
|
||||||
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
|
|
||||||
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, login, false);
|
|
||||||
ses.save();
|
|
||||||
}finally {
|
|
||||||
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true);
|
|
||||||
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath, login);
|
|
||||||
if (withLock) {
|
|
||||||
try {
|
|
||||||
log.debug("trying to acquire lock");
|
|
||||||
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
|
|
||||||
}catch (LockException le) {
|
|
||||||
throw new ItemLockedException(le);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
newNode = item2Node.getNode(destinationNode, item);
|
|
||||||
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode, login, false);
|
|
||||||
ses.save();
|
|
||||||
}finally {
|
|
||||||
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
|
|
||||||
}
|
|
||||||
versionHandler.makeVersionableContent(newNode);
|
|
||||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, login, destinationNode, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name, String description, String relPath, String login) throws BackendGenericError{
|
|
||||||
ContentHandler handler = getContentHandler(stream, storageBackend, name, relPath, login);
|
|
||||||
AbstractFileItem item =handler.buildItem(name, description, login);
|
|
||||||
return item ;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError {
|
|
||||||
|
|
||||||
|
|
||||||
final MultipleOutputStream mos;
|
|
||||||
try{
|
|
||||||
mos = new MultipleOutputStream(stream, 2);
|
|
||||||
}catch (IOException e) {
|
|
||||||
throw new BackendGenericError(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ContentHandler call() throws Exception {
|
|
||||||
ContentHandler handler =null;
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
log.debug("TIMING: reading the mimetype - start");
|
|
||||||
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
|
|
||||||
org.apache.tika.mime.MediaType mediaType = null;
|
|
||||||
TikaConfig config = TikaConfig.getDefaultConfig();
|
|
||||||
Detector detector = config.getDetector();
|
|
||||||
TikaInputStream stream = TikaInputStream.get(is1);
|
|
||||||
Metadata metadata = new Metadata();
|
|
||||||
metadata.add(Metadata.RESOURCE_NAME_KEY, name);
|
|
||||||
mediaType = detector.detect(stream, metadata);
|
|
||||||
String mimeType = mediaType.getBaseType().toString();
|
|
||||||
|
|
||||||
handler = contenthandlerFactory.create(mimeType);
|
|
||||||
|
|
||||||
is1.reset();
|
|
||||||
handler.initiliseSpecificContent(is1, name, mimeType);
|
|
||||||
|
|
||||||
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("error retrieving mimeType",e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MetaInfo call() throws Exception {
|
|
||||||
try(InputStream is1 = mos.get()){
|
|
||||||
MetaInfo info = storageBackend.upload(is1, relPath, name);
|
|
||||||
return info;
|
|
||||||
}catch (Throwable e) {
|
|
||||||
log.error("error writing content",e );
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
|
|
||||||
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
log.debug("TIMING: writing the stream - start");
|
|
||||||
try {
|
|
||||||
mos.startWriting();
|
|
||||||
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
|
|
||||||
|
|
||||||
ContentHandler handler = detectorF.get();
|
|
||||||
MetaInfo info = uploaderF.get();
|
|
||||||
handler.getContent().setData(NodeConstants.CONTENT_NAME);
|
|
||||||
handler.getContent().setStorageId(info.getStorageId());
|
|
||||||
handler.getContent().setSize(info.getSize());
|
|
||||||
handler.getContent().setRemotePath(info.getRemotePath());
|
|
||||||
return handler;
|
|
||||||
}catch (Exception e) {
|
|
||||||
throw new BackendGenericError(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
||||||
|
|
||||||
public class ArchiveStructureCreationParameter extends CreateParameters {
|
|
||||||
|
|
||||||
String parentFolderName;
|
|
||||||
FormDataContentDisposition fileDetails;
|
|
||||||
InputStream stream;
|
|
||||||
|
|
||||||
|
|
||||||
protected ArchiveStructureCreationParameter() {}
|
|
||||||
|
|
||||||
public String getParentFolderName() {
|
|
||||||
return parentFolderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormDataContentDisposition getFileDetails() {
|
|
||||||
return fileDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getStream() {
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValid() {
|
|
||||||
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream) && Objects.nonNull(fileDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "FileCreationParameters [parentFolder=" + parentFolderName + ", fileDetails=" + fileDetails
|
|
||||||
+ ", parentId=" + parentId + ", user=" + user + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ArchiveCreationBuilder builder() {
|
|
||||||
return new ArchiveCreationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ArchiveCreationBuilder extends ItemsParameterBuilder<ArchiveStructureCreationParameter>{
|
|
||||||
|
|
||||||
private ArchiveCreationBuilder() {
|
|
||||||
super(new ArchiveStructureCreationParameter());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArchiveCreationBuilder parentName(String name) {
|
|
||||||
parameters.parentFolderName = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ArchiveCreationBuilder stream(InputStream stream) {
|
|
||||||
parameters.stream = stream;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArchiveCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
|
|
||||||
parameters.fileDetails = fileDetails;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManagedType getMangedType() {
|
|
||||||
return ManagedType.ARCHIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
public abstract class CreateParameters {
|
|
||||||
|
|
||||||
public enum ManagedType {
|
|
||||||
FILE,
|
|
||||||
FOLDER,
|
|
||||||
ARCHIVE,
|
|
||||||
URL,
|
|
||||||
GCUBEITEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
String parentId;
|
|
||||||
Session session;
|
|
||||||
String user;
|
|
||||||
|
|
||||||
protected CreateParameters() {}
|
|
||||||
|
|
||||||
public abstract ManagedType getMangedType();
|
|
||||||
|
|
||||||
public String getParentId() {
|
|
||||||
return parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Session getSession() {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUser() {
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract boolean isValid();
|
|
||||||
|
|
||||||
public abstract String toString();
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
||||||
|
|
||||||
public class FileCreationParameters extends CreateParameters {
|
|
||||||
|
|
||||||
String name;
|
|
||||||
String description;
|
|
||||||
FormDataContentDisposition fileDetails;
|
|
||||||
InputStream stream;
|
|
||||||
|
|
||||||
|
|
||||||
protected FileCreationParameters() {}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormDataContentDisposition getFileDetails() {
|
|
||||||
return fileDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getStream() {
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValid() {
|
|
||||||
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "FileCreationParameters [name=" + name + ", description=" + description + ", fileDetails=" + fileDetails
|
|
||||||
+ ", parentId=" + parentId + ", user=" + user + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FileCreationBuilder builder() {
|
|
||||||
return new FileCreationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FileCreationBuilder extends ItemsParameterBuilder<FileCreationParameters>{
|
|
||||||
|
|
||||||
private FileCreationBuilder() {
|
|
||||||
super(new FileCreationParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileCreationBuilder name(String name) {
|
|
||||||
parameters.name = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileCreationBuilder description(String description) {
|
|
||||||
parameters.description = description;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileCreationBuilder stream(InputStream stream) {
|
|
||||||
parameters.stream = stream;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
|
|
||||||
parameters.fileDetails = fileDetails;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManagedType getMangedType() {
|
|
||||||
return ManagedType.FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.plugins.PluginParameters;
|
|
||||||
|
|
||||||
public class FolderCreationParameters extends CreateParameters {
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private String description="";
|
|
||||||
private boolean hidden = false;
|
|
||||||
private String externalPluginName = null;
|
|
||||||
private PluginParameters externalPluginParameters = null;
|
|
||||||
|
|
||||||
protected FolderCreationParameters() {}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHidden() {
|
|
||||||
return hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExternal() {
|
|
||||||
return externalPluginName!=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPluginName(String name) {
|
|
||||||
return this.externalPluginName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PluginParameters getPluginParameters() {
|
|
||||||
return externalPluginParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValid() {
|
|
||||||
return Objects.nonNull(name) && Objects.nonNull(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "FolderCreationParameters [name=" + name + ", description=" + description + ", hidden=" + hidden
|
|
||||||
+ ", parentId=" + parentId + ", session=" + session + ", user=" + user + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static FolderCreationBuilder builder() {
|
|
||||||
return new FolderCreationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FolderCreationBuilder extends ItemsParameterBuilder<FolderCreationParameters>{
|
|
||||||
|
|
||||||
private FolderCreationBuilder() {
|
|
||||||
super(new FolderCreationParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderCreationBuilder name(String name) {
|
|
||||||
parameters.name = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderCreationBuilder description(String description) {
|
|
||||||
parameters.description = description;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ExternalFolderCreationBuilder onRepository(String pluginName) {
|
|
||||||
return new ExternalFolderCreationBuilder(pluginName, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderCreationBuilder hidden(boolean hidden) {
|
|
||||||
parameters.hidden = hidden;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExternalFolderCreationBuilder {
|
|
||||||
|
|
||||||
FolderCreationBuilder cb;
|
|
||||||
|
|
||||||
protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
|
|
||||||
this.cb.parameters.externalPluginName = pluginName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderCreationBuilder withParameters(PluginParameters params){
|
|
||||||
this.cb.parameters.externalPluginParameters = params;
|
|
||||||
return this.cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManagedType getMangedType() {
|
|
||||||
return ManagedType.FOLDER;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
|
||||||
|
|
||||||
public class GCubeItemCreationParameters extends CreateParameters{
|
|
||||||
|
|
||||||
GCubeItem item;
|
|
||||||
|
|
||||||
|
|
||||||
protected GCubeItemCreationParameters() {}
|
|
||||||
|
|
||||||
public GCubeItem getItem() {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValid() {
|
|
||||||
return Objects.nonNull(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "GCubeItemCreationParameters [item=" + item + ", parentId=" + parentId + ", user=" + user + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GCubeItemCreationBuilder builder() {
|
|
||||||
return new GCubeItemCreationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GCubeItemCreationBuilder extends ItemsParameterBuilder<GCubeItemCreationParameters>{
|
|
||||||
|
|
||||||
private GCubeItemCreationBuilder() {
|
|
||||||
super(new GCubeItemCreationParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
public GCubeItemCreationBuilder item(GCubeItem item) {
|
|
||||||
parameters.item = item;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManagedType getMangedType() {
|
|
||||||
return ManagedType.GCUBEITEM;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
|
|
||||||
public abstract class ItemsParameterBuilder<T extends CreateParameters> {
|
|
||||||
|
|
||||||
T parameters;
|
|
||||||
|
|
||||||
protected ItemsParameterBuilder(T parameters) {
|
|
||||||
super();
|
|
||||||
this.parameters = parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemsParameterBuilder<T> on(String parentId) {
|
|
||||||
parameters.parentId = parentId;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemsParameterBuilder<T> author(String author) {
|
|
||||||
parameters.user = author;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemsParameterBuilder<T> with(Session session){
|
|
||||||
parameters.session = session;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T build() throws InvalidCallParameters {
|
|
||||||
if (!(parameters.isValid() && Objects.nonNull(parameters.parentId)))
|
|
||||||
throw new InvalidCallParameters("invalid call");
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class URLCreationParameters extends CreateParameters {
|
|
||||||
|
|
||||||
String name;
|
|
||||||
String description;
|
|
||||||
URL url;
|
|
||||||
|
|
||||||
|
|
||||||
protected URLCreationParameters() {}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public URL getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValid() {
|
|
||||||
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "URLCreationParameters [name=" + name + ", description=" + description + ", url=" + url + ", parentId="
|
|
||||||
+ parentId + ", user=" + user + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static URLCreationBuilder builder() {
|
|
||||||
return new URLCreationBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class URLCreationBuilder extends ItemsParameterBuilder<URLCreationParameters>{
|
|
||||||
|
|
||||||
private URLCreationBuilder() {
|
|
||||||
super(new URLCreationParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
public URLCreationBuilder name(String name) {
|
|
||||||
parameters.name = name;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public URLCreationBuilder description(String description) {
|
|
||||||
parameters.description = description;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public URLCreationBuilder url(URL url) {
|
|
||||||
parameters.url = url;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ManagedType getMangedType() {
|
|
||||||
return ManagedType.URL;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.plugins;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.enterprise.inject.Default;
|
|
||||||
import javax.enterprise.inject.Instance;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
|
||||||
import org.gcube.common.storagehub.model.items.ExternalFolder;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeFolderManager;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class FolderPluginHandler {
|
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(FolderPluginHandler.class);
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Node2ItemConverter node2Item;
|
|
||||||
|
|
||||||
private GcubeFolderManager defaultManager = new GcubeFolderManager();
|
|
||||||
|
|
||||||
public FolderManager getDefault() {
|
|
||||||
return defaultManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Instance<FolderManagerConnector> connectors;
|
|
||||||
|
|
||||||
private Map<String, FolderManagerConnector> connectorsMap;
|
|
||||||
|
|
||||||
FolderPluginHandler(){
|
|
||||||
if (connectors !=null)
|
|
||||||
connectorsMap = connectors.stream().collect(Collectors.toMap(FolderManagerConnector::getName, e -> e ));
|
|
||||||
else {
|
|
||||||
log.info("connectors are null");
|
|
||||||
connectorsMap = Collections.emptyMap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderManagerConnector getConnector(String name) throws PluginNotFoundException {
|
|
||||||
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
|
|
||||||
return connectorsMap.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FolderManager getFolderManager(Item item) throws PluginInitializationException, PluginNotFoundException, RepositoryException, BackendGenericError{
|
|
||||||
if (!item.isExternalManaged())
|
|
||||||
return defaultManager;
|
|
||||||
Session session = ((Node)item.getRelatedNode()).getSession();
|
|
||||||
Item parent = null;
|
|
||||||
do {
|
|
||||||
String parentId = item.getParentId();
|
|
||||||
Node node = session.getNodeByIdentifier(parentId);
|
|
||||||
parent = node2Item.getItem(node, Excludes.ALL);
|
|
||||||
|
|
||||||
if (parent !=null && parent instanceof ExternalFolder) {
|
|
||||||
ExternalFolder extParent = (ExternalFolder) parent;
|
|
||||||
String plugin = extParent.getManagedBy();
|
|
||||||
Map<String, Object> parameters = extParent.getConnectionParameters().getMap();
|
|
||||||
return getConnector(plugin).connect(extParent, parameters);
|
|
||||||
}
|
|
||||||
} while (parent!=null);
|
|
||||||
throw new BackendGenericError("selected external managed item doesn't have a parent external folder");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.plugins;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class OperationMediator {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
FolderPluginHandler folderHandler;
|
|
||||||
|
|
||||||
/*
|
|
||||||
boolean onMove(Item source, Item destination, Session session) throws PluginInitializationException, PluginNotFoundException, BackendGenericError, RepositoryException{
|
|
||||||
FolderManager sourceFolderManager = folderHandler.getFolderManager(source);
|
|
||||||
FolderManager destinationFolderManager = folderHandler.getFolderManager(destination);
|
|
||||||
|
|
||||||
if (source instanceof FolderItem) {
|
|
||||||
destinationFolderManager.onCreatedFolder((FolderItem) source);
|
|
||||||
|
|
||||||
|
|
||||||
session.move(source.getPath(), destination.getPath());
|
|
||||||
sourceFolderManager.onDeletingFolder((FolderItem) source);
|
|
||||||
} else if (source instanceof AbstractFileItem){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.vres;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.SimpleCredentials;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
||||||
import org.apache.jackrabbit.api.security.user.Group;
|
|
||||||
import org.apache.jackrabbit.api.security.user.User;
|
|
||||||
import org.apache.jackrabbit.api.security.user.UserManager;
|
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
|
||||||
import org.gcube.common.scope.impl.ScopeBean;
|
|
||||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.GroupHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class VREManager {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
|
|
||||||
|
|
||||||
private Map<String, VRE> vreMap = new HashMap<>();
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
RepositoryInitializer repository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Node2ItemConverter node2Item;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
GroupHandler groupHandler;
|
|
||||||
|
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
|
||||||
|
|
||||||
SimpleCredentials credentials;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public VREManager(ServletContext context) {
|
|
||||||
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized VRE getVRE(String completeName) {
|
|
||||||
logger.trace("requesting VRE {}",completeName);
|
|
||||||
if (vreMap.containsKey(completeName))
|
|
||||||
return vreMap.get(completeName);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized VRE putVRE(Item vreFolder) {
|
|
||||||
logger.trace("inserting VRE {}",vreFolder.getTitle());
|
|
||||||
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
|
|
||||||
else {
|
|
||||||
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, node2Item, executor);
|
|
||||||
vreMap.put(vreFolder.getTitle(), toReturn);
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized VRE getVreFolderItem(JackrabbitSession ses, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
|
|
||||||
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
|
|
||||||
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
|
|
||||||
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
|
|
||||||
return getVreFolderItemByGroupName(ses, entireScopeName, userId, excludes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public synchronized VRE getVreFolderItemByGroupName(JackrabbitSession ses, String groupName, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
|
|
||||||
UserManager um = ses.getUserManager();
|
|
||||||
Group groupAuth = um.getAuthorizable(groupName, Group.class);
|
|
||||||
User userAuth = um.getAuthorizable(userId, User.class);
|
|
||||||
|
|
||||||
if (groupAuth == null || userAuth == null || !groupAuth.isMember(userAuth))
|
|
||||||
throw new InvalidCallParameters("error getting VRE with user "+userId+" for group "+groupName);
|
|
||||||
|
|
||||||
|
|
||||||
VRE vre = this.getVRE(groupName);
|
|
||||||
if (vre!=null) return vre;
|
|
||||||
else {
|
|
||||||
|
|
||||||
Node vreFolderNode = groupHandler.getFolderNodeRelatedToGroup(ses, groupName);
|
|
||||||
|
|
||||||
Item vreFolder = node2Item.getItem(vreFolderNode, excludes);
|
|
||||||
return this.putVRE(vreFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,274 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.vres;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.jcr.Credentials;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.NodeIterator;
|
|
||||||
import javax.jcr.Property;
|
|
||||||
import javax.jcr.Repository;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.jcr.observation.Event;
|
|
||||||
import javax.jcr.observation.EventJournal;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class VREQueryRetriever implements Callable<List<Item>> {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
|
|
||||||
|
|
||||||
private static final int CACHE_DIMENSION = 50;
|
|
||||||
|
|
||||||
private Repository repository;
|
|
||||||
private Credentials credentials;
|
|
||||||
private Item vreFolder;
|
|
||||||
Map<String, Long> cachedMap = new HashMap<>(CACHE_DIMENSION);
|
|
||||||
|
|
||||||
long lastTimestamp =0;
|
|
||||||
|
|
||||||
long doTime= 0;
|
|
||||||
boolean underRedo = false;
|
|
||||||
Node2ItemConverter node2Item;
|
|
||||||
|
|
||||||
private static int TIME_MEASURE = Calendar.MINUTE;
|
|
||||||
private static int VALUE_TIME_BEFORE = 30;
|
|
||||||
|
|
||||||
|
|
||||||
public VREQueryRetriever(Repository repository, Credentials credentials, Node2ItemConverter node2Item, Item vreFolder) {
|
|
||||||
super();
|
|
||||||
this.repository = repository;
|
|
||||||
this.credentials = credentials;
|
|
||||||
this.vreFolder = vreFolder;
|
|
||||||
this.node2Item = node2Item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Item> call() {
|
|
||||||
Session ses = null;
|
|
||||||
try {
|
|
||||||
ses = repository.login(credentials);
|
|
||||||
Calendar now = Calendar.getInstance();
|
|
||||||
now.add(TIME_MEASURE, -1*Math.abs(VALUE_TIME_BEFORE));
|
|
||||||
|
|
||||||
if (doTime> now.getTimeInMillis() || underRedo) {
|
|
||||||
logger.debug("executing recents task for {} (cahced result)",vreFolder.getTitle());
|
|
||||||
return correctValues(ses, cachedMap);
|
|
||||||
}else {
|
|
||||||
logger.debug("executing recents task for {} (redoing it)",vreFolder.getTitle());
|
|
||||||
List<Item> toReturn = redo(ses);
|
|
||||||
doTime = System.currentTimeMillis();
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
}catch (Exception e) {
|
|
||||||
logger.error("error preparing recents for folder {}", vreFolder.getTitle(),e);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
logger.debug("recents task finished");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized List<Item> redo(Session ses) {
|
|
||||||
underRedo = true;
|
|
||||||
try {
|
|
||||||
Map<String, Long> tempCachedMap = new HashMap<>(cachedMap);
|
|
||||||
if (cachedMap.isEmpty())
|
|
||||||
init(ses, tempCachedMap);
|
|
||||||
else {
|
|
||||||
logger.debug("redoing recents for {}",vreFolder.getTitle());
|
|
||||||
update(ses, tempCachedMap);
|
|
||||||
}
|
|
||||||
cachedMap = tempCachedMap;
|
|
||||||
return correctValues(ses, tempCachedMap);
|
|
||||||
}finally{
|
|
||||||
underRedo = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private List<Item> correctValues(Session ses, Map<String, Long> tempCachedMap){
|
|
||||||
logger.debug("preparing returning values for {}",vreFolder.getTitle());
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
List<Map.Entry<String, Long>> list = new LinkedList<>(tempCachedMap.entrySet());
|
|
||||||
list.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue())*-1);
|
|
||||||
if (list.size()>CACHE_DIMENSION)
|
|
||||||
for (int index = CACHE_DIMENSION-1; index< list.size() ; index++)
|
|
||||||
tempCachedMap.remove(list.get(index).getKey());
|
|
||||||
|
|
||||||
List<String> cachedIds = list.stream().map(m -> m.getKey()).collect(Collectors.toList());
|
|
||||||
if (cachedIds.size()>10)
|
|
||||||
cachedIds = cachedIds.subList(0, 10);
|
|
||||||
|
|
||||||
List<Item> result = new ArrayList<>(10);
|
|
||||||
|
|
||||||
for (String id: cachedIds) {
|
|
||||||
try {
|
|
||||||
Item item = node2Item.getItem(id, ses, Excludes.EXCLUDE_ACCOUNTING);
|
|
||||||
if (item!=null)
|
|
||||||
result.add(item);
|
|
||||||
else logger.warn("item with id {} is null",id);
|
|
||||||
} catch (BackendGenericError | RepositoryException e) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("returning values prepared in {} for {}",System.currentTimeMillis()-start,vreFolder.getTitle());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void insertItemInTheRightPlace(Item item, Map<String, Long> tempCachedMap) {
|
|
||||||
long lastModifiedTime = item.getLastModificationTime().getTimeInMillis();
|
|
||||||
|
|
||||||
if (tempCachedMap.size()<CACHE_DIMENSION || lastModifiedTime>Collections.min(tempCachedMap.values()))
|
|
||||||
tempCachedMap.put(item.getId(), lastModifiedTime);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(Session ses,Map<String, Long> tempCachedMap){
|
|
||||||
try {
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
lastTimestamp = System.currentTimeMillis();
|
|
||||||
Node vreFolderNode = ses.getNodeByIdentifier(vreFolder.getId());
|
|
||||||
logger.debug("starting visiting children for {}",vreFolder.getTitle());
|
|
||||||
visitChildren(vreFolderNode, tempCachedMap);
|
|
||||||
logger.debug("initializing recents for {} took {}",vreFolder.getTitle(),System.currentTimeMillis()-start);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("error querying vre {}",vreFolder.getTitle(),e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void update(Session ses, Map<String, Long> tempCachedMap) {
|
|
||||||
try {
|
|
||||||
long timestampToUse = lastTimestamp;
|
|
||||||
lastTimestamp = System.currentTimeMillis();
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
|
|
||||||
|
|
||||||
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
|
|
||||||
journalChanged.skipTo(timestampToUse);
|
|
||||||
|
|
||||||
logger.debug("getting the journal took {}",System.currentTimeMillis()-start);
|
|
||||||
|
|
||||||
int events = 0;
|
|
||||||
|
|
||||||
//TODO: manage hidden nodes
|
|
||||||
while (journalChanged.hasNext()) {
|
|
||||||
events++;
|
|
||||||
Event event = journalChanged.nextEvent();
|
|
||||||
try {
|
|
||||||
switch(event.getType()) {
|
|
||||||
|
|
||||||
case Event.NODE_ADDED:
|
|
||||||
if (ses.nodeExists(event.getPath())) {
|
|
||||||
Node nodeAdded = ses.getNode(event.getPath());
|
|
||||||
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
|
||||||
logger.debug("node added event received with name {}", nodeAdded.getName());
|
|
||||||
Item item = node2Item.getItem(nodeAdded, Excludes.ALL);
|
|
||||||
if (tempCachedMap.get(event.getIdentifier())!=null)
|
|
||||||
tempCachedMap.remove(event.getIdentifier());
|
|
||||||
if (item.isHidden())
|
|
||||||
break;
|
|
||||||
insertItemInTheRightPlace(item,tempCachedMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Event.PROPERTY_CHANGED:
|
|
||||||
if (ses.propertyExists(event.getPath())) {
|
|
||||||
Property property = ses.getProperty(event.getPath());
|
|
||||||
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
|
|
||||||
logger.debug("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
|
||||||
String identifier = property.getParent().getIdentifier();
|
|
||||||
tempCachedMap.remove(identifier);
|
|
||||||
Item item = node2Item.getItem(property.getParent(), Excludes.ALL);
|
|
||||||
if (item.isHidden())
|
|
||||||
break;
|
|
||||||
insertItemInTheRightPlace(item, tempCachedMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Event.NODE_REMOVED:
|
|
||||||
logger.trace("node removed event received with type {}", event.getIdentifier());
|
|
||||||
|
|
||||||
if (tempCachedMap.get(event.getIdentifier())!=null &&
|
|
||||||
tempCachedMap.get(event.getIdentifier())<event.getDate())
|
|
||||||
tempCachedMap.remove(event.getIdentifier());
|
|
||||||
break;
|
|
||||||
case Event.NODE_MOVED:
|
|
||||||
Node nodeMoved = ses.getNode(event.getPath());
|
|
||||||
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
|
|
||||||
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
|
|
||||||
logger.debug("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
|
|
||||||
String identifier = nodeMoved.getIdentifier();
|
|
||||||
String nodePath = ses.getNode(identifier).getPath();
|
|
||||||
if (tempCachedMap.get(event.getIdentifier())!=null &&
|
|
||||||
!nodePath.startsWith(vreFolder.getPath()))
|
|
||||||
tempCachedMap.remove(event.getIdentifier());
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}catch (Exception e) {
|
|
||||||
logger.warn("error handling event {}",event.getType(),e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void visitChildren(Node node, Map<String, Long> tempCachedMap) throws Exception{
|
|
||||||
NodeIterator nodeIt = node.getNodes();
|
|
||||||
while(nodeIt.hasNext()) {
|
|
||||||
Node child = nodeIt.nextNode();
|
|
||||||
Item item = node2Item.getItem(child, Excludes.ALL);
|
|
||||||
if (item==null || item.isHidden()) continue;
|
|
||||||
if (item instanceof FolderItem)
|
|
||||||
visitChildren(child,tempCachedMap);
|
|
||||||
else if(item instanceof AbstractFileItem)
|
|
||||||
insertItemInTheRightPlace(item,tempCachedMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @Override
|
|
||||||
public void onEvent(EventIterator events) {
|
|
||||||
logger.trace("on event called");
|
|
||||||
while (events.hasNext()) {
|
|
||||||
Event event = events.nextEvent();
|
|
||||||
try {
|
|
||||||
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
|
|
||||||
} catch (RepositoryException e) {
|
|
||||||
logger.error("error reading event",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.security.Principal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -8,6 +11,9 @@ import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.security.AccessControlEntry;
|
||||||
|
import javax.jcr.security.AccessControlManager;
|
||||||
|
import javax.jcr.security.Privilege;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
|
@ -16,13 +22,19 @@ import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||||
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
|
import org.apache.jackrabbit.api.security.user.Group;
|
||||||
|
import org.apache.jackrabbit.api.security.user.User;
|
||||||
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
|
import org.gcube.common.storagehub.model.acls.ACL;
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
|
@ -35,51 +47,35 @@ import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.VreFolder;
|
import org.gcube.common.storagehub.model.items.VreFolder;
|
||||||
import org.gcube.common.storagehub.model.types.ACLList;
|
import org.gcube.common.storagehub.model.types.ACLList;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("items")
|
@Path("items")
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
public class ACLManager {
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class ACLManager extends Impersonable {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
|
private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@RequestScoped
|
@RequestScoped
|
||||||
@PathParam("id")
|
@PathParam("id")
|
||||||
String id;
|
String id;
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
ServletContext context;
|
ServletContext context;
|
||||||
|
|
||||||
|
|
||||||
@Inject Node2ItemConverter node2Item;
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
|
||||||
@Inject UnshareHandler unshareHandler;
|
@Inject
|
||||||
|
AuthorizationChecker authChecker;
|
||||||
@Inject ACLManagerInterface aclManagerDelegate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the AccessType for all the users in a shared folder
|
* returns the AccessType for all the users in a shared folder
|
||||||
*
|
*
|
||||||
|
@ -92,21 +88,38 @@ public class ACLManager extends Impersonable {
|
||||||
public ACLList getACL() {
|
public ACLList getACL() {
|
||||||
InnerMethodName.instance.set("getACLById");
|
InnerMethodName.instance.set("getACLById");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
List<ACL> acls = new ArrayList<>();
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
String path = ses.getNodeByIdentifier(id).getPath();
|
||||||
return new ACLList(aclManagerDelegate.get(item, ses));
|
log.info("checking acces for path {}",path);
|
||||||
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(ses, path );
|
||||||
|
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
|
||||||
|
ACL acl = new ACL();
|
||||||
|
acl.setPricipal(aclEntry.getPrincipal().getName());
|
||||||
|
List<AccessType> types = new ArrayList<>();
|
||||||
|
for (Privilege priv : aclEntry.getPrivileges())
|
||||||
|
try {
|
||||||
|
types.add(AccessType.fromValue(priv.getName()));
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
|
||||||
|
}
|
||||||
|
acl.setAccessTypes(types);
|
||||||
|
acls.add(acl);
|
||||||
|
}
|
||||||
|
|
||||||
}catch(RepositoryException re){
|
}catch(RepositoryException re){
|
||||||
log.error("jcr error getting acl", re);
|
log.error("jcr error getting acl", re);
|
||||||
throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re));
|
||||||
}catch(StorageHubException she ){
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
return new ACLList(acls);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,53 +139,89 @@ public class ACLManager extends Impersonable {
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Path("{id}/acls")
|
@Path("{id}/acls")
|
||||||
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
public void setACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
||||||
InnerMethodName.instance.set("setACLById");
|
InnerMethodName.instance.set("setACLById");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try {
|
try{
|
||||||
|
|
||||||
if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified");
|
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
Node node = ses.getNodeByIdentifier(id);
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
if (!(item instanceof SharedFolder))
|
if (!(item instanceof SharedFolder))
|
||||||
throw new InvalidItemException("the item is not a shared folder");
|
throw new InvalidItemException("the item is not a shared folder");
|
||||||
|
|
||||||
if (item.getOwner().equals(user))
|
if (item.getOwner().equals(user))
|
||||||
throw new UserNotAuthorizedException("owner acl cannot be changed");
|
throw new UserNotAuthorizedException("owner acl cannot be changed");
|
||||||
|
|
||||||
|
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
|
||||||
|
|
||||||
|
SharedFolder folder = ((SharedFolder)item);
|
||||||
|
|
||||||
SharedFolder folder = (SharedFolder) item;
|
|
||||||
|
|
||||||
authChecker.checkAdministratorControl(ses, currentUser, folder);
|
|
||||||
|
|
||||||
if (folder.isVreFolder()) {
|
if (folder.isVreFolder()) {
|
||||||
if (accessType==AccessType.ADMINISTRATOR) throw new InvalidCallParameters("a VRE admin cannot be changed with this method");
|
if (accessType!=AccessType.ADMINISTRATOR)
|
||||||
|
throw new InvalidCallParameters("acls in vreFolder cannot be changed, only new admin can be set");
|
||||||
|
|
||||||
if (!user.equals(folder.getTitle())) throw new InvalidCallParameters("the groupId in the argument is different to the one of the VREFolder");
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)ses).getUserManager();
|
||||||
|
|
||||||
|
String groupId = folder.getTitle();
|
||||||
|
|
||||||
|
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||||
|
User authUser = (User)usrManager.getAuthorizable(user);
|
||||||
|
|
||||||
|
if (!group.isMember(authUser))
|
||||||
|
throw new InvalidCallParameters("user "+user+" is not in the group "+groupId);
|
||||||
|
|
||||||
|
String path = node.getPath();
|
||||||
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path);
|
||||||
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
||||||
|
Principal principal = AccessControlUtils.getPrincipal(ses, user);
|
||||||
|
acls.addAccessControlEntry(principal, userPrivileges);
|
||||||
|
acm.setPolicy(path, acls);
|
||||||
|
ses.save();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
NodeIterator sharedSet = node.getSharedSet();
|
NodeIterator sharedSet = node.getSharedSet();
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
while (sharedSet.hasNext() && !found) {
|
while (sharedSet.hasNext() && !found) {
|
||||||
Node current = sharedSet.nextNode();
|
Node current = sharedSet.nextNode();
|
||||||
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
|
if (current.getPath().startsWith(Utils.getWorkspacePath(user).toPath()))
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
|
throw new InvalidCallParameters("shared folder with id "+item.getId()+" is not shared with user "+user);
|
||||||
|
|
||||||
|
String path = node.getPath();
|
||||||
|
|
||||||
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path);
|
||||||
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
||||||
|
|
||||||
|
AccessControlEntry aceToDelete = null;;
|
||||||
|
Principal principal = AccessControlUtils.getPrincipal(ses, user);
|
||||||
|
for (AccessControlEntry ace : acls.getAccessControlEntries())
|
||||||
|
if (ace.getPrincipal().equals(principal)) {
|
||||||
|
aceToDelete = ace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aceToDelete!= null)
|
||||||
|
acls.removeAccessControlEntry(aceToDelete);
|
||||||
|
acls.addAccessControlEntry(principal, userPrivileges);
|
||||||
|
acm.setPolicy(path, acls);
|
||||||
|
ses.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
aclManagerDelegate.update(user, folder, accessType, ses);
|
|
||||||
|
|
||||||
}catch(RepositoryException re){
|
}catch(RepositoryException re){
|
||||||
log.error("jcr error extracting archive", re);
|
log.error("jcr error extracting archive", re);
|
||||||
throw new WebApplicationException(new BackendGenericError("jcr error setting acl", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
|
||||||
}catch(StorageHubException she ){
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -181,19 +230,18 @@ public class ACLManager extends Impersonable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove right for a user only on Shared folder
|
* remove right for a user only on VRE folder
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param String user
|
* @param String user
|
||||||
*
|
* @param accessType accessType
|
||||||
*
|
*
|
||||||
* @exception {@link RepositoryException} when a generic jcr error occurs
|
* @exception {@link RepositoryException} when a generic jcr error occurs
|
||||||
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
|
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
|
||||||
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
|
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
|
||||||
* @exception {@link InvalidItemException} when the folder is not share
|
* @exception {@link InvalidItemException} when the folder is not share
|
||||||
*/
|
*/
|
||||||
//TODO: is this method correct? can ACL be removed, is correct that this means an unshare operation?
|
/*@DELETE
|
||||||
@DELETE
|
|
||||||
@Consumes(MediaType.TEXT_PLAIN)
|
@Consumes(MediaType.TEXT_PLAIN)
|
||||||
@Path("{id}/acls/{user}")
|
@Path("{id}/acls/{user}")
|
||||||
public void removeACL(@PathParam("user") String user) {
|
public void removeACL(@PathParam("user") String user) {
|
||||||
|
@ -201,24 +249,44 @@ public class ACLManager extends Impersonable {
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
Node node = ses.getNodeByIdentifier(id);
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
if (!(item instanceof SharedFolder))
|
if (!(item instanceof SharedFolder))
|
||||||
throw new InvalidItemException("the item is not a shared folder");
|
throw new InvalidItemException("the item is not a shared folder");
|
||||||
|
|
||||||
if (item instanceof VreFolder || ((SharedFolder) item).isVreFolder())
|
|
||||||
throw new InvalidCallParameters("acls in vreFolder cannot be removed with this method");
|
|
||||||
|
|
||||||
authChecker.checkAdministratorControl(ses, currentUser, (SharedFolder) item);
|
|
||||||
|
|
||||||
unshareHandler.unshare(ses, Collections.singleton(user), node, currentUser);
|
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
|
||||||
|
|
||||||
|
SharedFolder folder = ((SharedFolder)item);
|
||||||
|
|
||||||
|
if (folder.isVreFolder()) {
|
||||||
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
||||||
|
|
||||||
|
|
||||||
|
AccessControlEntry entryToDelete= null;
|
||||||
|
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
||||||
|
if (ace.getPrincipal().getName().equals(user)) {
|
||||||
|
entryToDelete = ace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (entryToDelete!=null)
|
||||||
|
acls.removeAccessControlEntry(entryToDelete);
|
||||||
|
else return;
|
||||||
|
|
||||||
|
acm.setPolicy(folder.getPath(), acls);
|
||||||
|
ses.save();
|
||||||
|
log.debug("removed Access control entry for user {}",user);
|
||||||
|
|
||||||
|
} else throw new InvalidCallParameters("remove acl can be called only on VRE folder");
|
||||||
|
|
||||||
}catch(RepositoryException re){
|
}catch(RepositoryException re){
|
||||||
log.error("jcr error extracting archive", re);
|
log.error("jcr error extracting archive", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing acl", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
|
||||||
}catch(StorageHubException she ){
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
|
@ -226,7 +294,7 @@ public class ACLManager extends Impersonable {
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/acls/write")
|
@Path("{id}/acls/write")
|
||||||
|
@ -242,7 +310,7 @@ public class ACLManager extends Impersonable {
|
||||||
throw new InvalidItemException("this method can be applied only to folder");
|
throw new InvalidItemException("this method can be applied only to folder");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, true);
|
authChecker.checkWriteAuthorizationControl(ses, id, true);
|
||||||
}catch (UserNotAuthorizedException e) {
|
}catch (UserNotAuthorizedException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Path("api-docs")
|
|
||||||
public class DocManager {
|
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(DocManager.class);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{any: .*}")
|
|
||||||
public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException {
|
|
||||||
logger.info(DocManager.class.getSimpleName() + " toDoc called");
|
|
||||||
|
|
||||||
String pathInfo = req.getPathInfo();
|
|
||||||
logger.debug("pathInfo {}", pathInfo);
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (pathInfo.endsWith("/api-docs")) {
|
|
||||||
pathInfo += "index.html";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pathInfo.endsWith("/api-docs/")) {
|
|
||||||
pathInfo += "index.html";
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("going to {}", pathInfo);
|
|
||||||
|
|
||||||
String realPath = req.getServletContext().getRealPath(pathInfo);
|
|
||||||
return new FileInputStream(new File(realPath));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new WebApplicationException("error getting docs",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +1,13 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
|
||||||
import static org.gcube.data.access.storagehub.Roles.VREMANAGER_ROLE;
|
|
||||||
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.NodeIterator;
|
||||||
import javax.jcr.PathNotFoundException;
|
import javax.jcr.PathNotFoundException;
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.security.AccessControlEntry;
|
|
||||||
import javax.jcr.security.AccessControlManager;
|
import javax.jcr.security.AccessControlManager;
|
||||||
import javax.jcr.security.Privilege;
|
import javax.jcr.security.Privilege;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
@ -28,7 +22,6 @@ import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
|
@ -41,82 +34,34 @@ import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils
|
||||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
|
||||||
import org.gcube.common.scope.impl.ScopeBean;
|
|
||||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.GroupHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.vres.VRE;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("groups")
|
@Path("groups")
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class GroupManager {
|
public class GroupManager {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Context ServletContext context;
|
@Context ServletContext context;
|
||||||
|
|
||||||
@Inject
|
|
||||||
TrashHandler trashHandler;
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
VREManager vreManager;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
GroupHandler groupHandler;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Node2ItemConverter node2Item;
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
@Path("")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public List<String> getGroups(){
|
public List<String> getGroups(){
|
||||||
|
|
||||||
InnerMethodName.instance.set("getGroups");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
List<String> groups= new ArrayList<>();
|
List<String> groups= new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
|
@ -135,9 +80,9 @@ public class GroupManager {
|
||||||
log.info("group {} found",group.getPrincipal().getName());
|
log.info("group {} found",group.getPrincipal().getName());
|
||||||
groups.add(group.getPrincipal().getName());
|
groups.add(group.getPrincipal().getName());
|
||||||
}
|
}
|
||||||
}catch(RepositoryException re ){
|
}catch(Exception e) {
|
||||||
log.error("jcr error creating item", re);
|
log.error("jcr error getting groups", e);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
} finally {
|
} finally {
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
|
@ -147,38 +92,24 @@ public class GroupManager {
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("")
|
@Path("")
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner){
|
public String createGroup(@FormParam("group") String group, @FormParam("accessType") AccessType accessType){
|
||||||
|
|
||||||
InnerMethodName.instance.set("createGroup");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
String groupId = null;
|
String groupId = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
log.info("create group called with groupid {} , accessType {} and folderOwner {}",group, accessType, folderOwner);
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
|
||||||
Group createdGroup = usrManager.createGroup(group);
|
Group createdGroup = usrManager.createGroup(group);
|
||||||
groupId = createdGroup.getID();
|
groupId = createdGroup.getID();
|
||||||
|
|
||||||
User user = (User)usrManager.getAuthorizable(folderOwner);
|
createVreFolder(groupId, session, accessType!=null?accessType:AccessType.WRITE_OWNER);
|
||||||
|
|
||||||
createVreFolder(groupId, session, accessType!=null?accessType:AccessType.WRITE_OWNER, folderOwner);
|
|
||||||
|
|
||||||
boolean success = this.internalAddUserToGroup(session, createdGroup, user);
|
|
||||||
|
|
||||||
if (!success) log.warn("the user have not been added to the group");
|
|
||||||
else log.debug("the user have been added to the group");
|
|
||||||
session.save();
|
session.save();
|
||||||
}catch(StorageHubException se) {
|
}catch(Exception e) {
|
||||||
log.error("error creating group {}", group, se);
|
|
||||||
GXOutboundErrorResponse.throwException(se);
|
|
||||||
}catch(Throwable e) {
|
|
||||||
log.error("jcr error creating group {}", group, e);
|
log.error("jcr error creating group {}", group, e);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -191,207 +122,44 @@ public class GroupManager {
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{group}")
|
@Path("{group}")
|
||||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public String deleteGroup(@PathParam("group") String group){
|
public String deleteGroup(@PathParam("group") String group){
|
||||||
|
|
||||||
InnerMethodName.instance.set("deleteGroup");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
|
||||||
Authorizable authorizable = usrManager.getAuthorizable(group);
|
|
||||||
if (authorizable!=null && authorizable.isGroup())
|
|
||||||
authorizable.remove();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Node node = groupHandler.getFolderNodeRelatedToGroup(session, group);
|
getVreFolderNode(session, group).removeSharedSet();
|
||||||
List<Item> workspaceItems = Utils.getItemList(node, Excludes.GET_ONLY_CONTENT, null, true, null);
|
|
||||||
trashHandler.removeOnlyNodesContent(session, workspaceItems);
|
|
||||||
node.removeSharedSet();
|
|
||||||
}catch (Exception e) {
|
}catch (Exception e) {
|
||||||
log.warn("vreFolder {} not found, removing only the group", group);
|
log.warn("vreFolder {} not found, removing only the group", group);
|
||||||
}
|
}
|
||||||
|
Authorizable authorizable = usrManager.getAuthorizable(group);
|
||||||
|
if (authorizable.isGroup())
|
||||||
|
authorizable.remove();
|
||||||
session.save();
|
session.save();
|
||||||
}catch(RepositoryException re ){
|
}catch(Exception e) {
|
||||||
log.error("jcr error creating item", re);
|
log.error("jcr error getting users", e);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
} finally {
|
} finally {
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isInfraManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); }
|
|
||||||
|
|
||||||
public boolean isVREManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(VREMANAGER_ROLE); }
|
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{id}/admins")
|
@Path("{id}")
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
|
|
||||||
InnerMethodName.instance.set("addAdmin");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
|
||||||
try {
|
|
||||||
Objects.nonNull(groupId);
|
|
||||||
Objects.nonNull(userId);
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
|
|
||||||
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
|
|
||||||
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
|
|
||||||
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
|
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)session).getUserManager();
|
|
||||||
|
|
||||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
|
||||||
User authUser = (User)usrManager.getAuthorizable(userId);
|
|
||||||
|
|
||||||
if (group ==null)
|
|
||||||
throw new InvalidCallParameters("invalid group "+groupId);
|
|
||||||
if (authUser ==null)
|
|
||||||
throw new InvalidCallParameters("invalid user "+userId);
|
|
||||||
|
|
||||||
if (!group.isMember(authUser))
|
|
||||||
throw new InvalidCallParameters("user "+userId+" is not in the group "+groupId);
|
|
||||||
|
|
||||||
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
|
|
||||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
||||||
Principal principal = AccessControlUtils.getPrincipal(session, userId);
|
|
||||||
acls.addAccessControlEntry(principal, userPrivileges);
|
|
||||||
acm.setPolicy(vreFolder.getPath(), acls);
|
|
||||||
|
|
||||||
session.save();
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}catch(Throwable re ){
|
|
||||||
log.error("adding admin to VREFolder", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error adding admin to VREFolder", re));
|
|
||||||
} finally {
|
|
||||||
if (session!=null)
|
|
||||||
session.logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DELETE
|
|
||||||
@Path("{id}/admins/{userId}")
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){
|
|
||||||
|
|
||||||
InnerMethodName.instance.set("removeAdmin");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Objects.nonNull(groupId);
|
|
||||||
Objects.nonNull(userId);
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
|
|
||||||
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
|
|
||||||
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
|
|
||||||
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
|
|
||||||
|
|
||||||
AccessControlEntry toRemove = null;
|
|
||||||
for (AccessControlEntry acl: acls.getAccessControlEntries())
|
|
||||||
if (acl.getPrincipal().getName().equals(userId)) {
|
|
||||||
toRemove = acl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
acls.removeAccessControlEntry(toRemove);
|
|
||||||
acm.setPolicy(vreFolder.getPath(), acls);
|
|
||||||
session.save();
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}catch(Throwable re ){
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re));
|
|
||||||
}finally {
|
|
||||||
if (session!=null)
|
|
||||||
session.logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{groupId}/admins")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public List<String> getAdmins(@PathParam("groupId") String groupId){
|
|
||||||
|
|
||||||
InnerMethodName.instance.set("getAdmins");
|
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
|
||||||
List<String> users = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
VRE vreFolder = vreManager.getVreFolderItemByGroupName(session, groupId, login, Excludes.ALL);
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
|
||||||
//authChecker.checkAdministratorControl(session, (VreFolder)vreFolder.getVreFolder());
|
|
||||||
Node node = session.getNodeByIdentifier(vreFolder.getVreFolder().getId());
|
|
||||||
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, node.getPath());
|
|
||||||
|
|
||||||
for (AccessControlEntry acl: acls.getAccessControlEntries())
|
|
||||||
for (Privilege pr: acl.getPrivileges()) {
|
|
||||||
if (pr.getName().equals(AccessType.ADMINISTRATOR.getValue())){
|
|
||||||
users.add(acl.getPrincipal().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}catch(Exception re ){
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
}finally {
|
|
||||||
if (session!=null)
|
|
||||||
session.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@PUT
|
|
||||||
@Path("{id}/users")
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
|
||||||
public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
||||||
|
|
||||||
InnerMethodName.instance.set("addUserToGroup");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!isInfraManager() && !isValidGroupForContext(groupId))
|
|
||||||
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
@ -399,22 +167,20 @@ public class GroupManager {
|
||||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||||
User user = (User)usrManager.getAuthorizable(userId);
|
User user = (User)usrManager.getAuthorizable(userId);
|
||||||
|
|
||||||
if (user==null)
|
success = group.addMember(user);
|
||||||
throw new InvalidCallParameters("user "+userId+" not exists");
|
|
||||||
|
|
||||||
if (group.isMember(user))
|
|
||||||
throw new InvalidCallParameters("user "+userId+" is already member of group "+groupId);
|
|
||||||
|
|
||||||
this.internalAddUserToGroup(session, group, user);
|
String folderName = group.getPrincipal().getName();
|
||||||
|
Node folder = getVreFolderNode(session, folderName);
|
||||||
|
|
||||||
|
String userPath = String.format("%s%s/%s",Utils.getWorkspacePath(user.getPrincipal().getName()).toPath(),Constants.VRE_FOLDER_PARENT_NAME, folderName);
|
||||||
|
log.debug("creating folder in user path {}", userPath );
|
||||||
|
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
|
||||||
|
|
||||||
session.save();
|
session.save();
|
||||||
}catch(StorageHubException she ){
|
}catch(Exception e) {
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error("jcr error adding user {} to group {}", userId, groupId, e);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
}catch(RepositoryException re ){
|
} finally {
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
}finally {
|
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
}
|
}
|
||||||
|
@ -422,51 +188,40 @@ public class GroupManager {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean internalAddUserToGroup(JackrabbitSession session, Group group, User user) throws RepositoryException, StorageHubException {
|
|
||||||
boolean success = group.addMember(user);
|
|
||||||
session.save();
|
|
||||||
String folderName = group.getPrincipal().getName();
|
|
||||||
Node folder = groupHandler.getFolderNodeRelatedToGroup(session, folderName);
|
|
||||||
|
|
||||||
String userPath = Paths.append(pathUtil.getVREsPath(user.getPrincipal().getName(), session), folderName).toPath();
|
|
||||||
log.debug("creating folder in user path {} from {}", userPath, folder.getPath() );
|
|
||||||
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
|
|
||||||
|
|
||||||
try {
|
|
||||||
session.getNode(userPath);
|
|
||||||
log.debug("the new folder exists ({}) ", userPath );
|
|
||||||
}catch (PathNotFoundException e) {
|
|
||||||
log.debug("the new folder doesn't exists ({}) ", userPath );
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{groupId}/users/{userId}")
|
@Path("{groupId}/users/{userId}")
|
||||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
|
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
|
||||||
|
|
||||||
InnerMethodName.instance.set("removeUserFromGroup");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!isValidGroupForContext(groupId) && !isInfraManager())
|
|
||||||
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
success = groupHandler.removeUserFromGroup(groupId, userId, session);
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
|
||||||
|
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||||
|
User user = (User)usrManager.getAuthorizable(userId);
|
||||||
|
|
||||||
|
//delete folder on user
|
||||||
|
String folderName = group.getPrincipal().getName();
|
||||||
|
Node folder = getVreFolderNode(session, folderName);
|
||||||
|
|
||||||
|
NodeIterator ni = folder.getSharedSet();
|
||||||
|
while (ni.hasNext()) {
|
||||||
|
Node node = ni.nextNode();
|
||||||
|
if (node.getPath().startsWith(Utils.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
|
||||||
|
node.removeShare();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
success = group.removeMember(user);
|
||||||
|
|
||||||
session.save();
|
session.save();
|
||||||
}catch(StorageHubException she ){
|
}catch(Exception e) {
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error("jcr error adding user {} to group {}", userId, groupId, e);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
}catch(RepositoryException re ){
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
} finally {
|
} finally {
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
|
@ -478,18 +233,12 @@ public class GroupManager {
|
||||||
@GET
|
@GET
|
||||||
@Path("{groupId}/users")
|
@Path("{groupId}/users")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
|
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
|
||||||
|
|
||||||
InnerMethodName.instance.set("getUsersOfGroup");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
List<String> users = new ArrayList<>();
|
List<String> users = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!isValidGroupForContext(groupId) && !isInfraManager())
|
|
||||||
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
|
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
@ -504,13 +253,10 @@ public class GroupManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}catch(StorageHubException she ){
|
}catch(Exception e) {
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error("jcr error getting users of group {}", groupId, e);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
}catch(RepositoryException re ){
|
} finally {
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
}finally {
|
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
}
|
}
|
||||||
|
@ -518,53 +264,53 @@ public class GroupManager {
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType, String owner ) throws Exception{
|
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType) throws Exception{
|
||||||
|
|
||||||
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
||||||
|
|
||||||
String name = groupId;
|
String name = groupId;
|
||||||
|
|
||||||
String currentScope = ScopeProvider.instance.get();
|
String title = groupId.substring(groupId.lastIndexOf("-")+1);
|
||||||
ScopeBean bean = new ScopeBean(currentScope);
|
|
||||||
while (!bean.is(Type.INFRASTRUCTURE)) {
|
Node folder= Utils.createFolderInternally(session, sharedRootNode, name, "VREFolder for "+groupId, false, AuthorizationProvider.instance.get().getClient().getId(), null);
|
||||||
bean = bean.enclosingScope();
|
|
||||||
}
|
|
||||||
String root = bean.toString().replaceAll("/", "");
|
|
||||||
|
|
||||||
String displayName = groupId.replaceAll(root+"-[^\\-]*\\-(.*)", "$1");
|
|
||||||
|
|
||||||
log.info("creating vreFolder with name {} and title {} and owner {}", name, displayName, owner);
|
|
||||||
|
|
||||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).description( "VREFolder for "+groupId).author(owner).on(sharedRootNode.getIdentifier()).with(session).build();
|
|
||||||
|
|
||||||
Node folder= Utils.createFolderInternally(folderParameters, null);
|
|
||||||
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
||||||
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
|
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
|
||||||
folder.setProperty(NodeProperty.TITLE.toString(), name);
|
folder.setProperty(NodeProperty.TITLE.toString(), name);
|
||||||
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), displayName);
|
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), title);
|
||||||
session.save();
|
session.save();
|
||||||
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
AccessControlManager acm = session.getAccessControlManager();
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
||||||
|
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
||||||
|
|
||||||
/*Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
||||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session, AuthorizationProvider.instance.get().getClient().getId()), adminPrivileges );
|
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session, AuthorizationProvider.instance.get().getClient().getId()), adminPrivileges );
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
|
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
|
||||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,groupId), usersPrivileges );
|
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,groupId), usersPrivileges );
|
||||||
acm.setPolicy(folder.getPath(), acls);
|
acm.setPolicy(folder.getPath(), acls);
|
||||||
|
|
||||||
log.debug("vrefolder created with id {}",folder.getIdentifier());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isValidGroupForContext(String group){
|
private Node getVreFolderNode(JackrabbitSession session, String name) throws InvalidItemException, Exception {
|
||||||
String currentContext = ScopeProvider.instance.get();
|
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
||||||
String expectedGroupId= currentContext.replace("/", "-").substring(1);
|
|
||||||
return group.equals(expectedGroupId);
|
Node vreFolder = null;
|
||||||
|
try {
|
||||||
|
vreFolder = sharedRootNode.getNode(name);
|
||||||
|
}catch (PathNotFoundException e) {
|
||||||
|
log.debug("is an old HL VRE");
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeIterator nodes = sharedRootNode.getNodes();
|
||||||
|
while (nodes.hasNext()) {
|
||||||
|
Node node = nodes.nextNode();
|
||||||
|
if (node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
|
||||||
|
vreFolder= node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vreFolder==null) throw new InvalidItemException("vre folder not found");
|
||||||
|
return vreFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
|
||||||
|
|
||||||
|
|
||||||
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
|
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
|
||||||
import org.gcube.common.authorization.library.provider.ClientInfo;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Path("")
|
|
||||||
public abstract class Impersonable {
|
|
||||||
|
|
||||||
Logger log = LoggerFactory.getLogger(Impersonable.class);
|
|
||||||
|
|
||||||
String currentUser;
|
|
||||||
|
|
||||||
@RequestScoped
|
|
||||||
@Inject
|
|
||||||
public void setCurrentUser(@Context final HttpServletRequest request) {
|
|
||||||
|
|
||||||
String impersonate = request!=null ? request.getParameter("impersonate") : null ;
|
|
||||||
ClientInfo info = AuthorizationProvider.instance.get().getClient();
|
|
||||||
if(impersonate!=null && info.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
|
|
||||||
this.currentUser = impersonate;
|
|
||||||
} else
|
|
||||||
this.currentUser = info.getId();
|
|
||||||
|
|
||||||
log.info("called with login {} and impersonate {}",info.getId(), impersonate);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
@ -14,18 +12,17 @@ import javax.jcr.security.AccessControlManager;
|
||||||
import javax.jcr.security.Privilege;
|
import javax.jcr.security.Privilege;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.FormParam;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
|
@ -42,33 +39,24 @@ import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Path("items")
|
@Path("items")
|
||||||
@RequestHeaders({
|
public class ItemSharing {
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class ItemSharing extends Impersonable{
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ItemSharing.class);
|
private static final Logger log = LoggerFactory.getLogger(ItemSharing.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AccountingHandler accountingHandler;
|
AccountingHandler accountingHandler;
|
||||||
|
@ -77,14 +65,11 @@ public class ItemSharing extends Impersonable{
|
||||||
@PathParam("id")
|
@PathParam("id")
|
||||||
String id;
|
String id;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
ServletContext context;
|
ServletContext context;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AuthorizationChecker authChecker;
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UnshareHandler unshareHandler;
|
UnshareHandler unshareHandler;
|
||||||
|
@ -92,122 +77,17 @@ public class ItemSharing extends Impersonable{
|
||||||
@Inject Node2ItemConverter node2Item;
|
@Inject Node2ItemConverter node2Item;
|
||||||
@Inject Item2NodeConverter item2Node;
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
@POST
|
|
||||||
@Path("{id}/share")
|
|
||||||
public String shareWithMap(@FormParam("mapUserPermission") String mapUserPermissionString, @FormParam("defaultAccessType") String defaultAccessTypeString){
|
|
||||||
InnerMethodName.instance.set("shareFolder");
|
|
||||||
HashMap<String,String> mapUserPermission;
|
|
||||||
|
|
||||||
Session ses = null;
|
|
||||||
String toReturn = null;
|
|
||||||
try{
|
|
||||||
try {
|
|
||||||
mapUserPermission = (HashMap<String,String>)new ObjectMapper().readValue(mapUserPermissionString, HashMap.class);
|
|
||||||
}catch (Exception e) {
|
|
||||||
throw new InvalidCallParameters("invalid map passed");
|
|
||||||
}
|
|
||||||
AccessType defaultAccessType;
|
|
||||||
try {
|
|
||||||
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
|
|
||||||
}catch (IllegalArgumentException e) {
|
|
||||||
throw new InvalidCallParameters("invalid default accessType");
|
|
||||||
}
|
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
|
||||||
|
|
||||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
|
||||||
|
|
||||||
|
|
||||||
if (mapUserPermission==null || mapUserPermission.isEmpty())
|
|
||||||
throw new InvalidCallParameters("users is empty");
|
|
||||||
|
|
||||||
Node nodeToShare = ses.getNodeByIdentifier(id);
|
|
||||||
|
|
||||||
boolean alreadyShared = false;
|
|
||||||
|
|
||||||
Node sharedFolderNode;
|
|
||||||
if (!node2Item.checkNodeType(nodeToShare, SharedFolder.class))
|
|
||||||
sharedFolderNode= shareFolder(nodeToShare, ses);
|
|
||||||
else {
|
|
||||||
sharedFolderNode = nodeToShare;
|
|
||||||
alreadyShared = true;
|
|
||||||
}
|
|
||||||
ses.save();
|
|
||||||
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,currentUser);
|
|
||||||
}catch (LockException e) {
|
|
||||||
throw new ItemLockedException(e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
|
|
||||||
AccessControlManager acm = ses.getAccessControlManager();
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
|
||||||
|
|
||||||
if (!alreadyShared) {
|
|
||||||
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
||||||
addUserToSharing(sharedFolderNode, ses, currentUser, item, adminPrivileges, acls);
|
|
||||||
mapUserPermission.remove(currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (Entry<String, String> entry: mapUserPermission.entrySet() )
|
|
||||||
try {
|
|
||||||
AccessType accessType = defaultAccessType;
|
|
||||||
try {
|
|
||||||
if (entry.getValue()!=null)
|
|
||||||
accessType = AccessType.fromValue(entry.getValue());
|
|
||||||
}catch (IllegalArgumentException e) { log.warn("an illegal accessType passed to sharing ({})", entry.getValue());}
|
|
||||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
|
||||||
addUserToSharing(sharedFolderNode, ses, entry.getKey(), null, userPrivileges, acls);
|
|
||||||
}catch(Exception e){
|
|
||||||
log.warn("error adding user {} to sharing of folder {}", entry.getKey(), sharedFolderNode.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
|
||||||
|
|
||||||
String title = sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString();
|
|
||||||
accountingHandler.createShareFolder(title, mapUserPermission.keySet(), ses, sharedFolderNode, currentUser, false);
|
|
||||||
|
|
||||||
ses.save();
|
|
||||||
|
|
||||||
toReturn = sharedFolderNode.getIdentifier();
|
|
||||||
} finally {
|
|
||||||
if (!ses.hasPendingChanges())
|
|
||||||
ses.getWorkspace().getLockManager().unlock(sharedFolderNode.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr sharing", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error sharing folder", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{id}/share")
|
@Path("{id}/share")
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Deprecated
|
|
||||||
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
|
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
|
||||||
InnerMethodName.instance.set("shareFolder");
|
InnerMethodName.instance.set("shareFolder");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||||
|
|
||||||
|
@ -231,7 +111,7 @@ public class ItemSharing extends Impersonable{
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
|
@ -242,8 +122,8 @@ public class ItemSharing extends Impersonable{
|
||||||
|
|
||||||
if (!alreadyShared) {
|
if (!alreadyShared) {
|
||||||
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
||||||
addUserToSharing(sharedFolderNode, ses, currentUser, item, adminPrivileges, acls);
|
addUserToSharing(sharedFolderNode, ses, login, item, adminPrivileges, acls);
|
||||||
users.remove(currentUser);
|
users.remove(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
||||||
|
@ -257,7 +137,7 @@ public class ItemSharing extends Impersonable{
|
||||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
|
|
||||||
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, currentUser, false);
|
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, false);
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
|
@ -284,8 +164,9 @@ public class ItemSharing extends Impersonable{
|
||||||
|
|
||||||
|
|
||||||
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
|
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(currentUser))
|
|
||||||
|
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(login))
|
||||||
throw new InvalidItemException("item with id "+id+" cannot be shared");
|
throw new InvalidItemException("item with id "+id+" cannot be shared");
|
||||||
|
|
||||||
String sharedFolderName = node.getIdentifier();
|
String sharedFolderName = node.getIdentifier();
|
||||||
|
@ -305,7 +186,7 @@ public class ItemSharing extends Impersonable{
|
||||||
String userRootWSId;
|
String userRootWSId;
|
||||||
String userPath;
|
String userPath;
|
||||||
if (itemToShare==null) {
|
if (itemToShare==null) {
|
||||||
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
|
String userRootWS = Utils.getWorkspacePath(user).toPath();
|
||||||
userRootWSId = ses.getNode(userRootWS).getIdentifier();
|
userRootWSId = ses.getNode(userRootWS).getIdentifier();
|
||||||
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
|
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
|
||||||
}
|
}
|
||||||
|
@ -334,13 +215,13 @@ public class ItemSharing extends Impersonable{
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
public String unshare(@FormDataParam("users") Set<String> users){
|
public String unshare(@FormDataParam("users") Set<String> users){
|
||||||
InnerMethodName.instance.set("unshareFolder");
|
InnerMethodName.instance.set("unshareFolder");
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try {
|
try {
|
||||||
log.debug("unsharing folder with id {} with users {}", id, users);
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
Node sharedNode = ses.getNodeByIdentifier(id);
|
Node sharedNode = ses.getNodeByIdentifier(id);
|
||||||
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
|
toReturn = unshareHandler.unshare(ses, users, sharedNode, login);
|
||||||
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");
|
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");
|
||||||
}catch(RepositoryException re){
|
}catch(RepositoryException re){
|
||||||
log.error("jcr unsharing", re);
|
log.error("jcr unsharing", re);
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.jcr.ItemNotFoundException;
|
||||||
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.PathNotFoundException;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.lock.LockException;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
|
@ -17,105 +30,125 @@ import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||||
import org.apache.commons.compress.archivers.ArchiveException;
|
import org.apache.commons.compress.archivers.ArchiveException;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
||||||
|
import org.apache.tika.config.TikaConfig;
|
||||||
|
import org.apache.tika.detect.Detector;
|
||||||
|
import org.apache.tika.io.TikaInputStream;
|
||||||
|
import org.apache.tika.metadata.Metadata;
|
||||||
|
import org.gcube.common.authorization.library.AuthorizedTasks;
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||||
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
|
import org.gcube.data.access.storagehub.MultipleOutputStream;
|
||||||
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
|
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters;
|
import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
|
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("items")
|
@Path("items")
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
public class ItemsCreator {
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), })
|
|
||||||
public class ItemsCreator extends Impersonable {
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
|
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
|
||||||
|
|
||||||
@Context
|
private static ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||||
ServletContext context;
|
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Context ServletContext context;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ItemHandler itemHandler;
|
ContentHandlerFactory contenthandlerFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AccountingHandler accountingHandler;
|
||||||
|
|
||||||
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
|
@Inject StorageBackendHandler storageBackend;
|
||||||
|
|
||||||
|
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Path("/{id}/create/FOLDER")
|
@Path("/{id}/create/FOLDER")
|
||||||
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
|
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("hidden") boolean hidden) {
|
||||||
@FormParam("description") String description, @FormParam("hidden") boolean hidden) {
|
|
||||||
InnerMethodName.instance.set("createItem(FOLDER)");
|
InnerMethodName.instance.set("createItem(FOLDER)");
|
||||||
log.info("create folder item called");
|
log.info("create folder item called");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try {
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
|
|
||||||
.description(description).hidden(hidden).on(id).with(ses).author(currentUser);
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
toReturn = itemHandler.create(builder.build());
|
|
||||||
} catch (StorageHubException she) {
|
Node destination;
|
||||||
|
try {
|
||||||
|
destination = ses.getNodeByIdentifier(id);
|
||||||
|
}catch(RepositoryException inf) {
|
||||||
|
throw new IdNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
||||||
|
|
||||||
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = Utils.createFolderInternally(ses, destination, name, description, hidden, login, accountingHandler);
|
||||||
|
ses.save();
|
||||||
|
} finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
} catch (RepositoryException re) {
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error creating item", re);
|
log.error("jcr error creating item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||||
} catch (Throwable e) {
|
}finally{
|
||||||
log.error("unexpected error", e);
|
if (ses!=null)
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (ses != null)
|
|
||||||
ses.logout();
|
|
||||||
|
|
||||||
}
|
|
||||||
return Response.ok(toReturn).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
@Path("/{id}/create/EXTERNALFOLDER")
|
|
||||||
public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name,
|
|
||||||
@FormParam("description") String description, @FormParam("hidden") boolean hidden,
|
|
||||||
@FormParam("pluginName") String pluginName, @FormParam("parameters") String pluginParameters) {
|
|
||||||
InnerMethodName.instance.set("createItem(EXTERNALFOLDER)");
|
|
||||||
log.info("create folder item called");
|
|
||||||
Session ses = null;
|
|
||||||
String toReturn = null;
|
|
||||||
try {
|
|
||||||
// TODO
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
|
|
||||||
.description(description).onRepository(pluginName).withParameters(null).hidden(hidden).on(id)
|
|
||||||
.with(ses).author(currentUser);
|
|
||||||
toReturn = itemHandler.create(builder.build());
|
|
||||||
} catch (StorageHubException she) {
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
} catch (RepositoryException re) {
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("unexpected error", e);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (ses != null)
|
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -125,36 +158,57 @@ public class ItemsCreator extends Impersonable {
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Path("/{id}/create/URL")
|
@Path("/{id}/create/URL")
|
||||||
public Response createURL(@PathParam("id") String id, @FormParam("name") String name,
|
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) {
|
||||||
@FormParam("description") String description, @FormParam("value") URL value) {
|
|
||||||
InnerMethodName.instance.set("createItem(URL)");
|
InnerMethodName.instance.set("createItem(URL)");
|
||||||
log.info("create url called");
|
log.info("create url called");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try {
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name)
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
.description(description).url(value).on(id).with(ses).author(currentUser);
|
|
||||||
|
|
||||||
toReturn = itemHandler.create(builder.build());
|
Node destination;
|
||||||
} catch (StorageHubException she) {
|
try {
|
||||||
|
destination = ses.getNodeByIdentifier(id);
|
||||||
|
}catch(RepositoryException inf) {
|
||||||
|
throw new IdNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
||||||
|
|
||||||
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = Utils.createURLInternally(ses, destination, name, value, description, login, accountingHandler);
|
||||||
|
ses.save();
|
||||||
|
} finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
} catch (RepositoryException re) {
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error creating item", re);
|
log.error("jcr error creating item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||||
} catch (Throwable e) {
|
}finally{
|
||||||
log.error("unexpected error", e);
|
if (ses!=null)
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (ses != null)
|
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
|
||||||
}
|
}
|
||||||
return Response.ok(toReturn).build();
|
return Response.ok(toReturn).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Path("/{id}/create/GCUBEITEM")
|
@Path("/{id}/create/GCUBEITEM")
|
||||||
|
@ -164,58 +218,93 @@ public class ItemsCreator extends Impersonable {
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
|
|
||||||
try {
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder()
|
|
||||||
.item(item).on(id).with(ses).author(currentUser);
|
|
||||||
|
|
||||||
toReturn = itemHandler.create(builder.build());
|
Node destination;
|
||||||
} catch (StorageHubException she) {
|
try {
|
||||||
|
destination = ses.getNodeByIdentifier(id);
|
||||||
|
}catch(ItemNotFoundException inf) {
|
||||||
|
throw new IdNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
||||||
|
|
||||||
|
|
||||||
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
||||||
|
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = Utils.createGcubeItemInternally(ses, destination, item.getName(), item.getDescription(), login, item, accountingHandler);
|
||||||
|
ses.save();
|
||||||
|
} finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
} catch (RepositoryException re) {
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error creating item", re);
|
log.error("jcr error creating item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||||
} catch (Throwable e) {
|
}finally{
|
||||||
log.error("unexpected error", e);
|
if (ses!=null)
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (ses != null)
|
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Path("/{id}/create/FILE")
|
@Path("/{id}/create/FILE")
|
||||||
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
||||||
@FormDataParam("description") String description, @FormDataParam("file") InputStream stream,
|
@FormDataParam("description") String description,
|
||||||
@FormDataParam("file") FormDataContentDisposition fileDetail) {
|
@FormDataParam("file") InputStream stream,
|
||||||
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||||
InnerMethodName.instance.set("createItem(FILE)");
|
InnerMethodName.instance.set("createItem(FILE)");
|
||||||
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try {
|
try{
|
||||||
|
if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null or empty");
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name)
|
|
||||||
.description(description).stream(stream).fileDetails(fileDetail).on(id).with(ses)
|
|
||||||
.author(currentUser);
|
|
||||||
|
|
||||||
toReturn = itemHandler.create(builder.build());
|
Node destination = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
} catch (RepositoryException re) {
|
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
|
||||||
|
log.info("session: {}",ses.toString());
|
||||||
|
|
||||||
|
Node newNode = createFileItemInternally(ses, destination, stream, name, description, login, true);
|
||||||
|
ses.save();
|
||||||
|
|
||||||
|
versionHandler.checkinContentNode(newNode, ses);
|
||||||
|
log.info("file with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error creating file item", re);
|
log.error("jcr error creating file item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
|
||||||
} catch (StorageHubException she) {
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
} catch (Throwable e) {
|
}catch(Throwable e ){
|
||||||
log.error("unexpected error", e);
|
log.error("unexpected error", e);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
} finally {
|
}finally{
|
||||||
if (ses != null && ses.isLive()) {
|
if (ses!=null && ses.isLive()) {
|
||||||
log.info("session closed");
|
log.info("session closed");
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
@ -224,39 +313,249 @@ public class ItemsCreator extends Impersonable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, UserNotAuthorizedException, ItemLockedException, BackendGenericError{
|
||||||
|
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationNode.getPath()), name).toPath());
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
|
||||||
|
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
|
||||||
|
if (withLock) {
|
||||||
|
try {
|
||||||
|
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
|
||||||
|
}catch (LockException le) {
|
||||||
|
throw new ItemLockedException(le);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
versionHandler.checkoutContentNode(newNode, ses);
|
||||||
|
log.trace("replacing content of class {}",item.getContent().getClass());
|
||||||
|
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
|
||||||
|
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, false);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
|
||||||
|
}
|
||||||
|
}catch(PathNotFoundException pnf) {
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destinationNode.getIdentifier(), true);
|
||||||
|
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
|
||||||
|
if (withLock) {
|
||||||
|
try {
|
||||||
|
log.debug("trying to acquire lock");
|
||||||
|
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
|
||||||
|
}catch (LockException le) {
|
||||||
|
throw new ItemLockedException(le);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
newNode = item2Node.getNode(destinationNode, item);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
|
||||||
|
}
|
||||||
|
versionHandler.makeVersionableContent(newNode, ses);
|
||||||
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AbstractFileItem fillItemWithContent(InputStream stream, String name, String description, String path, String login) throws BackendGenericError{
|
||||||
|
ContentHandler handler = getContentHandler(stream , name, path, login);
|
||||||
|
AbstractFileItem item =handler.buildItem(name, description, login);
|
||||||
|
return item ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Path("/{id}/create/ARCHIVE")
|
@Path("/{id}/create/ARCHIVE")
|
||||||
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
|
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
|
||||||
@FormDataParam("file") InputStream stream, @FormDataParam("file") FormDataContentDisposition fileDetail) {
|
@FormDataParam("file") InputStream stream,
|
||||||
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||||
InnerMethodName.instance.set("createItem(ARCHIVE)");
|
InnerMethodName.instance.set("createItem(ARCHIVE)");
|
||||||
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try {
|
try{
|
||||||
|
if (parentFolderName==null) throw new InvalidCallParameters("new folder name is null");
|
||||||
|
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter
|
Node destination = ses.getNodeByIdentifier(id);
|
||||||
.builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail).on(id).with(ses)
|
|
||||||
.author(currentUser);
|
|
||||||
|
|
||||||
toReturn = itemHandler.create(builder.build());
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
} catch (RepositoryException | ArchiveException | IOException re) {
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier() , true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
|
}catch (LockException le) {
|
||||||
|
throw new ItemLockedException(le);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node parentDirectoryNode = Utils.createFolderInternally(ses, destination, parentFolderName, "", false, login, accountingHandler);
|
||||||
|
try {
|
||||||
|
if (ses.getWorkspace().getLockManager().isLocked(destination.getPath()))
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
} catch (Throwable t){
|
||||||
|
log.warn("error unlocking {}", destination.getPath(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Node> fileNodes = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
|
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
||||||
|
|
||||||
|
try (ArchiveInputStream input = new ArchiveStreamFactory()
|
||||||
|
.createArchiveInputStream(new BufferedInputStream(stream, 1024*64))){
|
||||||
|
ArchiveEntry entry;
|
||||||
|
while ((entry = input.getNextEntry()) != null) {
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
String entirePath = entry.getName();
|
||||||
|
String name = entirePath.replaceAll("(.*/)*(.*)/", "$2");
|
||||||
|
String parentPath = entirePath.replaceAll("(.*/)*(.*)/", "$1");
|
||||||
|
log.debug("creating directory with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
||||||
|
Node createdNode;
|
||||||
|
if (parentPath.isEmpty()) {
|
||||||
|
createdNode = Utils.createFolderInternally(ses, parentDirectoryNode, name, "", false, login, accountingHandler);
|
||||||
|
}else {
|
||||||
|
Node parentNode = directoryNodeMap.get(parentPath);
|
||||||
|
createdNode = Utils.createFolderInternally(ses, parentNode, name, "", false, login, accountingHandler);
|
||||||
|
}
|
||||||
|
directoryNodeMap.put(entirePath, createdNode);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
String entirePath = entry.getName();
|
||||||
|
String name = entirePath.replaceAll("(.*/)*(.*)", "$2");
|
||||||
|
String parentPath = entirePath.replaceAll("(.*/)*(.*)", "$1");
|
||||||
|
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
||||||
|
Node fileNode = null;
|
||||||
|
if (parentPath.isEmpty())
|
||||||
|
fileNode = createFileItemInternally(ses, parentDirectoryNode, input, name, "", login, false);
|
||||||
|
else {
|
||||||
|
Node parentNode = directoryNodeMap.get(parentPath);
|
||||||
|
fileNode = createFileItemInternally(ses, parentNode, input, name, "", login, false);
|
||||||
|
}
|
||||||
|
fileNodes.add(fileNode);
|
||||||
|
}catch(Exception e) {
|
||||||
|
log.warn("error getting file {}",entry.getName(),e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ses.save();
|
||||||
|
for (Node node : fileNodes)
|
||||||
|
versionHandler.checkinContentNode(node, ses);
|
||||||
|
toReturn = parentDirectoryNode.getIdentifier();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}catch(RepositoryException | ArchiveException | IOException re){
|
||||||
log.error("jcr error extracting archive", re);
|
log.error("jcr error extracting archive", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||||
} catch (StorageHubException she) {
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
} catch (Throwable e) {
|
} finally{
|
||||||
log.error("unexpected error", e);
|
if (ses!=null)
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (ses != null)
|
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ContentHandler getContentHandler(InputStream stream , String name, String path, String login) throws BackendGenericError {
|
||||||
|
|
||||||
|
|
||||||
|
final MultipleOutputStream mos;
|
||||||
|
try{
|
||||||
|
mos = new MultipleOutputStream(stream, 2);
|
||||||
|
}catch (IOException e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentHandler call() throws Exception {
|
||||||
|
ContentHandler handler =null;
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
log.debug("TIMING: reading the mimetype - start");
|
||||||
|
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
|
||||||
|
org.apache.tika.mime.MediaType mediaType = null;
|
||||||
|
TikaConfig config = TikaConfig.getDefaultConfig();
|
||||||
|
Detector detector = config.getDetector();
|
||||||
|
TikaInputStream stream = TikaInputStream.get(is1);
|
||||||
|
Metadata metadata = new Metadata();
|
||||||
|
metadata.add(Metadata.RESOURCE_NAME_KEY, name);
|
||||||
|
mediaType = detector.detect(stream, metadata);
|
||||||
|
String mimeType = mediaType.getBaseType().toString();
|
||||||
|
|
||||||
|
handler = contenthandlerFactory.create(mimeType);
|
||||||
|
|
||||||
|
is1.reset();
|
||||||
|
handler.initiliseSpecificContent(is1, name, mimeType);
|
||||||
|
|
||||||
|
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("error retrieving mimeType",e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetaInfo call() throws Exception {
|
||||||
|
try(InputStream is1 = mos.get()){
|
||||||
|
String uid = UUID.randomUUID().toString();
|
||||||
|
String remotePath= String.format("%s/%s-%s",path,uid,name);
|
||||||
|
MetaInfo info = storageBackend.upload(is1, remotePath);
|
||||||
|
return info;
|
||||||
|
}catch (Throwable e) {
|
||||||
|
log.error("error writing content",e );
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
|
||||||
|
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
log.debug("TIMING: writing the stream - start");
|
||||||
|
try {
|
||||||
|
mos.startWriting();
|
||||||
|
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
|
||||||
|
|
||||||
|
ContentHandler handler = detectorF.get();
|
||||||
|
MetaInfo info = uploaderF.get();
|
||||||
|
handler.getContent().setData(NodeConstants.CONTENT_NAME);
|
||||||
|
handler.getContent().setStorageId(info.getStorageId());
|
||||||
|
handler.getContent().setSize(info.getSize());
|
||||||
|
handler.getContent().setRemotePath(info.getRemotePath());
|
||||||
|
return handler;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ import javax.ws.rs.core.StreamingOutput;
|
||||||
|
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||||
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.encryption.StringEncrypter;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
import org.gcube.common.scope.impl.ScopeBean;
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
|
@ -57,16 +58,12 @@ import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.VreFolder;
|
import org.gcube.common.storagehub.model.items.VreFolder;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.service.ItemList;
|
import org.gcube.common.storagehub.model.service.ItemList;
|
||||||
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
||||||
import org.gcube.common.storagehub.model.service.VersionList;
|
import org.gcube.common.storagehub.model.service.VersionList;
|
||||||
|
@ -74,40 +71,30 @@ import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.Range;
|
import org.gcube.data.access.storagehub.Range;
|
||||||
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
|
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CompressHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
|
|
||||||
@Path("items")
|
@Path("items")
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
public class ItemsManager {
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class ItemsManager extends Impersonable{
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ItemsManager.class);
|
private static final Logger log = LoggerFactory.getLogger(ItemsManager.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AccountingHandler accountingHandler;
|
AccountingHandler accountingHandler;
|
||||||
|
@ -121,25 +108,17 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AuthorizationChecker authChecker;
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VersionHandler versionHandler;
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TrashHandler trashHandler;
|
TrashHandler trashHandler;
|
||||||
|
|
||||||
@Inject PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject Node2ItemConverter node2Item;
|
@Inject Node2ItemConverter node2Item;
|
||||||
@Inject Item2NodeConverter item2Node;
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
|
@Inject StorageBackendHandler storageBackend;
|
||||||
@Inject
|
|
||||||
FolderPluginHandler folderPluginHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
CompressHandler compressHandler;
|
|
||||||
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
|
@ -151,14 +130,14 @@ public class ItemsManager extends Impersonable{
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
Node node = ses.getNodeByIdentifier(id);
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = node2Item.getItem(node, excludes);
|
toReturn = node2Item.getItem(node, excludes);
|
||||||
}catch (ItemNotFoundException e) {
|
}catch (ItemNotFoundException e) {
|
||||||
log.error("id {} not found",id,e);
|
log.error("id {} not found",id,e);
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||||
}catch(RepositoryException re){
|
}catch(RepositoryException re){
|
||||||
log.error("jcr error getting item", re);
|
log.error("jcr error getting item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
|
||||||
}catch(StorageHubException she ){
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
|
@ -170,90 +149,16 @@ public class ItemsManager extends Impersonable{
|
||||||
return new ItemWrapper<Item>(toReturn);
|
return new ItemWrapper<Item>(toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}/path")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){
|
|
||||||
InnerMethodName.instance.set("getByPath");
|
|
||||||
Session ses = null;
|
|
||||||
Item toReturn = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
|
||||||
|
|
||||||
String relativePath = path.startsWith("/")? path.substring(1) : path;
|
|
||||||
if (path.endsWith("/"))
|
|
||||||
relativePath.substring(0,relativePath.lastIndexOf("/"));
|
|
||||||
|
|
||||||
if (relativePath.isEmpty()) throw new InvalidCallParameters("empty path");
|
|
||||||
|
|
||||||
Item item =null;
|
|
||||||
String nextId = id;
|
|
||||||
String[] paths = relativePath.split("/");
|
|
||||||
for (String actualPath: paths) {
|
|
||||||
item = getChildrenMatchingName(ses, nextId, actualPath, Excludes.ALL);
|
|
||||||
if (item ==null) throw new InvalidCallParameters("relative path "+actualPath+" not found under item with id "+nextId);
|
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, item.getId());
|
|
||||||
nextId = item.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludes.containsAll(Excludes.ALL))
|
|
||||||
return new ItemWrapper<Item>(item);
|
|
||||||
else
|
|
||||||
return new ItemWrapper<Item>(node2Item.getItem(ses.getNodeByIdentifier(item.getId()), excludes));
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item by path", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item by path", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ItemWrapper<Item>(toReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Item getChildrenMatchingName(Session ses, String id, String name, List<String> excludes) throws ItemNotFoundException , RepositoryException, StorageHubException {
|
|
||||||
|
|
||||||
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
Node child= it.nextNode();
|
|
||||||
String nodeName = child.getName();
|
|
||||||
if (!child.hasProperty(NodeProperty.TITLE.toString())) continue;
|
|
||||||
String title = child.getProperty(NodeProperty.TITLE.toString()).getString();
|
|
||||||
|
|
||||||
if (nodeName.equals(name) || title.equals(name)){
|
|
||||||
return node2Item.getItem(child, excludes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/items/{name}")
|
@Path("{id}/items/{name}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
|
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
|
||||||
InnerMethodName.instance.set("findChildrenByNamePattern");
|
InnerMethodName.instance.set("findChildrenByNamePattern");
|
||||||
return _findChildrenByNamePattern(excludes, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}/items")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
|
|
||||||
InnerMethodName.instance.set("findChildrenByNamePattern");
|
|
||||||
return _findChildrenByNamePattern(excludes, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ItemList _findChildrenByNamePattern(List<String> excludes, String name){
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
List<Item> toReturn = new ArrayList<>();
|
List<Item> toReturn = new ArrayList<>();
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
//NOT using the internal pattern matching of jcr because of title for shared folder
|
//NOT using the internal pattern matching of jcr because of title for shared folder
|
||||||
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
|
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
|
||||||
|
@ -284,11 +189,11 @@ public class ItemsManager extends Impersonable{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ItemList(toReturn);
|
return new ItemList(toReturn);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/children/count")
|
@Path("{id}/children/count")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -299,7 +204,7 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch (ItemNotFoundException e) {
|
}catch (ItemNotFoundException e) {
|
||||||
log.error("id {} not found",id,e);
|
log.error("id {} not found",id,e);
|
||||||
|
@ -326,7 +231,7 @@ public class ItemsManager extends Impersonable{
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch (ItemNotFoundException e) {
|
}catch (ItemNotFoundException e) {
|
||||||
log.error("id {} not found",id,e);
|
log.error("id {} not found",id,e);
|
||||||
|
@ -345,36 +250,6 @@ public class ItemsManager extends Impersonable{
|
||||||
return new ItemList(toReturn);
|
return new ItemList(toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}/search")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public ItemList searchItems(@QueryParam("showHidden") Boolean showHidden, @QueryParam("excludeTrashed") Boolean excludeTrashed, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType,@QueryParam("name") String name ){
|
|
||||||
InnerMethodName.instance.set("search");
|
|
||||||
Session ses = null;
|
|
||||||
List<? extends Item> toReturn = null;
|
|
||||||
try{
|
|
||||||
log.debug("search for node {}",name);
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
|
||||||
toReturn = Utils.searchByNameOnFolder(ses, currentUser, authChecker, ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden,excludeTrashed==true?false:excludeTrashed , nodeType!=null ? ClassHandler.instance().get(nodeType) : null, name);
|
|
||||||
log.debug("search retrieved {} elements",toReturn.size());
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
log.error("id {} not found",id,e);
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting children", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ItemList(toReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/children/paged")
|
@Path("{id}/children/paged")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -384,7 +259,7 @@ public class ItemsManager extends Impersonable{
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch (ItemNotFoundException e) {
|
}catch (ItemNotFoundException e) {
|
||||||
log.error("id {} not found",id,e);
|
log.error("id {} not found",id,e);
|
||||||
|
@ -405,14 +280,16 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("publiclink/{id}")
|
@Path("publiclink/{id}")
|
||||||
@AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"URIResolver"}, exception=MyAuthException.class)
|
||||||
public Response resolvePublicLink() {
|
public Response resolvePublicLink() {
|
||||||
InnerMethodName.instance.set("resolvePubliclink");
|
InnerMethodName.instance.set("resolvePubliclink");
|
||||||
|
|
||||||
log.warn("arrived id is {}",id);
|
log.warn("arrived id is {}",id);
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try{
|
try{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
String complexId = id;
|
String complexId = id;
|
||||||
|
|
||||||
if (id.startsWith(enchriptedPrefix)) {
|
if (id.startsWith(enchriptedPrefix)) {
|
||||||
|
@ -444,21 +321,16 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
log.warn("item id to retrieve is {}",itemId);
|
log.warn("item id to retrieve is {}",itemId);
|
||||||
|
|
||||||
Node selectedNode;
|
Node selectedNode = ses.getNodeByIdentifier(itemId);
|
||||||
try {
|
|
||||||
selectedNode= ses.getNodeByIdentifier(itemId);
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
throw new IdNotFoundException(itemId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
||||||
|
|
||||||
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
|
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
|
||||||
|
|
||||||
if (versionName!=null)
|
if (versionName!=null)
|
||||||
return downloadVersionInternal(ses, currentUser, itemId, versionName, false);
|
return downloadVersionInternal(ses, login, itemId, versionName, false);
|
||||||
else
|
else
|
||||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
|
||||||
|
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
|
@ -483,7 +355,7 @@ public class ItemsManager extends Impersonable{
|
||||||
URL toReturn = null;
|
URL toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
Node selectedNode = ses.getNodeByIdentifier(id);
|
Node selectedNode = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
@ -556,7 +428,7 @@ public class ItemsManager extends Impersonable{
|
||||||
String filePublicUrl = String.format("%s/%s%s",basepath, enchriptedPrefix, enchriptedString);
|
String filePublicUrl = String.format("%s/%s%s",basepath, enchriptedPrefix, enchriptedString);
|
||||||
return filePublicUrl;
|
return filePublicUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{id}/publish")
|
@Path("{id}/publish")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -566,7 +438,7 @@ public class ItemsManager extends Impersonable{
|
||||||
Item folder= null;
|
Item folder= null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
Node currentNode =ses.getNodeByIdentifier(id);
|
Node currentNode =ses.getNodeByIdentifier(id);
|
||||||
log.trace("current node is {}",currentNode.getPath());
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
|
|
||||||
|
@ -574,11 +446,11 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
if (!(folder instanceof FolderItem))
|
if (!(folder instanceof FolderItem))
|
||||||
throw new InvalidCallParameters("item is not a folder");
|
throw new InvalidCallParameters("item is not a folder");
|
||||||
|
|
||||||
currentNode.setProperty(NodeProperty.IS_PUBLIC.toString(), publish);
|
currentNode.setProperty(NodeProperty.IS_PUBLIC.toString(), publish);
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error getting rootSharedFolder", re);
|
log.error("jcr error getting rootSharedFolder", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
@ -602,7 +474,7 @@ public class ItemsManager extends Impersonable{
|
||||||
Item sharedParent= null;
|
Item sharedParent= null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
Node currentNode =ses.getNodeByIdentifier(id);
|
Node currentNode =ses.getNodeByIdentifier(id);
|
||||||
log.trace("current node is {}",currentNode.getPath());
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
|
|
||||||
|
@ -645,7 +517,7 @@ public class ItemsManager extends Impersonable{
|
||||||
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
|
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
Node node = ses.getNodeByIdentifier(id);
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
@ -653,7 +525,7 @@ public class ItemsManager extends Impersonable{
|
||||||
if (!(currentItem instanceof AbstractFileItem))
|
if (!(currentItem instanceof AbstractFileItem))
|
||||||
throw new InvalidItemException("this item is not versioned");
|
throw new InvalidItemException("this item is not versioned");
|
||||||
|
|
||||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
|
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node, ses);
|
||||||
|
|
||||||
for (Version version: jcrVersions) {
|
for (Version version: jcrVersions) {
|
||||||
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
|
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
|
||||||
|
@ -679,10 +551,11 @@ public class ItemsManager extends Impersonable{
|
||||||
InnerMethodName.instance.set("downloadSpecificVersion");
|
InnerMethodName.instance.set("downloadSpecificVersion");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try{
|
try{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
return downloadVersionInternal(ses, currentUser, id, versionName, true);
|
return downloadVersionInternal(ses, login, id, versionName, true);
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error downloading version", re);
|
log.error("jcr error downloading version", re);
|
||||||
|
@ -703,33 +576,32 @@ public class ItemsManager extends Impersonable{
|
||||||
if (!(currentItem instanceof AbstractFileItem))
|
if (!(currentItem instanceof AbstractFileItem))
|
||||||
throw new InvalidItemException("this item is not a file");
|
throw new InvalidItemException("this item is not a file");
|
||||||
|
|
||||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
|
List<Version> jcrVersions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(id), ses);
|
||||||
|
|
||||||
for (Version version: jcrVersions) {
|
for (Version version: jcrVersions) {
|
||||||
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
|
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
|
||||||
if (version.getName().equals(versionName)) {
|
if (version.getName().equals(versionName)) {
|
||||||
Content content = node2Item.getContentFromVersion(version);
|
long size = version.getFrozenNode().getProperty(NodeProperty.SIZE.toString()).getLong();
|
||||||
|
String mimeType = version.getFrozenNode().getProperty(NodeProperty.MIME_TYPE.toString()).getString();
|
||||||
FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
|
String storageId = version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
|
||||||
final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
|
|
||||||
|
final InputStream streamToWrite = storageBackend.download(storageId);
|
||||||
log.debug("retrieved storage id is {} with storageBackend {} (stream is null? {})",content.getStorageId(), folderManager.getStorageBackend().getClass().getSimpleName(), streamToWrite==null );
|
|
||||||
|
|
||||||
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
|
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
|
||||||
String ext = FilenameUtils.getExtension(currentItem.getTitle());
|
String ext = FilenameUtils.getExtension(currentItem.getTitle());
|
||||||
|
|
||||||
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
||||||
|
|
||||||
if (withAccounting)
|
if (withAccounting)
|
||||||
accountingHandler.createReadObj(fileName, ses, node, login, true);
|
accountingHandler.createReadObj(fileName, ses, node, true);
|
||||||
|
|
||||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
.ok(so)
|
.ok(so)
|
||||||
.header("content-disposition","attachment; filename = "+fileName)
|
.header("content-disposition","attachment; filename = "+fileName)
|
||||||
.header("Content-Length", content.getSize())
|
.header("Content-Length", size)
|
||||||
.header("Content-Type", content.getMimeType())
|
.header("Content-Type", mimeType)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -741,29 +613,26 @@ public class ItemsManager extends Impersonable{
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
|
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
|
||||||
InnerMethodName.instance.set("getAnchestors");
|
InnerMethodName.instance.set("getAnchestors");
|
||||||
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
|
org.gcube.common.storagehub.model.Path absolutePath = Utils.getWorkspacePath();
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
List<Item> toReturn = new LinkedList<>();
|
List<Item> toReturn = new LinkedList<>();
|
||||||
try{
|
try{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
Node currentNode = ses.getNodeByIdentifier(id);
|
Node currentNode = ses.getNodeByIdentifier(id);
|
||||||
Item currentItem = node2Item.getItem(currentNode, excludes);
|
Item currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
log.trace("current node is {}",currentNode.getPath());
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
while (!(currentNode.getPath().matches("/Home/[^/]{1,}/Workspace"))) {
|
while (!(currentNode.getPath()+"/").equals(absolutePath.toPath())) {
|
||||||
if (currentItem instanceof SharedFolder){
|
if (currentItem instanceof SharedFolder){
|
||||||
NodeIterator sharedSetIterator = currentNode.getSharedSet();
|
NodeIterator sharedSetIterator = currentNode.getSharedSet();
|
||||||
boolean found = false;
|
|
||||||
while (sharedSetIterator.hasNext()) {
|
while (sharedSetIterator.hasNext()) {
|
||||||
Node sharedNode = sharedSetIterator.nextNode();
|
Node sharedNode = sharedSetIterator.nextNode();
|
||||||
if (sharedNode.getPath().startsWith(absolutePath.toPath())) {
|
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath(login).toPath())) {
|
||||||
currentNode = sharedNode.getParent();
|
currentNode = sharedNode.getParent();
|
||||||
found=true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) break;
|
|
||||||
currentItem = node2Item.getItem(currentNode, excludes);
|
currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
}else {
|
}else {
|
||||||
currentNode = currentNode.getParent();
|
currentNode = currentNode.getParent();
|
||||||
|
@ -800,16 +669,17 @@ public class ItemsManager extends Impersonable{
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
Response response = null;
|
Response response = null;
|
||||||
try{
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
final Node node = ses.getNodeByIdentifier(id);
|
final Node node = ses.getNodeByIdentifier(id);
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
final Item item = node2Item.getItem(node, null);
|
final Item item = node2Item.getItem(node, null);
|
||||||
if (item instanceof AbstractFileItem){
|
if (item instanceof AbstractFileItem){
|
||||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
|
||||||
} else if (item instanceof FolderItem){
|
} else if (item instanceof FolderItem){
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Deque<Item> allNodes = compressHandler.getAllNodesForZip((FolderItem)item, ses, currentUser, accountingHandler, excludes);
|
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler, excludes);
|
||||||
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
|
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
|
||||||
StreamingOutput so = new StreamingOutput() {
|
StreamingOutput so = new StreamingOutput() {
|
||||||
|
|
||||||
|
@ -820,7 +690,7 @@ public class ItemsManager extends Impersonable{
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||||
log.debug("writing StreamOutput");
|
log.debug("writing StreamOutput");
|
||||||
compressHandler.zipNode(zos, allNodes, currentUser, originalPath);
|
Utils.zipNode(zos, allNodes, login, originalPath, storageBackend);
|
||||||
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
|
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("error writing stream",e);
|
log.error("error writing stream",e);
|
||||||
|
@ -836,7 +706,7 @@ public class ItemsManager extends Impersonable{
|
||||||
.header("Content-Length", -1l)
|
.header("Content-Length", -1l)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
accountingHandler.createReadObj(item.getTitle(), ses, (Node) item.getRelatedNode(), currentUser, false);
|
accountingHandler.createReadObj(item.getTitle(), ses, ses.getNodeByIdentifier(item.getId()), false);
|
||||||
}finally {
|
}finally {
|
||||||
if (ses!=null) ses.save();
|
if (ses!=null) ses.save();
|
||||||
}
|
}
|
||||||
|
@ -855,14 +725,12 @@ public class ItemsManager extends Impersonable{
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, BackendGenericError {
|
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException {
|
||||||
|
|
||||||
FolderManager folderManager = folderPluginHandler.getFolderManager(fileItem);
|
final InputStream streamToWrite = storageBackend.download(fileItem.getContent().getStorageId());
|
||||||
|
|
||||||
final InputStream streamToWrite = folderManager.getStorageBackend().download(fileItem.getContent());
|
|
||||||
|
|
||||||
if (withAccounting)
|
if (withAccounting)
|
||||||
accountingHandler.createReadObj(fileItem.getTitle(), ses, (Node) fileItem.getRelatedNode(), login, true);
|
accountingHandler.createReadObj(fileItem.getTitle(), ses, ses.getNodeByIdentifier(fileItem.getId()), true);
|
||||||
|
|
||||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||||
|
|
||||||
|
@ -883,12 +751,13 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try{
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||||
|
@ -909,11 +778,12 @@ public class ItemsManager extends Impersonable{
|
||||||
if (!(destinationItem instanceof FolderItem))
|
if (!(destinationItem instanceof FolderItem))
|
||||||
throw new InvalidItemException("destination item is not a folder");
|
throw new InvalidItemException("destination item is not a folder");
|
||||||
|
|
||||||
boolean movingSharedItemOutside = item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier()));
|
if (item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier())))
|
||||||
|
throw new InvalidCallParameters("shared Item cannot be moved in a different shared folder or in a private folder");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
|
@ -921,18 +791,13 @@ public class ItemsManager extends Impersonable{
|
||||||
String uniqueName =(Utils.checkExistanceAndGetUniqueName(ses, destination, nodeToMove.getName()));
|
String uniqueName =(Utils.checkExistanceAndGetUniqueName(ses, destination, nodeToMove.getName()));
|
||||||
String newPath = String.format("%s/%s",destination.getPath(), uniqueName);
|
String newPath = String.format("%s/%s",destination.getPath(), uniqueName);
|
||||||
|
|
||||||
ses.move(nodeToMove.getPath(), newPath);
|
ses.getWorkspace().move(nodeToMove.getPath(), newPath);
|
||||||
Utils.setPropertyOnChangeNode(ses.getNode(newPath), currentUser, ItemAction.MOVED);
|
Utils.setPropertyOnChangeNode(ses.getNode(newPath), login, ItemAction.MOVED);
|
||||||
|
|
||||||
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||||
|
|
||||||
if (movingSharedItemOutside)
|
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting , ses, destination, false);
|
||||||
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
|
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, originalParent, false);
|
||||||
|
|
||||||
//folderHandler.onMove(source, destination);
|
|
||||||
|
|
||||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
|
|
||||||
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false);
|
|
||||||
ses.save();
|
ses.save();
|
||||||
}finally {
|
}finally {
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||||
|
@ -961,11 +826,13 @@ public class ItemsManager extends Impersonable{
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String newFileIdentifier = null;
|
String newFileIdentifier = null;
|
||||||
try{
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
//ses = RepositoryInitializer.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
|
||||||
|
//TODO check if it is possible to change all the ACL on a workspace
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
final Node nodeToCopy = ses.getNodeByIdentifier(id);
|
final Node nodeToCopy = ses.getNodeByIdentifier(id);
|
||||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||||
|
@ -977,8 +844,8 @@ public class ItemsManager extends Impersonable{
|
||||||
throw new InvalidItemException("folder cannot be copied");
|
throw new InvalidItemException("folder cannot be copied");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
|
@ -989,23 +856,20 @@ public class ItemsManager extends Impersonable{
|
||||||
Node newNode = ses.getNode(newPath);
|
Node newNode = ses.getNode(newPath);
|
||||||
newFileIdentifier = newNode.getIdentifier();
|
newFileIdentifier = newNode.getIdentifier();
|
||||||
|
|
||||||
//TODO: folderHandler.onCopy(source, destination);
|
|
||||||
|
|
||||||
if (item instanceof AbstractFileItem) {
|
if (item instanceof AbstractFileItem) {
|
||||||
FolderManager manager = folderPluginHandler.getFolderManager(item);
|
|
||||||
((AbstractFileItem) item).getContent().setRemotePath(newPath);
|
((AbstractFileItem) item).getContent().setRemotePath(newPath);
|
||||||
String newStorageID = manager.getStorageBackend().onCopy((AbstractFileItem) item);
|
String newStorageID = storageBackend.copy((AbstractFileItem) item);
|
||||||
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
|
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
|
||||||
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
|
Utils.setPropertyOnChangeNode(newNode, login, ItemAction.CLONED);
|
||||||
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
|
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), login);
|
||||||
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
|
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
|
||||||
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
||||||
|
|
||||||
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
|
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, destination, false);
|
||||||
|
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
@ -1036,11 +900,12 @@ public class ItemsManager extends Impersonable{
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
@ -1054,8 +919,8 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
|
@ -1065,9 +930,9 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
|
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
|
||||||
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
||||||
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
|
Utils.setPropertyOnChangeNode(nodeToMove, login, ItemAction.RENAMED);
|
||||||
ses.move(nodeToMove.getPath(), newPath);
|
ses.move(nodeToMove.getPath(), newPath);
|
||||||
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), currentUser, ses, false);
|
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), ses, false);
|
||||||
ses.save();
|
ses.save();
|
||||||
}finally {
|
}finally {
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||||
|
@ -1089,96 +954,6 @@ public class ItemsManager extends Impersonable{
|
||||||
return Response.ok(id).build();
|
return Response.ok(id).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: transform this and setMetadata in a generic method for all properties
|
|
||||||
@PUT
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("/{id}/hidden")
|
|
||||||
public Response setItemAsHidden(Boolean hidden){
|
|
||||||
InnerMethodName.instance.set("setHidden");
|
|
||||||
|
|
||||||
Session ses = null;
|
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
|
||||||
|
|
||||||
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
|
|
||||||
}catch (LockException e) {
|
|
||||||
throw new ItemLockedException(e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
item2Node.updateHidden(nodeToUpdate, hidden, currentUser);
|
|
||||||
ses.save();
|
|
||||||
}finally {
|
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
|
||||||
}
|
|
||||||
//TODO: UPDATE accounting
|
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
|
||||||
log.error("jcr error moving item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null) {
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return Response.ok(id).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: transform this and setMetadata in a generic method for all properties
|
|
||||||
@PUT
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
@Path("/{id}/description")
|
|
||||||
public Response setDescription(String description){
|
|
||||||
InnerMethodName.instance.set("setDescription");
|
|
||||||
|
|
||||||
Session ses = null;
|
|
||||||
|
|
||||||
try{
|
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
|
||||||
|
|
||||||
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
|
|
||||||
}catch (LockException e) {
|
|
||||||
throw new ItemLockedException(e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
item2Node.updateDescription(nodeToUpdate, description, currentUser);
|
|
||||||
ses.save();
|
|
||||||
}finally {
|
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
|
||||||
}
|
|
||||||
//TODO: UPDATE accounting
|
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
|
||||||
log.error("jcr error moving item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null) {
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return Response.ok(id).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
@Path("/{id}/metadata")
|
@Path("/{id}/metadata")
|
||||||
|
@ -1188,20 +963,21 @@ public class ItemsManager extends Impersonable{
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
|
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,login);
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
throw new ItemLockedException(e);
|
throw new ItemLockedException(e);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), currentUser);
|
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), login);
|
||||||
ses.save();
|
ses.save();
|
||||||
}finally {
|
}finally {
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
||||||
|
@ -1237,28 +1013,25 @@ public class ItemsManager extends Impersonable{
|
||||||
|
|
||||||
//TODO check if it is possible to change all the ACL on a workspace
|
//TODO check if it is possible to change all the ACL on a workspace
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
|
||||||
|
|
||||||
final Node nodeToDelete = ses.getNodeByIdentifier(id);
|
final Node nodeToDelete = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item itemToDelete = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
|
Item itemToDelete = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
|
||||||
|
|
||||||
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
|
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
|
||||||
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
|
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
|
||||||
|
|
||||||
if (itemToDelete.isExternalManaged() && !force)
|
|
||||||
throw new InvalidItemException("External managed Items cannot be moved to Trash");
|
|
||||||
|
|
||||||
log.debug("item is trashed? {}", itemToDelete.isTrashed());
|
log.debug("item is trashed? {}", itemToDelete.isTrashed());
|
||||||
|
|
||||||
if (!itemToDelete.isTrashed() && !force) {
|
if (!itemToDelete.isTrashed() && !force)
|
||||||
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete, currentUser);
|
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete);
|
||||||
}else
|
else
|
||||||
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
|
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
|
||||||
|
|
||||||
}catch (LockException e) {
|
}catch (LockException e) {
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error moving item", re);
|
log.error("jcr error moving item", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
|
|
@ -1,434 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.jcr.ItemNotFoundException;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.NodeIterator;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.FormParam;
|
|
||||||
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.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
||||||
import org.apache.jackrabbit.api.security.user.User;
|
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Owner;
|
|
||||||
import org.gcube.common.storagehub.model.messages.Message;
|
|
||||||
import org.gcube.common.storagehub.model.service.ItemList;
|
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
|
||||||
import org.gcube.common.storagehub.model.types.MessageList;
|
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter.Values;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.gcube.data.access.storagehub.types.MessageSharable;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("messages")
|
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class MessageManager extends Impersonable{
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(MessageManager.class);
|
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AccountingHandler accountingHandler;
|
|
||||||
|
|
||||||
@RequestScoped
|
|
||||||
@PathParam("id")
|
|
||||||
String id;
|
|
||||||
|
|
||||||
@Context
|
|
||||||
ServletContext context;
|
|
||||||
|
|
||||||
@Inject PathUtil pathUtil;
|
|
||||||
|
|
||||||
@Inject Node2ItemConverter node2Item;
|
|
||||||
@Inject Item2NodeConverter item2Node;
|
|
||||||
|
|
||||||
@Inject TrashHandler trashHandler;
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public Message getById(){
|
|
||||||
InnerMethodName.instance.set("getMessageById");
|
|
||||||
Session ses = null;
|
|
||||||
Message toReturn = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
Node messageNode = ses.getNodeByIdentifier(id);
|
|
||||||
toReturn = node2Item.getMessageItem(messageNode);
|
|
||||||
checkRights(currentUser, toReturn);
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
log.error("id {} not found",id,e);
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@DELETE
|
|
||||||
@Path("{id}")
|
|
||||||
public void deleteById(){
|
|
||||||
InnerMethodName.instance.set("deleteMessageById");
|
|
||||||
Session ses = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
Node messageNode = ses.getNodeByIdentifier(id);
|
|
||||||
Message message = node2Item.getMessageItem(messageNode);
|
|
||||||
Node personalNode = checkRights(currentUser, message);
|
|
||||||
|
|
||||||
if (countSharedSet(messageNode)>1)
|
|
||||||
personalNode.removeShare();
|
|
||||||
else {
|
|
||||||
if (message.isWithAttachments()) {
|
|
||||||
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
|
|
||||||
List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
|
|
||||||
trashHandler.removeOnlyNodesContent(ses, attachments);
|
|
||||||
}
|
|
||||||
messageNode.removeSharedSet();
|
|
||||||
}
|
|
||||||
ses.save();
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
log.error("id {} not found",id,e);
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{id}/attachments")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public ItemList getAttachments(){
|
|
||||||
InnerMethodName.instance.set("getAttachmentsByMessageId");
|
|
||||||
Session ses = null;
|
|
||||||
List<Item> attachments = new ArrayList<>();
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
Node messageNode = ses.getNodeByIdentifier(id);
|
|
||||||
Message messageItem = node2Item.getMessageItem(messageNode);
|
|
||||||
checkRights(currentUser, messageItem);
|
|
||||||
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
|
|
||||||
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
log.error("id {} not found",id,e);
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ItemList(attachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("inbox")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){
|
|
||||||
InnerMethodName.instance.set("getReceivedMessages");
|
|
||||||
Session ses = null;
|
|
||||||
List<Message> toReturn = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath());
|
|
||||||
|
|
||||||
//return sorted for createdTime
|
|
||||||
toReturn = getMessages(node, reduceBody);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MessageList(toReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("sent")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){
|
|
||||||
InnerMethodName.instance.set("getSentMessages");
|
|
||||||
Session ses = null;
|
|
||||||
List<Message> toReturn = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
|
|
||||||
|
|
||||||
toReturn = getMessages(node, reduceBody);
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new MessageList(toReturn);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PUT
|
|
||||||
@Path("{id}/{prop}")
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public void setProperty(@PathParam("prop") String property,Object value){
|
|
||||||
InnerMethodName.instance.set("setPropertyOnMessage("+property+")");
|
|
||||||
Session ses = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
Node messageNode = ses.getNodeByIdentifier(id);
|
|
||||||
Message messageItem = node2Item.getMessageItem(messageNode);
|
|
||||||
checkRights(currentUser, messageItem);
|
|
||||||
Values val = Item2NodeConverter.getObjectValue(value.getClass(), value);
|
|
||||||
messageNode.setProperty(property, val.getValue());
|
|
||||||
ses.save();
|
|
||||||
}catch (ItemNotFoundException e) {
|
|
||||||
log.error("id {} not found",id,e);
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}catch( Exception re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("send")
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
public String sendMessage(@FormParam("to[]") List<String> addresses,
|
|
||||||
@FormParam("subject") String subject, @FormParam("body") String body,
|
|
||||||
@FormParam("attachments[]") List<String> attachments){
|
|
||||||
InnerMethodName.instance.set("sendMessage");
|
|
||||||
JackrabbitSession ses = null;
|
|
||||||
String messageId = null;
|
|
||||||
try{
|
|
||||||
if (addresses.size()==0 || body==null || subject==null)
|
|
||||||
throw new InvalidCallParameters();
|
|
||||||
|
|
||||||
log.debug("attachments send are {}",attachments);
|
|
||||||
|
|
||||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
Message message = new MessageSharable();
|
|
||||||
message.setAddresses(addresses.toArray(new String[0]));
|
|
||||||
message.setSubject(subject);
|
|
||||||
message.setBody(body);
|
|
||||||
message.setName(UUID.randomUUID().toString());
|
|
||||||
User user = ses.getUserManager().getAuthorizable(currentUser, User.class);
|
|
||||||
Owner owner = new Owner();
|
|
||||||
owner.setUserId(user.getID());
|
|
||||||
owner.setUserName(user.getPrincipal().getName());
|
|
||||||
message.setSender(owner);
|
|
||||||
Node outbox = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
|
|
||||||
Node messageNode = item2Node.getNode(outbox, message);
|
|
||||||
ses.save();
|
|
||||||
if (attachments!=null && !attachments.isEmpty()) {
|
|
||||||
saveAttachments(ses, messageNode, attachments);
|
|
||||||
ses.save();
|
|
||||||
}
|
|
||||||
for (String to: addresses)
|
|
||||||
try {
|
|
||||||
String userMessagePath = Paths.append(pathUtil.getInboxPath(to), messageNode.getName()).toPath();
|
|
||||||
ses.getWorkspace().clone(ses.getWorkspace().getName(), messageNode.getPath(), userMessagePath, false);
|
|
||||||
}catch (Exception e) {
|
|
||||||
log.warn("message not send to {}",to,e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ses.save();
|
|
||||||
messageId = messageNode.getIdentifier();
|
|
||||||
}catch(RepositoryException re){
|
|
||||||
log.error("jcr error getting item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
|
|
||||||
}catch(StorageHubException she ){
|
|
||||||
log.error(she.getErrorMessage(), she);
|
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
||||||
}finally{
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return messageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, BackendGenericError{
|
|
||||||
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
|
|
||||||
|
|
||||||
for (String itemId: attachments) {
|
|
||||||
Node node = ses.getNodeByIdentifier(itemId);
|
|
||||||
Item item = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT);
|
|
||||||
Node newNode = copyNode(ses, attachmentNode, item);
|
|
||||||
//removes accounting if exists
|
|
||||||
if (newNode.hasNode(NodeProperty.ACCOUNTING.toString()))
|
|
||||||
newNode.getNode(NodeProperty.ACCOUNTING.toString()).remove();
|
|
||||||
}
|
|
||||||
return messageNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//returns Messages sorted by createdTime
|
|
||||||
private List<Message> getMessages(Node node, Integer reduceBody) throws RepositoryException{
|
|
||||||
List<Message> messages = new ArrayList<Message>();
|
|
||||||
NodeIterator nodeIt = node.getNodes();
|
|
||||||
while(nodeIt.hasNext()) {
|
|
||||||
Node child = nodeIt.nextNode();
|
|
||||||
log.info("message type "+child.getPrimaryNodeType().getName());
|
|
||||||
Message message = node2Item.getMessageItem(child);
|
|
||||||
if (message == null) {
|
|
||||||
log.info("message discarded");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reduceBody != null && reduceBody>0 && message.getBody().length()>reduceBody )
|
|
||||||
message.setBody(message.getBody().substring(0, reduceBody));
|
|
||||||
insertOrdered(messages, message);
|
|
||||||
}
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void insertOrdered(List<Message> messages, Message toInsert) {
|
|
||||||
if (messages.isEmpty())
|
|
||||||
messages.add(toInsert);
|
|
||||||
else {
|
|
||||||
int i;
|
|
||||||
for ( i=0 ; i<messages.size(); i++)
|
|
||||||
if (messages.get(i).getCreationTime().getTimeInMillis()<=toInsert.getCreationTime().getTimeInMillis())
|
|
||||||
break;
|
|
||||||
messages.add(i, toInsert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Node checkRights(String user, Message messageItem) throws RepositoryException, StorageHubException{
|
|
||||||
Node personalNode = null;
|
|
||||||
Node messageNode = (Node) messageItem.getRelatedNode();
|
|
||||||
if (messageNode.getPath().startsWith(pathUtil.getInboxPath(user).toPath()))
|
|
||||||
return messageNode;
|
|
||||||
|
|
||||||
NodeIterator nodeIt = messageNode.getSharedSet();
|
|
||||||
while (nodeIt.hasNext()) {
|
|
||||||
Node node = nodeIt.nextNode();
|
|
||||||
if (node.getPath().startsWith(pathUtil.getInboxPath(user).toPath()))
|
|
||||||
personalNode = node;
|
|
||||||
}
|
|
||||||
if (personalNode == null &&
|
|
||||||
!messageItem.getSender().getUserName().equals(user) && !Arrays.asList(messageItem.getAddresses()).contains(user))
|
|
||||||
throw new UserNotAuthorizedException("user "+currentUser+"cannot read message with id "+id);
|
|
||||||
return personalNode== null ? messageNode : personalNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: move in a common place
|
|
||||||
@Inject FolderPluginHandler folderPluginHandler;
|
|
||||||
|
|
||||||
private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, BackendGenericError{
|
|
||||||
//it needs to be locked ??
|
|
||||||
Node nodeToCopy = ((Node)itemToCopy.getRelatedNode());
|
|
||||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() );
|
|
||||||
String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
|
|
||||||
session.getWorkspace().copy(nodeToCopy.getPath(), newPath);
|
|
||||||
Node newNode = session.getNode(newPath);
|
|
||||||
|
|
||||||
if (itemToCopy instanceof AbstractFileItem) {
|
|
||||||
AbstractFileItem newNodeItem = node2Item.getItem(newNode, Excludes.EXCLUDE_ACCOUNTING);
|
|
||||||
newNodeItem.getContent().setRemotePath(newPath);
|
|
||||||
String newStorageID = folderPluginHandler.getDefault().getStorageBackend().onCopy(newNodeItem);
|
|
||||||
newNodeItem.getContent().setStorageId(newStorageID);
|
|
||||||
item2Node.replaceContent(newNode, newNodeItem, ItemAction.CLONED);
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
|
|
||||||
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
|
|
||||||
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
|
|
||||||
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
|
||||||
return newNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int countSharedSet(Node node) throws RepositoryException{
|
|
||||||
int count =0;
|
|
||||||
NodeIterator it = node.getSharedSet();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
count ++;
|
|
||||||
it.next();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,4 @@ import javax.jcr.Repository;
|
||||||
public interface RepositoryInitializer {
|
public interface RepositoryInitializer {
|
||||||
|
|
||||||
Repository getRepository();
|
Repository getRepository();
|
||||||
|
|
||||||
void shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,13 @@ package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.PathNotFoundException;
|
import javax.jcr.NodeIterator;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.query.QueryResult;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
|
@ -24,86 +20,49 @@ import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||||
import org.apache.jackrabbit.api.security.user.Authorizable;
|
import org.apache.jackrabbit.api.security.user.Authorizable;
|
||||||
import org.apache.jackrabbit.api.security.user.Group;
|
|
||||||
import org.apache.jackrabbit.api.security.user.Query;
|
import org.apache.jackrabbit.api.security.user.Query;
|
||||||
import org.apache.jackrabbit.api.security.user.QueryBuilder;
|
import org.apache.jackrabbit.api.security.user.QueryBuilder;
|
||||||
import org.apache.jackrabbit.api.security.user.User;
|
import org.apache.jackrabbit.api.security.user.User;
|
||||||
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
|
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
|
||||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.GroupHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("users")
|
@Path("users")
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class UserManager {
|
public class UserManager {
|
||||||
|
|
||||||
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
|
|
||||||
|
|
||||||
@Context ServletContext context;
|
@Context ServletContext context;
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
|
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UnshareHandler unshareHandler;
|
UnshareHandler unshareHandler;
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
TrashHandler trashHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
GroupHandler groupHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
@Path("")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public List<String> getUsers(){
|
public List<String> getUsers(){
|
||||||
|
|
||||||
InnerMethodName.instance.set("getUsers");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
List<String> users = null;
|
List<String> users= new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
|
||||||
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
|
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,20 +70,12 @@ public class UserManager {
|
||||||
builder.setSelector(User.class);
|
builder.setSelector(User.class);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Set<String> usersSet= new HashSet<>();
|
|
||||||
String adminUser = context.getInitParameter(Constants.ADMIN_PARAM_NAME);
|
|
||||||
|
|
||||||
while (result.hasNext()) {
|
while (result.hasNext()) {
|
||||||
Authorizable user = result.next();
|
Authorizable user = result.next();
|
||||||
log.debug("user {} found",user.getPrincipal().getName());
|
log.debug("user {} found",user.getPrincipal().getName());
|
||||||
if (user.getPrincipal().getName().equals(adminUser)) continue;
|
users.add(user.getPrincipal().getName());
|
||||||
usersSet.add(user.getPrincipal().getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
users = new ArrayList<>(usersSet);
|
|
||||||
Collections.sort(users);
|
|
||||||
|
|
||||||
}catch(Exception e) {
|
}catch(Exception e) {
|
||||||
log.error("jcr error getting users", e);
|
log.error("jcr error getting users", e);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
|
@ -135,87 +86,36 @@ public class UserManager {
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{user}")
|
|
||||||
public String getUser(@PathParam("user") String user){
|
|
||||||
|
|
||||||
InnerMethodName.instance.set("getUser");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
|
||||||
try {
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
|
||||||
Authorizable authorizable = usrManager.getAuthorizable(user);
|
|
||||||
|
|
||||||
if (authorizable != null && !authorizable.isGroup())
|
|
||||||
return authorizable.getPrincipal().getName();
|
|
||||||
|
|
||||||
log.debug("user {} not found", user);
|
|
||||||
|
|
||||||
}catch(Exception e) {
|
|
||||||
log.error("jcr error getting user", e);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
||||||
} finally {
|
|
||||||
if (session!=null)
|
|
||||||
session.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(user));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("")
|
@Path("")
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
|
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
|
||||||
|
|
||||||
InnerMethodName.instance.set("createUser");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
String userId = null;
|
String userId = null;
|
||||||
try {
|
try {
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
|
||||||
User createdUser = usrManager.createUser(user, password);
|
User createdUser = usrManager.createUser(user, password);
|
||||||
|
|
||||||
userId = createdUser.getID();
|
userId = createdUser.getID();
|
||||||
|
|
||||||
Node homeNode = session.getNode("/Home");
|
Node homeNode = session.getNode("/Home");
|
||||||
Node userHome = homeNode.addNode(user, "nthl:home");
|
Node userHome = homeNode.addNode(user, "nthl:home");
|
||||||
|
|
||||||
userHome.setProperty(Constants.HOME_VERSION_PROP, 1l);
|
|
||||||
|
|
||||||
//creating workspace folder
|
//creating workspace folder
|
||||||
FolderCreationParameters wsFolderParameters = FolderCreationParameters.builder().name(Constants.WORKSPACE_ROOT_FOLDER_NAME).description("workspace of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
Node workspaceFolder = Utils.createFolderInternally(session, userHome, Constants.WORKSPACE_ROOT_FOLDER_NAME, "workspace of "+user, false, user, null);
|
||||||
Utils.createFolderInternally(wsFolderParameters, null);
|
|
||||||
//creating thrash folder
|
//creating thrash folder
|
||||||
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
Utils.createFolderInternally(session, workspaceFolder, Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
|
||||||
Utils.createFolderInternally(trashFolderParameters, null);
|
|
||||||
//creating Vre container folder
|
//creating Vre container folder
|
||||||
FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder().name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
Utils.createFolderInternally(session, workspaceFolder, Constants.VRE_FOLDER_PARENT_NAME, "special folder container of "+user, false, user, null);
|
||||||
Utils.createFolderInternally(vreFolderParameters, null);
|
|
||||||
|
|
||||||
//creating inbox folder
|
|
||||||
FolderCreationParameters inboxFolderParameters = FolderCreationParameters.builder().name(Constants.INBOX_FOLDER_NAME).description("inbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
|
||||||
Utils.createFolderInternally(inboxFolderParameters, null);
|
|
||||||
|
|
||||||
//creating outbox folder
|
|
||||||
FolderCreationParameters outboxFolderParameters = FolderCreationParameters.builder().name(Constants.OUTBOX_FOLDER_NAME).description("outbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
|
||||||
Utils.createFolderInternally(outboxFolderParameters, null);
|
|
||||||
|
|
||||||
session.save();
|
session.save();
|
||||||
}catch(StorageHubException she ){
|
}catch(Exception e) {
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error("jcr error creating user {}", user, e);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
}catch(RepositoryException re ){
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
} finally {
|
} finally {
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
|
@ -226,144 +126,51 @@ public class UserManager {
|
||||||
|
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{user}")
|
@Path("{id}")
|
||||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||||
public String deleteUser(@PathParam("user") final String user){
|
public String deleteUser(@PathParam("id") String id){
|
||||||
|
|
||||||
InnerMethodName.instance.set("deleteUser");
|
|
||||||
|
|
||||||
JackrabbitSession session = null;
|
JackrabbitSession session = null;
|
||||||
|
String userId = null;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||||
|
|
||||||
User authorizable = (User) usrManager.getAuthorizable(new PrincipalImpl(user));
|
org.gcube.common.storagehub.model.Path path = Utils.getWorkspacePath(id);
|
||||||
|
|
||||||
if (authorizable!=null)
|
|
||||||
removeUserFromBelongingGroup(session, authorizable, usrManager);
|
|
||||||
else log.warn("user was already deleted from jackrabbit, trying to delete folders");
|
|
||||||
|
|
||||||
unshareUsersFolders(session, user);
|
|
||||||
|
|
||||||
removeUserHomeAndDeleteFiles(session, user);
|
|
||||||
|
String sql2Query = String.format("SELECT * FROM [nthl:workspaceSharedItem] AS node WHERE ISDESCENDANTNODE('%s')", path.toPath());
|
||||||
//FINALIZE user removal
|
|
||||||
if (authorizable!=null && !authorizable.isGroup()) {
|
log.info("query sent is {}",sql2Query);
|
||||||
log.info("removing user {}", user);
|
|
||||||
|
|
||||||
|
javax.jcr.query.Query jcrQuery = session.getWorkspace().getQueryManager().createQuery(sql2Query, Constants.QUERY_LANGUAGE);
|
||||||
|
|
||||||
|
QueryResult result = jcrQuery.execute();
|
||||||
|
NodeIterator nodeIt = result.getNodes();
|
||||||
|
while (nodeIt.hasNext()) {
|
||||||
|
Node rNode = nodeIt.nextNode();
|
||||||
|
String title = rNode.hasProperty(NodeProperty.TITLE.toString()) ? rNode.getProperty(NodeProperty.TITLE.toString()).getString():"unknown";
|
||||||
|
log.debug("removing sharing for folder name {} with title {} and path {} ",rNode.getName(), title, rNode.getPath());
|
||||||
|
unshareHandler.unshare(session, Collections.singleton(id), rNode, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Authorizable authorizable = usrManager.getAuthorizable(new PrincipalImpl(id));
|
||||||
|
if (!authorizable.isGroup()) {
|
||||||
|
log.info("removing user {}", id);
|
||||||
authorizable.remove();
|
authorizable.remove();
|
||||||
} else log.warn("the user {} was already deleted, it should never happen", user);
|
}
|
||||||
|
|
||||||
session.save();
|
session.save();
|
||||||
}catch(StorageHubException she ){
|
}catch(Exception e) {
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error("jcr error getting users", e);
|
||||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||||
}catch(RepositoryException re ){
|
|
||||||
log.error("jcr error creating item", re);
|
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
||||||
} finally {
|
} finally {
|
||||||
if (session!=null)
|
if (session!=null)
|
||||||
session.logout();
|
session.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeUserFromBelongingGroup(JackrabbitSession session, User authorizable, org.apache.jackrabbit.api.security.user.UserManager usrManager) throws RepositoryException, StorageHubException {
|
|
||||||
Iterator<Authorizable> groups = session.getUserManager().findAuthorizables(new Query() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> void build(QueryBuilder<T> builder) {
|
|
||||||
builder.setSelector(Group.class);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
String user = authorizable.getPrincipal().getName();
|
|
||||||
while(groups.hasNext()) {
|
|
||||||
Authorizable group = groups.next();
|
|
||||||
log.info("group found {}", group.getPrincipal().getName() );
|
|
||||||
if (group.isGroup() && ((Group)group).isMember(authorizable)) {
|
|
||||||
|
|
||||||
boolean success = groupHandler.removeUserFromGroup(group.getPrincipal().getName(), user, session);
|
|
||||||
log.warn("user {} {} removed from vre {}",user,success?"":"not" ,group.getPrincipal().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unshareUsersFolders(JackrabbitSession session, String user){
|
|
||||||
try {
|
|
||||||
|
|
||||||
Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
|
||||||
|
|
||||||
Predicate<Node> sharedWithUserChecker = new Predicate<Node>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean test(Node t) {
|
|
||||||
try {
|
|
||||||
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
|
|
||||||
return true;
|
|
||||||
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
List<SharedFolder> items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class);
|
|
||||||
|
|
||||||
log.debug(" Shared folder to unshare found are {}", items.size());
|
|
||||||
|
|
||||||
for (SharedFolder item: items) {
|
|
||||||
String title = item.getTitle();
|
|
||||||
log.debug("in list folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
|
|
||||||
if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue;
|
|
||||||
if (item.isVreFolder()) continue;
|
|
||||||
|
|
||||||
log.info("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
|
|
||||||
String owner = item.getOwner();
|
|
||||||
|
|
||||||
Set<String> usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user);
|
|
||||||
|
|
||||||
try {
|
|
||||||
unshareHandler.unshareForRemoval(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user);
|
|
||||||
}catch (Throwable e) {
|
|
||||||
log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
log.warn("error getting folder shared with {}",user, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeUserHomeAndDeleteFiles(JackrabbitSession session, String user) throws RepositoryException, StorageHubException {
|
|
||||||
org.gcube.common.storagehub.model.Path homePath = pathUtil.getHome(user);
|
|
||||||
org.gcube.common.storagehub.model.Path workspacePath = pathUtil.getWorkspacePath(user);
|
|
||||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(user, session);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Node workspaceNode = session.getNode(workspacePath.toPath());
|
|
||||||
List<Item> workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null).stream().filter(i -> !i.isShared()).collect(Collectors.toList());
|
|
||||||
trashHandler.removeOnlyNodesContent(session, workspaceItems);
|
|
||||||
} catch (PathNotFoundException e) {
|
|
||||||
log.warn("{} workspace dir {} was already deleted", user, homePath.toPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Node trashNode = session.getNode(trashPath.toPath());
|
|
||||||
List<Item> trashItems = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
|
|
||||||
trashHandler.removeOnlyNodesContent(session, trashItems);
|
|
||||||
} catch (PathNotFoundException e) {
|
|
||||||
log.warn("{} trash dir {} was already deleted", user, homePath.toPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
Node homeNode = session.getNode(homePath.toPath());
|
|
||||||
homeNode.remove();
|
|
||||||
} catch (PathNotFoundException e) {
|
|
||||||
log.warn("{} home dir {} was already deleted", user, homePath.toPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +1,87 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.NodeIterator;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.query.Query;
|
||||||
|
import javax.jcr.query.QueryResult;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.FormParam;
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||||
import org.gcube.common.storagehub.model.Excludes;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.expressions.logical.And;
|
||||||
|
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
import org.gcube.common.storagehub.model.service.ItemList;
|
import org.gcube.common.storagehub.model.service.ItemList;
|
||||||
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.Range;
|
import org.gcube.data.access.storagehub.Range;
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
import org.gcube.data.access.storagehub.handlers.VRE;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
import org.gcube.data.access.storagehub.handlers.VREManager;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.vres.VRE;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
|
|
||||||
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
||||||
import org.gcube.smartgears.annotations.ManagedBy;
|
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
|
|
||||||
|
@Path("")
|
||||||
@Path("/")
|
public class WorkspaceManager {
|
||||||
@ManagedBy(StorageHubAppllicationManager.class)
|
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class WorkspaceManager extends Impersonable{
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(WorkspaceManager.class);
|
private static final Logger log = LoggerFactory.getLogger(WorkspaceManager.class);
|
||||||
|
|
||||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
@Inject
|
||||||
|
RepositoryInitializer repository;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Evaluators evaluator;
|
Evaluators evaluator;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PathUtil pathUtil;
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ServletContext context;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VREManager vreManager;
|
VREManager vreManager;
|
||||||
|
|
||||||
@Context
|
|
||||||
ServletContext context;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AuthorizationChecker authChecker;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TrashHandler trashHandler;
|
TrashHandler trashHandler;
|
||||||
|
|
||||||
|
@ -96,11 +92,9 @@ public class WorkspaceManager extends Impersonable{
|
||||||
@Inject Node2ItemConverter node2Item;
|
@Inject Node2ItemConverter node2Item;
|
||||||
@Inject Item2NodeConverter item2Node;
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
@Inject
|
@Inject StorageBackendHandler storageBackend;
|
||||||
FolderPluginHandler folderHandler;
|
|
||||||
|
|
||||||
|
|
||||||
@Path("/")
|
@Path("")
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
|
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
|
||||||
|
@ -108,24 +102,25 @@ public class WorkspaceManager extends Impersonable{
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
org.gcube.common.storagehub.model.Path absolutePath;
|
org.gcube.common.storagehub.model.Path absolutePath;
|
||||||
if (relPath==null)
|
if (relPath==null)
|
||||||
absolutePath = pathUtil.getWorkspacePath(currentUser);
|
absolutePath = Utils.getWorkspacePath();
|
||||||
else absolutePath = Paths.append(pathUtil.getWorkspacePath(currentUser), relPath);
|
else absolutePath = Paths.append(Utils.getWorkspacePath(), relPath);
|
||||||
|
|
||||||
Item toReturn = null;
|
Item toReturn = null;
|
||||||
try{
|
try{
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
//TODO: remove when all user will have TRASH
|
|
||||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
//TODO: remove it when users will be created via storageHub
|
||||||
|
String user = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
if (!ses.nodeExists(trashPath.toPath())) {
|
if (!ses.nodeExists(trashPath.toPath())) {
|
||||||
Node wsNode = ses.getNode(pathUtil.getWorkspacePath(currentUser).toPath());
|
Utils.createFolderInternally(ses, ses.getNode(Utils.getWorkspacePath().toPath()) , Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
|
||||||
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME)
|
|
||||||
.description("trash of "+currentUser)
|
|
||||||
.author(currentUser).on(wsNode.getIdentifier()).with(ses).build();
|
|
||||||
Utils.createFolderInternally(trashFolderParameters, null);
|
|
||||||
ses.save();
|
ses.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
Node node = ses.getNode(absolutePath.toPath());
|
Node node = ses.getNode(absolutePath.toPath());
|
||||||
authChecker.checkReadAuthorizationControl(ses, currentUser, node.getIdentifier());
|
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
|
||||||
toReturn = node2Item.getItem(node, excludes);
|
toReturn = node2Item.getItem(node, excludes);
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error getting workspace item", re);
|
log.error("jcr error getting workspace item", re);
|
||||||
|
@ -141,17 +136,38 @@ public class WorkspaceManager extends Impersonable{
|
||||||
return new ItemWrapper<Item>(toReturn);
|
return new ItemWrapper<Item>(toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized VRE getVreFolderItem(Session ses) throws RepositoryException, BackendGenericError{
|
||||||
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
|
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
|
||||||
|
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
|
||||||
|
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
|
||||||
|
VRE vre = vreManager.getVRE(entireScopeName);
|
||||||
|
if (vre!=null) return vre;
|
||||||
|
else {
|
||||||
|
String query = String.format("SELECT * FROM [nthl:workspaceItem] As node WHERE node.[jcr:title] like '%s' AND ISDESCENDANTNODE('%s')",entireScopeName, vrePath.toPath());
|
||||||
|
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
|
||||||
|
NodeIterator it = jcrQuery.execute().getNodes();
|
||||||
|
|
||||||
|
if (!it.hasNext()) throw new BackendGenericError("vre folder not found for context "+entireScopeName);
|
||||||
|
|
||||||
|
Node folder = it.nextNode();
|
||||||
|
Item vreFolder = node2Item.getItem(folder, excludes);
|
||||||
|
return vreManager.putVRE(vreFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Path("vrefolder")
|
@Path("vrefolder")
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemWrapper<Item> getVreRootFolder(){
|
public ItemWrapper<Item> getVreRootFolder(){
|
||||||
InnerMethodName.instance.set("getVreRootFolder");
|
InnerMethodName.instance.set("getVreRootFolder");
|
||||||
JackrabbitSession ses = null;
|
Session ses = null;
|
||||||
Item vreItem = null;
|
Item vreItem = null;
|
||||||
try {
|
try {
|
||||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
vreItem = vreManager.getVreFolderItem(ses, currentUser, excludes).getVreFolder();
|
vreItem = getVreFolderItem(ses).getVreFolder();
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("jcr error getting vrefolder", re);
|
log.error("jcr error getting vrefolder", re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
@ -170,12 +186,13 @@ public class WorkspaceManager extends Impersonable{
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemList getVreFolderRecentsDocument(){
|
public ItemList getVreFolderRecentsDocument(){
|
||||||
InnerMethodName.instance.set("getVreFolderRecents");
|
InnerMethodName.instance.set("getVreFolderRecents");
|
||||||
JackrabbitSession ses = null;
|
Session ses = null;
|
||||||
List<Item> recentItems = Collections.emptyList();
|
List<Item> recentItems = Collections.emptyList();
|
||||||
try{
|
try{
|
||||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
VRE vre = vreManager.getVreFolderItem(ses, currentUser, excludes);
|
VRE vre = getVreFolderItem(ses);
|
||||||
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
|
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
|
||||||
recentItems = vre.getRecents();
|
recentItems = vre.getRecents();
|
||||||
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
|
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
|
||||||
|
@ -203,12 +220,12 @@ public class WorkspaceManager extends Impersonable{
|
||||||
public ItemWrapper<Item> getTrashRootFolder(){
|
public ItemWrapper<Item> getTrashRootFolder(){
|
||||||
InnerMethodName.instance.set("getTrashRootFolder");
|
InnerMethodName.instance.set("getTrashRootFolder");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
String user = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
Item item = null;
|
Item item = null;
|
||||||
try{
|
try{
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
|
||||||
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
|
|
||||||
Node folder = ses.getNode(trashPath.toPath());
|
Node folder = ses.getNode(trashPath.toPath());
|
||||||
|
@ -225,18 +242,18 @@ public class WorkspaceManager extends Impersonable{
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ItemWrapper<Item>(item);
|
return new ItemWrapper<Item>(item);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Path("trash/empty")
|
@Path("trash/empty")
|
||||||
@DELETE
|
@DELETE
|
||||||
public String emptyTrash(){
|
public String emptyTrash(){
|
||||||
InnerMethodName.instance.set("emptyTrash");
|
InnerMethodName.instance.set("emptyTrash");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
|
||||||
Node trashNode = ses.getNode(trashPath.toPath());
|
Node trashNode = ses.getNode(trashPath.toPath());
|
||||||
List<Item> itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
|
List<Item> itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
|
||||||
trashHandler.removeNodes(ses, itemsToDelete);
|
trashHandler.removeNodes(ses, itemsToDelete);
|
||||||
|
@ -256,39 +273,32 @@ public class WorkspaceManager extends Impersonable{
|
||||||
}
|
}
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.TEXT_PLAIN)
|
||||||
@Path("trash/restore")
|
@Path("trash/restore")
|
||||||
public String restoreItem(@FormParam("trashedItemId") String trashedItemId,@FormParam("destinationId") String destinationFolderId){
|
public String restoreItem(String identifier){
|
||||||
InnerMethodName.instance.set("restoreItem");
|
InnerMethodName.instance.set("restoreItem");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
String toReturn = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
|
|
||||||
log.info("restoring node with id {}", trashedItemId);
|
log.info("restoring node with id {}", identifier);
|
||||||
|
|
||||||
|
//TODO check if it is possible to change all the ACL on a workspace
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
final Node nodeToRestore = ses.getNodeByIdentifier(trashedItemId);
|
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
|
||||||
|
|
||||||
|
final Node nodeToRestore = ses.getNodeByIdentifier(identifier);
|
||||||
|
|
||||||
Item itemToRestore = node2Item.getItem(nodeToRestore, Excludes.ALL);
|
Item itemToRestore = node2Item.getItem(nodeToRestore, Excludes.ALL);
|
||||||
|
|
||||||
if (!(itemToRestore instanceof TrashItem))
|
if (!(itemToRestore instanceof TrashItem))
|
||||||
throw new InvalidItemException("Only trash items can be restored");
|
throw new InvalidItemException("Only trash items can be restored");
|
||||||
|
|
||||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore);
|
||||||
if (!itemToRestore.getPath().startsWith(trashPath.toPath()))
|
|
||||||
throw new UserNotAuthorizedException("this item is not in the user "+currentUser+" trash");
|
|
||||||
|
|
||||||
Item destinationItem = null;
|
|
||||||
if (destinationFolderId!=null ) {
|
|
||||||
destinationItem = node2Item.getItem(ses.getNodeByIdentifier(destinationFolderId), Excludes.ALL);
|
|
||||||
if (!(destinationItem instanceof FolderItem))
|
|
||||||
throw new InvalidCallParameters("destintation item is not a folder");
|
|
||||||
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore, (FolderItem) destinationItem, currentUser);
|
|
||||||
} else
|
|
||||||
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore, null, currentUser);
|
|
||||||
|
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("error restoring item with id {}",trashedItemId, re);
|
log.error("error restoring item with id {}",identifier, re);
|
||||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
}catch(StorageHubException she ){
|
}catch(StorageHubException she ){
|
||||||
log.error(she.getErrorMessage(), she);
|
log.error(she.getErrorMessage(), she);
|
||||||
|
@ -309,13 +319,12 @@ public class WorkspaceManager extends Impersonable{
|
||||||
public ItemList getVreFolders(){
|
public ItemList getVreFolders(){
|
||||||
InnerMethodName.instance.set("getVreFolders");
|
InnerMethodName.instance.set("getVreFolders");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
List<? extends Item> toReturn = null;
|
|
||||||
org.gcube.common.storagehub.model.Path vrePath = null;
|
|
||||||
try{
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
vrePath = pathUtil.getVREsPath(currentUser, ses);
|
|
||||||
log.info("vres folder path is {}",vrePath.toPath());
|
|
||||||
|
|
||||||
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
|
List<? extends Item> toReturn = null;
|
||||||
|
try{
|
||||||
|
log.info("vres folder path is {}",vrePath.toPath());
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
|
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("error reading the node children of {}",vrePath, re);
|
log.error("error reading the node children of {}",vrePath, re);
|
||||||
|
@ -337,11 +346,10 @@ public class WorkspaceManager extends Impersonable{
|
||||||
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
|
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
|
||||||
InnerMethodName.instance.set("getVreFoldersPaged");
|
InnerMethodName.instance.set("getVreFoldersPaged");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
org.gcube.common.storagehub.model.Path vrePath = null;
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
vrePath = pathUtil.getVREsPath(currentUser, ses);
|
|
||||||
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false, null);
|
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false, null);
|
||||||
}catch(RepositoryException re ){
|
}catch(RepositoryException re ){
|
||||||
log.error("(paged) error reading the node children of {}",vrePath, re);
|
log.error("(paged) error reading the node children of {}",vrePath, re);
|
||||||
|
@ -358,12 +366,65 @@ public class WorkspaceManager extends Impersonable{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Path("query")
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public ItemList searchItems(@QueryParam("n") String node, @QueryParam("e") String jsonExpr, @QueryParam("o") List<String> orderField, @QueryParam("l") Integer limit, @QueryParam("f") Integer offset){
|
||||||
|
InnerMethodName.instance.set("searchItems");
|
||||||
|
Session ses = null;
|
||||||
|
List<? extends Item> toReturn = new ArrayList<>();
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
|
||||||
|
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getWorkspacePath()), expression));
|
||||||
|
|
||||||
|
String orderBy = "";
|
||||||
|
if (orderField!=null && orderField.size()>0)
|
||||||
|
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
|
||||||
|
|
||||||
|
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
|
||||||
|
|
||||||
|
log.info("query sent is {}",sql2Query);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(sql2Query, Constants.QUERY_LANGUAGE);
|
||||||
|
|
||||||
|
if (limit!=null && limit!=-1 )
|
||||||
|
jcrQuery.setLimit(limit);
|
||||||
|
|
||||||
|
if (offset!=null && offset!=-1 )
|
||||||
|
jcrQuery.setOffset(offset);
|
||||||
|
|
||||||
|
QueryResult result = jcrQuery.execute();
|
||||||
|
|
||||||
|
NodeIterator it = result.getNodes();
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
|
toReturn.add(node2Item.getItem(it.nextNode(), null));
|
||||||
|
}catch(RepositoryException | IOException re ){
|
||||||
|
log.error("error executing the query", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error(she.getErrorMessage(), she);
|
||||||
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ItemList(toReturn);
|
||||||
|
}
|
||||||
|
|
||||||
@Path("count")
|
@Path("count")
|
||||||
@GET
|
@GET
|
||||||
public String getTotalItemsCount(){
|
public String getTotalItemsCount(){
|
||||||
InnerMethodName.instance.set("getTotalItemsCount");
|
InnerMethodName.instance.set("getTotalItemsCount");
|
||||||
return folderHandler.getDefault().getStorageBackend().getTotalItemsCount();
|
return storageBackend.getTotalItemsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -371,8 +432,8 @@ public class WorkspaceManager extends Impersonable{
|
||||||
@GET
|
@GET
|
||||||
public String getTotalVolume(){
|
public String getTotalVolume(){
|
||||||
InnerMethodName.instance.set("getTotalSize");
|
InnerMethodName.instance.set("getTotalSize");
|
||||||
return folderHandler.getDefault().getStorageBackend().getTotalSizeStored();
|
return storageBackend.getTotalVolume();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,200 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services.admin;
|
|
||||||
|
|
||||||
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
|
|
||||||
import org.apache.cxf.io.ReaderInputStream;
|
|
||||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
|
||||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
|
||||||
import org.gcube.common.authorization.library.AuthorizedTasks;
|
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.data.access.storagehub.PathUtil;
|
|
||||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
|
||||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
|
|
||||||
import org.gcube.data.access.storagehub.scripting.AbstractScript;
|
|
||||||
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
|
|
||||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
|
||||||
|
|
||||||
@Path("admin/script")
|
|
||||||
@RequestHeaders({
|
|
||||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
|
||||||
})
|
|
||||||
public class ScriptManager {
|
|
||||||
|
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(ScriptManager.class);
|
|
||||||
|
|
||||||
private RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AccountingHandler accountingHandler;
|
|
||||||
|
|
||||||
@Context
|
|
||||||
ServletContext context;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
ScriptUtil scriptUtil;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
ItemHandler itemHandler;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
PathUtil pathUtil;
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("execute")
|
|
||||||
@AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class)
|
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
|
||||||
public String run( @FormDataParam("name") String name,
|
|
||||||
@FormDataParam("asynch") Boolean asynch,
|
|
||||||
@FormDataParam("destinationFolderId") String destinationFolderId,
|
|
||||||
@FormDataParam("file") InputStream stream,
|
|
||||||
@FormDataParam("file") FormDataContentDisposition fileDetail) {
|
|
||||||
try {
|
|
||||||
ScriptClassLoader scriptClassLoader = new ScriptClassLoader(Thread.currentThread().getContextClassLoader());
|
|
||||||
Class<?> scriptClass = uploadClass(stream, scriptClassLoader, fileDetail.getFileName().replace(".class", ""));
|
|
||||||
return run(scriptClass, name, destinationFolderId, asynch!=null? asynch : false);
|
|
||||||
}catch(Throwable e) {
|
|
||||||
log.error("error executing script {}", name,e);
|
|
||||||
throw new WebApplicationException("error loading class",e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Class<?> uploadClass(InputStream stream, ScriptClassLoader classLoader, String name) throws Throwable {
|
|
||||||
try(ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
|
|
||||||
int nRead;
|
|
||||||
byte[] data = new byte[1024];
|
|
||||||
while ((nRead = stream.read(data, 0, data.length)) != -1)
|
|
||||||
buffer.write(data, 0, nRead);
|
|
||||||
|
|
||||||
buffer.flush();
|
|
||||||
byte[] byteArray = buffer.toByteArray();
|
|
||||||
return classLoader.findClass(name, byteArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String run(Class<?> clazz, String name, String destinationFolderId, boolean asynch) throws Throwable {
|
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
log.info("script {} called by {}", clazz.getSimpleName(), login);
|
|
||||||
JackrabbitSession ses = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
||||||
|
|
||||||
String parentId = destinationFolderId!=null ? destinationFolderId : ses.getNode(pathUtil.getWorkspacePath(login).toPath()).getIdentifier();
|
|
||||||
Node parentNode = ses.getNodeByIdentifier(parentId);
|
|
||||||
String parentPath = parentNode.getPath();
|
|
||||||
|
|
||||||
if (AbstractScript.class.isAssignableFrom(clazz)) {
|
|
||||||
AbstractScript scriptInstance = (AbstractScript) clazz.newInstance();
|
|
||||||
|
|
||||||
RealRun realRun = new RealRun(ses, scriptInstance, login, parentId, name);
|
|
||||||
if (asynch) {
|
|
||||||
new Thread(AuthorizedTasks.bind(realRun)).start();
|
|
||||||
}else realRun.run();
|
|
||||||
|
|
||||||
} else throw new Exception("class "+clazz.getSimpleName()+" not implements AbstractScript");
|
|
||||||
|
|
||||||
return Paths.append(Paths.getPath(parentPath), name).toPath();
|
|
||||||
|
|
||||||
}catch (Throwable e) {
|
|
||||||
if (ses !=null && ses.isLive())
|
|
||||||
ses.logout();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class RealRun implements Runnable{
|
|
||||||
|
|
||||||
private JackrabbitSession ses;
|
|
||||||
AbstractScript instance;
|
|
||||||
String login;
|
|
||||||
String parentId;
|
|
||||||
String name;
|
|
||||||
|
|
||||||
public RealRun(JackrabbitSession ses, AbstractScript instance, String login, String parentId, String name) {
|
|
||||||
super();
|
|
||||||
this.ses = ses;
|
|
||||||
this.instance = instance;
|
|
||||||
this.login = login;
|
|
||||||
this.parentId = parentId;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try{
|
|
||||||
String result ="";
|
|
||||||
try {
|
|
||||||
result = instance.run(ses, null, scriptUtil);
|
|
||||||
log.info("result is {}",result);
|
|
||||||
}catch(Throwable t) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw, true);
|
|
||||||
t.printStackTrace(pw);
|
|
||||||
result+= "\n"+sw.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
try( InputStream stream = new ReaderInputStream(new StringReader(result))){
|
|
||||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description("result of script execution "+name)
|
|
||||||
.stream(stream).on(parentId).with(ses).author(login);
|
|
||||||
itemHandler.create(builder.build());
|
|
||||||
} catch (Throwable e) {
|
|
||||||
log.error("error saving script result {} in the Workspace",name, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (ses!=null)
|
|
||||||
ses.logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class ScriptClassLoader extends ClassLoader{
|
|
||||||
|
|
||||||
public ScriptClassLoader(ClassLoader parent) {
|
|
||||||
super(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> findClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services.admin;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class ScriptUtilImpl implements ScriptUtil {
|
|
||||||
|
|
||||||
@Inject Node2ItemConverter node2Item;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Item> getChildren(Predicate<Node> checker, Node parent, List<String> excludes, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError {
|
|
||||||
return Utils.getItemList(checker, parent, excludes, null, showHidden, nodeTypeToInclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Item getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError {
|
|
||||||
return node2Item.getItem(node, excludes);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services.delegates;
|
|
||||||
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.jcr.Node;
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.jcr.security.AccessControlEntry;
|
|
||||||
import javax.jcr.security.AccessControlManager;
|
|
||||||
import javax.jcr.security.Privilege;
|
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
|
||||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
|
||||||
import org.gcube.common.storagehub.model.acls.ACL;
|
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
|
||||||
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class ACLManagerDelegate implements ACLManagerInterface {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
Node2ItemConverter node2Item;
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(ACLManagerDelegate.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError {
|
|
||||||
List<ACL> acls = new ArrayList<>();
|
|
||||||
if (!item.isShared()) return acls;
|
|
||||||
|
|
||||||
Node toRetrieve = (Node) item.getRelatedNode();
|
|
||||||
if (!(item instanceof SharedFolder))
|
|
||||||
toRetrieve = retrieveSharedFolderParent(toRetrieve, session);
|
|
||||||
|
|
||||||
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, toRetrieve.getPath());
|
|
||||||
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
|
|
||||||
ACL acl = new ACL();
|
|
||||||
acl.setPricipal(aclEntry.getPrincipal().getName());
|
|
||||||
List<AccessType> types = new ArrayList<>();
|
|
||||||
for (Privilege priv : aclEntry.getPrivileges())
|
|
||||||
try {
|
|
||||||
types.add(AccessType.fromValue(priv.getName()));
|
|
||||||
}catch (Exception e) {
|
|
||||||
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
|
|
||||||
}
|
|
||||||
acl.setAccessTypes(types);
|
|
||||||
acls.add(acl);
|
|
||||||
}
|
|
||||||
return acls;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
|
|
||||||
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
|
|
||||||
else
|
|
||||||
return retrieveSharedFolderParent(node.getParent(), session);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException {
|
|
||||||
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
|
||||||
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
|
|
||||||
_remove(acls, principal);
|
|
||||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
|
||||||
acls.addAccessControlEntry(principal, userPrivileges);
|
|
||||||
acm.setPolicy(folder.getPath(), acls);
|
|
||||||
session.save();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void delete(String targetUser, SharedFolder folder, Session session) throws RepositoryException {
|
|
||||||
AccessControlManager acm = session.getAccessControlManager();
|
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
|
||||||
|
|
||||||
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
|
|
||||||
_remove(acls, principal);
|
|
||||||
acm.setPolicy(folder.getPath(), acls);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void _remove(JackrabbitAccessControlList acls, Principal principal) throws RepositoryException {
|
|
||||||
AccessControlEntry aceToDelete = null;
|
|
||||||
for (AccessControlEntry ace : acls.getAccessControlEntries())
|
|
||||||
if (ace.getPrincipal().equals(principal)) {
|
|
||||||
aceToDelete = ace;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aceToDelete!= null)
|
|
||||||
acls.removeAccessControlEntry(aceToDelete);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.services.interfaces;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.jcr.RepositoryException;
|
|
||||||
import javax.jcr.Session;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.acls.ACL;
|
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
|
||||||
|
|
||||||
public interface ACLManagerInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the AccessType for all the users in a shared folder
|
|
||||||
*
|
|
||||||
* @exception {@link RepositoryException} when a generic jcr error occurs
|
|
||||||
* @exception {@link UserNotAuthorizedException} when the caller is not authorized to access to the shared folder
|
|
||||||
*/
|
|
||||||
List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a new AccessType for a user in a shared folder or VRE folder
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param String user
|
|
||||||
* @param accessType accessType
|
|
||||||
*
|
|
||||||
* @exception {@link RepositoryException} when a generic jcr error occurs
|
|
||||||
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
|
|
||||||
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
|
|
||||||
* @exception {@link InvalidItemException} when the folder is not share
|
|
||||||
*/
|
|
||||||
void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException;
|
|
||||||
|
|
||||||
void delete(String targetUser, SharedFolder folder, Session session)
|
|
||||||
throws RepositoryException, StorageHubException;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class GCubeFolderManagerConnector implements FolderManagerConnector {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FolderManager connect(FolderItem item, Map<String, Object> parameters) throws PluginInitializationException {
|
|
||||||
return new GcubeFolderManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,11 +1,10 @@
|
||||||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
package org.gcube.data.access.storagehub.storage.backend.impl;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.UUID;
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
|
||||||
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||||
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||||
|
@ -15,6 +14,7 @@ import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
public class GCubeStorageBackend implements StorageBackend {
|
public class GCubeStorageBackend implements StorageBackend {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(GCubeStorageBackend.class);
|
private static final Logger log = LoggerFactory.getLogger(GCubeStorageBackend.class);
|
||||||
|
@ -22,13 +22,9 @@ public class GCubeStorageBackend implements StorageBackend {
|
||||||
private final static String SERVICE_NAME = "home-library";
|
private final static String SERVICE_NAME = "home-library";
|
||||||
private final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
private final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected GCubeStorageBackend() {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream download(Content content) {
|
public InputStream getContent(String id) {
|
||||||
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(content.getStorageId());
|
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,38 +33,35 @@ public class GCubeStorageBackend implements StorageBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String onCopy(AbstractFileItem item) {
|
public String copy(String idToCopy, String path) {
|
||||||
log.info("copying storage Id {} to newPath {}", item.getContent().getStorageId(), item.getPath());
|
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(idToCopy).to(path);
|
||||||
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(item.getContent().getStorageId()).to(item.getPath());
|
log.info("copying storage Id {} to newPath {} and the id returned by storage is {}", idToCopy, path, newStorageID);
|
||||||
log.info("The id returned by storage is {}", newStorageID);
|
|
||||||
return newStorageID;
|
return newStorageID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String onMove(AbstractFileItem item) {
|
public String move(String idToMove) {
|
||||||
return item.getContent().getStorageId();
|
return idToMove;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetaInfo upload(InputStream stream, String relPath, String name) {
|
public MetaInfo upload(InputStream stream, String itemPath) {
|
||||||
log.debug("uploading file");
|
log.debug("uploading file");
|
||||||
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
||||||
String uid = UUID.randomUUID().toString();
|
String storageId =storageClient.put(true).LFile(stream).RFile(itemPath);
|
||||||
String remotePath= String.format("%s/%s-%s",relPath,uid,name);
|
|
||||||
String storageId =storageClient.put(true).LFile(stream).RFile(remotePath);
|
|
||||||
long size = storageClient.getSize().RFileById(storageId);
|
long size = storageClient.getSize().RFileById(storageId);
|
||||||
MetaInfo info = new MetaInfo();
|
MetaInfo info = new MetaInfo();
|
||||||
info.setSize(size);
|
info.setSize(size);
|
||||||
info.setStorageId(storageId);
|
info.setStorageId(storageId);
|
||||||
info.setRemotePath(remotePath);
|
info.setRemotePath(itemPath);
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDelete(Content content) {
|
public void delete(String id) {
|
||||||
log.debug("deleting");
|
log.debug("deleting");
|
||||||
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
||||||
storageClient.remove().RFileById(content.getStorageId());
|
storageClient.remove().RFileById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StorageClient getStorageClient(String login){
|
private static StorageClient getStorageClient(String login){
|
||||||
|
@ -88,5 +81,8 @@ public class GCubeStorageBackend implements StorageBackend {
|
||||||
return storageClient.getUserTotalItems();
|
return storageClient.getUserTotalItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
|
||||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
|
||||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
public class GcubeFolderManager implements FolderManager {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StorageBackend getStorageBackend() {
|
|
||||||
return new GCubeStorageBackend();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean manageVersion() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatedFolder(FolderItem folder) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDeletingFolder(FolderItem folder) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMovedFolder(FolderItem movedFolder) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCopiedFolder(FolderItem copiedFolder) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FolderItem getRootFolder() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.types;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
|
||||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
|
||||||
|
|
||||||
public class ContentPair {
|
|
||||||
|
|
||||||
private Content content;
|
|
||||||
private StorageBackend storageBackend;
|
|
||||||
public ContentPair(Content content, StorageBackend storageBackend) {
|
|
||||||
super();
|
|
||||||
this.content = content;
|
|
||||||
this.storageBackend = storageBackend;
|
|
||||||
}
|
|
||||||
public Content getContent() {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
public StorageBackend getStorageBackend() {
|
|
||||||
return storageBackend;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((content.getStorageId() == null) ? 0 : content.getStorageId().hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
ContentPair other = (ContentPair) obj;
|
|
||||||
if (content.getStorageId() == null) {
|
|
||||||
if (other.content.getStorageId() != null)
|
|
||||||
return false;
|
|
||||||
} else if (!content.getStorageId().equals(other.content.getStorageId()))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.gcube.data.access.storagehub.types;
|
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
|
||||||
import org.gcube.common.storagehub.model.messages.Message;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@RootNode("nthl:itemSentRequestSH")
|
|
||||||
public class MessageSharable extends Message {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,3 @@
|
||||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
|
||||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
|
||||||
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
|
|
||||||
bean-discovery-mode="all">
|
|
||||||
</beans>
|
</beans>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,297 +1,313 @@
|
||||||
European Union Public Licence V. 1.1
|
European Union Public Licence V. 1.1
|
||||||
|
|
||||||
|
|
||||||
EUPL © the European Community 2007
|
EUPL © the European Community 2007
|
||||||
|
|
||||||
|
|
||||||
This European Union Public Licence (the “EUPL”) applies to the Work or Software
|
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
|
(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
|
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).
|
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
|
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
|
(as defined below) has placed the following notice immediately following the
|
||||||
copyright notice for the Original Work:
|
copyright notice for the Original Work:
|
||||||
|
|
||||||
Licensed under the EUPL V.1.1
|
Licensed under the EUPL V.1.1
|
||||||
|
|
||||||
or has expressed by any other mean his willingness to license under the EUPL.
|
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:
|
1. Definitions
|
||||||
|
|
||||||
- The Licence: this Licence.
|
In this Licence, the following terms have the following meaning:
|
||||||
|
|
||||||
- The Original Work or the Software: the software distributed and/or
|
- The Licence: this Licence.
|
||||||
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,
|
- The Original Work or the Software: the software distributed and/or
|
||||||
based upon the Original Work or modifications thereof. This Licence does not
|
communicated by the Licensor under this Licence, available as Source Code and
|
||||||
define the extent of modification or dependence on the Original Work required
|
also as Executable Code as the case may be.
|
||||||
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.
|
- 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 Source Code: the human-readable form of the Work which is the most
|
- The Work: the Original Work and/or its Derivative Works.
|
||||||
convenient for people to study and modify.
|
|
||||||
|
|
||||||
- The Executable Code: any code which has generally been compiled and which is
|
- The Source Code: the human-readable form of the Work which is the most
|
||||||
meant to be interpreted by a computer as a program.
|
convenient for people to study and modify.
|
||||||
|
|
||||||
- The Licensor: the natural or legal person that distributes and/or communicates
|
- The Executable Code: any code which has generally been compiled and which is
|
||||||
the Work under the Licence.
|
meant to be interpreted by a computer as a program.
|
||||||
|
|
||||||
- Contributor(s): any natural or legal person who modifies the Work under the
|
- The Licensor: the natural or legal person that distributes and/or communicates
|
||||||
Licence, or otherwise contributes to the creation of a Derivative Work.
|
the Work under the Licence.
|
||||||
|
|
||||||
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
- Contributor(s): any natural or legal person who modifies the Work under the
|
||||||
Software under the terms of the Licence.
|
Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||||
|
|
||||||
- Distribution and/or Communication: any act of selling, giving, lending,
|
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
||||||
renting, distributing, communicating, transmitting, or otherwise making
|
Software under the terms of the Licence.
|
||||||
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.
|
|
||||||
|
|
||||||
|
- 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
|
2. Scope of the rights granted by the Licence
|
||||||
- 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
|
The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
|
||||||
known or later invented, as far as the applicable law permits so.
|
sub-licensable licence to do the following, for the duration of copyright vested
|
||||||
|
in the Original Work:
|
||||||
|
|
||||||
In the countries where moral rights apply, the Licensor waives his right to
|
- use the Work in any circumstance and for all usage, reproduce the Work, modify
|
||||||
exercise his moral right to the extent allowed by law in order to make effective
|
- the Original Work, and make Derivative Works based upon the Work, communicate
|
||||||
the licence of the economic rights here above listed.
|
- 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.
|
||||||
|
|
||||||
The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
|
Those rights can be exercised on any media, supports and formats, whether now
|
||||||
any patents held by the Licensor, to the extent necessary to make use of the
|
known or later invented, as far as the applicable law permits so.
|
||||||
rights granted on the Work under this Licence.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
3. Communication of the Source Code
|
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.
|
||||||
|
|
||||||
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
|
3. Communication of the Source Code
|
||||||
|
|
||||||
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
The Licensor may provide the Work either in its Source Code form, or as
|
||||||
any exception or limitation to the exclusive rights of the rights owners in the
|
Executable Code. If the Work is provided as Executable Code, the Licensor
|
||||||
Original Work or Software, of the exhaustion of those rights or of other
|
provides in addition a machine-readable copy of the Source Code of the Work
|
||||||
applicable limitations thereto.
|
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.
|
||||||
|
|
||||||
|
|
||||||
5. Obligations of the Licensee
|
|
||||||
|
|
||||||
The grant of the rights mentioned above is subject to some restrictions and
|
4. Limitations on copyright
|
||||||
obligations imposed on the Licensee. Those obligations are the following:
|
|
||||||
|
|
||||||
Attribution right: the Licensee shall keep intact all copyright, patent or
|
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
||||||
trademarks notices and all notices that refer to the Licence and to the
|
any exception or limitation to the exclusive rights of the rights owners in the
|
||||||
disclaimer of warranties. The Licensee must include a copy of such notices and a
|
Original Work or Software, of the exhaustion of those rights or of other
|
||||||
copy of the Licence with every copy of the Work he/she distributes and/or
|
applicable limitations thereto.
|
||||||
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
|
5. Obligations of the Licensee
|
||||||
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,
|
The grant of the rights mentioned above is subject to some restrictions and
|
||||||
trademarks, service marks, or names of the Licensor, except as required for
|
obligations imposed on the Licensee. Those obligations are the following:
|
||||||
reasonable and customary use in describing the origin of the Work and
|
|
||||||
reproducing the content of the copyright notice.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
6. Chain of Authorship
|
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.
|
||||||
|
|
||||||
The original Licensor warrants that the copyright in the Original Work granted
|
Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
|
||||||
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
Works or copies thereof based upon both the Original Work and another work
|
||||||
power and authority to grant the Licence.
|
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.
|
||||||
|
|
||||||
Each Contributor warrants that the copyright in the modifications he/she brings
|
Provision of Source Code: When distributing and/or communicating copies of the
|
||||||
to the Work are owned by him/her or licensed to him/her and that he/she has the
|
Work, the Licensee will provide a machine-readable copy of the Source Code or
|
||||||
power and authority to grant the Licence.
|
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.
|
||||||
|
|
||||||
Each time You accept the Licence, the original Licensor and subsequent
|
Legal Protection: This Licence does not grant permission to use the trade names,
|
||||||
Contributors grant You a licence to their contributions to the Work, under the
|
trademarks, service marks, or names of the Licensor, except as required for
|
||||||
terms of this Licence.
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the copyright notice.
|
||||||
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty
|
|
||||||
|
|
||||||
The Work is a work in progress, which is continuously improved by numerous
|
6. Chain of Authorship
|
||||||
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
|
The original Licensor warrants that the copyright in the Original Work granted
|
||||||
and without warranties of any kind concerning the Work, including without
|
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
||||||
limitation merchantability, fitness for a particular purpose, absence of defects
|
power and authority to grant the Licence.
|
||||||
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
|
Each Contributor warrants that the copyright in the modifications he/she brings
|
||||||
for the grant of any rights to the Work.
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty
|
||||||
|
|
||||||
9. Additional agreements
|
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.
|
||||||
|
|
||||||
While distributing the Original Work or Derivative Works, You may choose to
|
For the above reason, the Work is provided under the Licence on an “as is” basis
|
||||||
conclude an additional agreement to offer, and charge a fee for, acceptance of
|
and without warranties of any kind concerning the Work, including without
|
||||||
support, warranty, indemnity, or other liability obligations and/or services
|
limitation merchantability, fitness for a particular purpose, absence of defects
|
||||||
consistent with this Licence. However, in accepting such obligations, You may
|
or errors, accuracy, non-infringement of intellectual property rights other than
|
||||||
act only on your own behalf and on your sole responsibility, not on behalf of
|
copyright as stated in Article 6 of this Licence.
|
||||||
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.
|
|
||||||
|
|
||||||
|
This disclaimer of warranty is an essential part of the Licence and a condition
|
||||||
|
for the grant of any rights to the Work.
|
||||||
|
|
||||||
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
|
8. Disclaimer of Liability
|
||||||
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.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
9. Additional agreements
|
||||||
|
|
||||||
12. Termination of the Licence
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
10. Acceptance of the Licence
|
||||||
|
|
||||||
13. Miscellaneous
|
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.
|
||||||
|
|
||||||
Without prejudice of Article 9 above, the Licence represents the complete
|
Similarly, you irrevocably accept this Licence and all of its terms and
|
||||||
agreement between the Parties as to the Work licensed hereunder.
|
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.
|
||||||
|
|
||||||
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,
|
11. Information to the public
|
||||||
have identical value. Parties can take advantage of the linguistic version of
|
|
||||||
their choice.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
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
|
12. Termination of the Licence
|
||||||
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.
|
|
||||||
|
|
||||||
|
The Licence and the rights granted hereunder will terminate automatically upon
|
||||||
|
any breach by the Licensee of the terms of the Licence.
|
||||||
|
|
||||||
15. Applicable Law
|
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.
|
||||||
|
|
||||||
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
|
13. Miscellaneous
|
||||||
- Licensee; the Licensor, other than the European Commission, has no residence
|
|
||||||
- or registered office inside a European Union country.
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
Appendix
|
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.
|
||||||
|
|
||||||
|
|
||||||
“Compatible Licences” according to article 5 EUPL are:
|
|
||||||
|
|
||||||
|
14. Jurisdiction
|
||||||
|
|
||||||
- GNU General Public License (GNU GPL) v. 2
|
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.
|
||||||
|
|
||||||
- Open Software License (OSL) v. 2.1, v. 3.0
|
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.
|
||||||
|
|
||||||
- Common Public License v. 1.0
|
|
||||||
|
|
||||||
- Eclipse Public License v. 1.0
|
|
||||||
|
|
||||||
- Cecill v. 2.0
|
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
|
||||||
|
|
|
@ -5,27 +5,27 @@ REST web service for Jackrabbit
|
||||||
|
|
||||||
|
|
||||||
This software is part of the gCube Framework (https://www.gcube-system.org/): an
|
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
|
open-source software toolkit used for building and operating Hybrid Data
|
||||||
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
||||||
by favouring the realisation of reuse oriented policies.
|
by favouring the realisation of reuse oriented policies.
|
||||||
|
|
||||||
The projects leading to this software have received funding from a series of
|
The projects leading to this software have received funding from a series of
|
||||||
European Union programmes including:
|
European Union programmes including:
|
||||||
* the Sixth Framework Programme for Research and Technological Development -
|
* the Sixth Framework Programme for Research and Technological Development -
|
||||||
DILIGENT (grant no. 004260);
|
DILIGENT (grant no. 004260);
|
||||||
* the Seventh Framework Programme for research, technological development and
|
* the Seventh Framework Programme for research, technological development and
|
||||||
demonstration - D4Science (grant no. 212488), D4Science-II (grant no.
|
demonstration - D4Science (grant no. 212488), D4Science-II (grant no.
|
||||||
239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine
|
239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine
|
||||||
(grant no. 283644);
|
(grant no. 283644);
|
||||||
* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680),
|
* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680),
|
||||||
EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant
|
EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant
|
||||||
no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
|
no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
|
||||||
|
|
||||||
|
|
||||||
Version
|
Version
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
1.4.2 (20230524-150450)
|
1.0.7-SNAPSHOT (2019-09-16)
|
||||||
|
|
||||||
Please see the file named "changelog.xml" in this directory for the release notes.
|
Please see the file named "changelog.xml" in this directory for the release notes.
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ Download information
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
Source code is available from SVN:
|
Source code is available from SVN:
|
||||||
https://code-repo.d4science.org/gCubeSystem/storagehub
|
${scm.url}
|
||||||
|
|
||||||
Binaries can be downloaded from the gCube website:
|
Binaries can be downloaded from the gCube website:
|
||||||
https://www.gcube-system.org/
|
https://www.gcube-system.org/
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
<application mode='online'>
|
|
||||||
<name>StorageHub</name>
|
|
||||||
<group>DataAccess</group>
|
|
||||||
<version>1.4.2</version>
|
|
||||||
<description>Storage Hub webapp</description>
|
|
||||||
<local-persistence location='target' />
|
|
||||||
<exclude>/workspace/api-docs/*</exclude>
|
|
||||||
</application>
|
|
|
@ -1,26 +0,0 @@
|
||||||
.d4science_intro {
|
|
||||||
top: 0;
|
|
||||||
z-index: 2000;
|
|
||||||
position: fixed;
|
|
||||||
display: block ruby;
|
|
||||||
padding: 10px;
|
|
||||||
background: white;
|
|
||||||
width: 100%;
|
|
||||||
height: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-fixed-top {
|
|
||||||
top: 100px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
top: 160px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar {
|
|
||||||
margin-bottom: 40px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
top: 90px;
|
|
||||||
}
|
|
|
@ -9,15 +9,15 @@ import org.gcube.common.storagehub.model.expressions.GenericSearchableItem;
|
||||||
import org.gcube.common.storagehub.model.expressions.date.Before;
|
import org.gcube.common.storagehub.model.expressions.date.Before;
|
||||||
import org.gcube.common.storagehub.model.expressions.logical.And;
|
import org.gcube.common.storagehub.model.expressions.logical.And;
|
||||||
import org.gcube.common.storagehub.model.expressions.text.Contains;
|
import org.gcube.common.storagehub.model.expressions.text.Contains;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
|
||||||
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
//@RunWith(WeldJunit4Runner.class)
|
//@RunWith(WeldJunit4Runner.class)
|
||||||
public class Expressions {
|
public class Expressions {
|
||||||
/*
|
|
||||||
private static Logger log = LoggerFactory.getLogger(Expression.class);
|
private static Logger log = LoggerFactory.getLogger(Expression.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -36,21 +36,12 @@ public class Expressions {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test2() {
|
||||||
String entirePath = "sp2/comic/";
|
String groupId ="/gcube/devsec/devVre";
|
||||||
/*String[] parentPathSplit = entirePath.split("/");
|
String title = groupId.substring(groupId.lastIndexOf("/")+1);
|
||||||
System.out.println(parentPathSplit.length);
|
System.out.println(title);
|
||||||
for (String v: parentPathSplit)
|
|
||||||
System.out.println(v);
|
|
||||||
*/
|
|
||||||
|
|
||||||
String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2");
|
|
||||||
String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1");
|
|
||||||
System.out.println(entirePath+" --"+name+"-- "+parentPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
|
@ -14,23 +13,18 @@ import javax.jcr.nodetype.NodeType;
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.vlkan.rfos.RotatingFileOutputStream;
|
|
||||||
import com.vlkan.rfos.RotationConfig;
|
|
||||||
import com.vlkan.rfos.policy.DailyRotationPolicy;
|
|
||||||
import com.vlkan.rfos.policy.SizeBasedRotationPolicy;
|
|
||||||
|
|
||||||
|
|
||||||
public class TestFields {
|
public class TestFields {
|
||||||
|
|
||||||
Logger logger = LoggerFactory.getLogger(TestFields.class);
|
Logger logger = LoggerFactory.getLogger(TestFields.class);
|
||||||
|
|
||||||
@Test
|
//@Test
|
||||||
public void iterateOverFields() throws Exception{
|
public void iterateOverFields() throws Exception{
|
||||||
|
|
||||||
Property prop = mock(Property.class);
|
Property prop = mock(Property.class);
|
||||||
|
@ -69,21 +63,4 @@ public class TestFields {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void print() throws Exception{
|
|
||||||
RotationConfig config = RotationConfig
|
|
||||||
.builder()
|
|
||||||
.file("/tmp/app.log")
|
|
||||||
.filePattern("/tmp/app-%d{yyyyMMdd-HHmmss.SSS}.log")
|
|
||||||
.policy(new SizeBasedRotationPolicy(1024 * 1024 * 100 /* 100MiB */))
|
|
||||||
.policy(DailyRotationPolicy.getInstance())
|
|
||||||
.build();
|
|
||||||
|
|
||||||
try (RotatingFileOutputStream stream = new RotatingFileOutputStream(config)) {
|
|
||||||
for (int i =0 ; i<1000 ; i++)
|
|
||||||
stream.write("Operation: done".getBytes(StandardCharsets.UTF_8));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
package org.gcube.data.access.fs;
|
package org.gcube.data.access.fs;
|
||||||
|
|
||||||
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.DataBufferByte;
|
||||||
|
import java.awt.image.DataBufferInt;
|
||||||
|
import java.awt.image.ImageObserver;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestNode {
|
public class TestNode {
|
||||||
|
|
||||||
/*@Test
|
/*@Test
|
||||||
|
|
Loading…
Reference in New Issue