Compare commits
131 Commits
Author | SHA1 | Date |
---|---|---|
Massimiliano Assante | fc37ffec6f | |
lucio | e0a50f2a72 | |
lucio | b4c9cfeee6 | |
lucio | 7920345286 | |
lucio | 80704b9df2 | |
lucio | a42919ffcf | |
lucio | 6b54bf4554 | |
lucio | 122cba00e4 | |
Lucio Lelii | 60d9bf570c | |
Lucio Lelii | f9870a0190 | |
lucio | d9a229929b | |
Lucio Lelii | 0b907277cd | |
Lucio Lelii | 500aaa3fc9 | |
Lucio Lelii | e167aa24d9 | |
Lucio Lelii | 39d73b97c4 | |
Lucio Lelii | 4dc547afd2 | |
Lucio Lelii | 122b326203 | |
Lucio Lelii | 1bbd1d200f | |
Lucio Lelii | 647dbb651a | |
lucio.lelii | 7f88e20a88 | |
lucio.lelii | 08f0160d8d | |
lucio.lelii | 2a46ac3aa2 | |
lucio.lelii | 882f849e2f | |
lucio.lelii | 8c934a138e | |
lucio.lelii | 20390e3147 | |
lucio.lelii | 47bf9b57d2 | |
lucio.lelii | 27c6f2d3e1 | |
lucio.lelii | 586d9df939 | |
lucio.lelii | 7ebd1ae629 | |
lucio.lelii | 51cbd0776a | |
lucio.lelii | f30029c052 | |
Lucio Lelii | 68eb65e168 | |
lucio.lelii | 8fd9bb5ac2 | |
lucio.lelii | 147e8a8961 | |
Roberto Cirillo | 933009f8ab | |
Roberto Cirillo | 0222d27a5e | |
Roberto Cirillo | 082b49ebc6 | |
Roberto Cirillo | e255a2ff5d | |
lucio.lelii | 24576cd30f | |
Lucio Lelii | f68588e05c | |
Lucio Lelii | cb609cf51c | |
Lucio Lelii | 8929ff579c | |
Lucio Lelii | aeb434dd06 | |
lucio.lelii | 470cc28035 | |
lucio.lelii | 13016497f1 | |
lucio.lelii | eab7dc19b4 | |
lucio.lelii | 3723ac730c | |
lucio.lelii | 2aadb9cce7 | |
lucio.lelii | bcbe97f547 | |
lucio.lelii | a2613dc1a7 | |
lucio.lelii | 64952442ed | |
lucio.lelii | e271e9fe78 | |
lucio.lelii | 7566a3cf9f | |
lucio.lelii | 8c677df64e | |
lucio.lelii | 61c84fbb11 | |
lucio.lelii | 31751ca11e | |
lucio.lelii | 7591536a69 | |
lucio.lelii | 6b690caf56 | |
lucio.lelii | 288e8d4254 | |
lucio.lelii | b68d30cd53 | |
lucio.lelii | 7df7afecd3 | |
lucio.lelii | 1e916b21b6 | |
lucio.lelii | 56e01e91f8 | |
lucio.lelii | 94cb6e4cd3 | |
Roberto Cirillo | 5760a44220 | |
lucio.lelii | cbb77864c5 | |
user1 | effbb513a7 | |
user1 | 953cec03ee | |
user1 | 0d499d6c88 | |
user1 | 79f755dc13 | |
user1 | 8b494440af | |
user1 | d57647a714 | |
Fabio Sinibaldi | cb57512174 | |
Lucio Lelii | 2732b05426 | |
Lucio Lelii | 432859d9bb | |
Lucio Lelii | dcf1a614b4 | |
Lucio Lelii | 84cec8aa76 | |
Lucio Lelii | 52df23f2a9 | |
Lucio Lelii | ce8a1e744f | |
Lucio Lelii | 70ae49e28d | |
Lucio Lelii | f2742ce0e0 | |
Lucio Lelii | 7ed01ecc4e | |
Lucio Lelii | 1db74cc4df | |
Lucio Lelii | aae84a27d6 | |
Lucio Lelii | b80f1ccb0d | |
Lucio Lelii | ea438888c8 | |
Lucio Lelii | 01b74ae117 | |
Lucio Lelii | 94d9307b4c | |
Lucio Lelii | e82d695bbf | |
Lucio Lelii | 458b8a72ea | |
Lucio Lelii | 487eae33e2 | |
Lucio Lelii | 08351b2005 | |
Lucio Lelii | 4c13f4098e | |
lucio | 6e69de91d0 | |
lucio | 62fe5a77a0 | |
lucio | acbd780dff | |
lucio | a7ee9afb76 | |
lucio | 9e3b5f08e0 | |
lucio | 133d71f14f | |
Lucio Lelii | 9d895f0adf | |
lucio | 177888e1b4 | |
lucio | 868eadfdaa | |
lucio | 6c9aaa9489 | |
lucio | 774e2b4bfb | |
lucio | fae5173b17 | |
lucio | ddbac93245 | |
lucio | 8a84c93c18 | |
lucio | 2033af4572 | |
lucio | 0711d8a702 | |
lucio | b9d62994f9 | |
lucio | 8f725d46c0 | |
lucio | eb3daa0a26 | |
lucio | e08984af23 | |
lucio | 067f487f8b | |
lucio | df1956c08d | |
Lucio Lelii | 4ebc3ce222 | |
Lucio Lelii | abc2e16cde | |
Lucio Lelii | 0311d9782d | |
lucio | 1bcaa47d48 | |
lucio | 0f645fdde7 | |
lucio | 8ac4752ca7 | |
lucio | a4dc3cff54 | |
lucio | de91f86daf | |
lucio | 188d11ff70 | |
lucio | c1ab8333b8 | |
lucio | 67fe556a4f | |
lucio | 2dc02aa194 | |
lucio | 4802a0542e | |
lucio | 0f156c6637 | |
lucio | 0508aa0e3a | |
lucio | 18cba6c067 |
|
@ -13,15 +13,15 @@
|
|||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
|
@ -35,5 +35,6 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
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.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
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.enablePreviewFeatures=disabled
|
||||
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.source=1.8
|
||||
|
|
|
@ -1,16 +1,226 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-module deploy-name="storagehub">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<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="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</wb-module>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</project-modules>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
# 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
|
|
@ -0,0 +1,26 @@
|
|||
# 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.1
|
||||
#European Union Public Licence V.1.2
|
||||
|
||||
##*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
|
||||
copyright notice for the Original Work:
|
||||
|
||||
**Licensed under the EUPL V.1.1**
|
||||
**Licensed under the EUPL V.1.2**
|
||||
|
||||
or has expressed by any other mean his willingness to license under the EUPL.
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
<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>
|
|
@ -1,32 +0,0 @@
|
|||
<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,7 +1,8 @@
|
|||
<application mode='online'>
|
||||
<name>StorageHub</name>
|
||||
<group>DataAccess</group>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<version>1.4.2</version>
|
||||
<description>Storage Hub webapp</description>
|
||||
<local-persistence location='target' />
|
||||
<exclude>/workspace/api-docs/*</exclude>
|
||||
</application>
|
|
@ -0,0 +1,24 @@
|
|||
<?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>
|
282
pom.xml
282
pom.xml
|
@ -1,53 +1,44 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<parent>
|
||||
<artifactId>maven-parent</artifactId>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<version>1.1.0</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.gcube.data.access</groupId>
|
||||
<artifactId>storagehub</artifactId>
|
||||
<version>1.0.8</version>
|
||||
<version>1.4.2</version>
|
||||
<name>storagehub</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection>
|
||||
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
|
||||
<url>https://code-repo.d4science.org/gCubeSystem/storagehub</url>
|
||||
</scm>
|
||||
|
||||
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
|
||||
<jackrabbit.version>2.16.0</jackrabbit.version>
|
||||
<jackrabbit.version>2.20.2</jackrabbit.version>
|
||||
<jackson.version>2.8.11</jackson.version>
|
||||
<slf4j.version>1.7.4</slf4j.version>
|
||||
<tomcat.version>7.0.40</tomcat.version>
|
||||
<jetty.version>6.1.26</jetty.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>
|
||||
<description>REST web service for Jackrabbit</description>
|
||||
<warname>storagehub</warname>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<enunciate.version>2.14.0</enunciate.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.gcube.distribution</groupId>
|
||||
<artifactId>maven-smartgears-bom</artifactId>
|
||||
<version>LATEST</version>
|
||||
<artifactId>gcube-smartgears-bom</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
@ -58,82 +49,85 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-smartgears</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-smartgears-app</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>authorization-control-library</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||
<version>[1.0.0,2.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>common-authorization</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-encryption</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-scope-maps</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-scope</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>common-encryption</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>storagehub-model</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.data.access</groupId>
|
||||
<artifactId>storagehub-script-utils</artifactId>
|
||||
<version>[1.0.0, 2.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>5.5.13.1</version>
|
||||
<version>5.5.13.2</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>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.62</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
<artifactId>gxJRS</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JCR dependencies -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.jcr</groupId>
|
||||
<artifactId>jcr</artifactId>
|
||||
|
@ -142,7 +136,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.jackrabbit</groupId>
|
||||
<artifactId>jackrabbit-api</artifactId>
|
||||
<version>${jackrabbit.version}</version>
|
||||
<version>2.19.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jackrabbit</groupId>
|
||||
|
@ -154,139 +148,159 @@
|
|||
<artifactId>jackrabbit-jcr-server</artifactId>
|
||||
<version>${jackrabbit.version}</version>
|
||||
</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 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-parsers</artifactId>
|
||||
<version>1.21</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
<version>1.21</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- jersey -->
|
||||
<!-- https://mvnrepository.com/artifact/net.bull.javamelody/javamelody-core -->
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<groupId>net.bull.javamelody</groupId>
|
||||
<artifactId>javamelody-core</artifactId>
|
||||
<version>1.82.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet</artifactId>
|
||||
<version>2.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
|
||||
<artifactId>jersey-gf-cdi</artifactId>
|
||||
<version>2.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>javax.transaction-api</artifactId>
|
||||
<version>1.2</version>
|
||||
<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>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- weld -->
|
||||
<!-- 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>1.1</version>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet-core</artifactId>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.inject</groupId>
|
||||
<artifactId>jersey-hk2</artifactId>
|
||||
<version>2.30.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-server</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.ext.cdi</groupId>
|
||||
<artifactId>jersey-cdi1x</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.ext.cdi</groupId>
|
||||
<artifactId>jersey-cdi1x-servlet</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.servlet</groupId>
|
||||
<artifactId>weld-servlet</artifactId>
|
||||
<version>2.2.10.Final</version>
|
||||
<artifactId>weld-servlet-core</artifactId>
|
||||
<version>3.1.0.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
|
||||
<dependency>
|
||||
<groupId>org.jboss</groupId>
|
||||
<artifactId>jandex</artifactId>
|
||||
<version>1.2.2.Final</version>
|
||||
<version>2.2.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||
<artifactId>jackson-jaxrs-json-provider</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
<version>2.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-multipart</artifactId>
|
||||
<version>2.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.1-901.jdbc4</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Storage dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.gcube.contentmanagement</groupId>
|
||||
<artifactId>storage-manager-core</artifactId>
|
||||
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.contentmanagement</groupId>
|
||||
<artifactId>storage-manager-wrapper</artifactId>
|
||||
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
|
||||
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.17</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.tukaani</groupId>
|
||||
<artifactId>xz</artifactId>
|
||||
<version>1.5</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||
<artifactId>jersey-test-framework-provider-simple</artifactId>
|
||||
<version>2.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
|
@ -299,7 +313,6 @@
|
|||
<version>10.8.2.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.jeeunit</groupId>
|
||||
<artifactId>jeeunit</artifactId>
|
||||
|
@ -312,21 +325,29 @@
|
|||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.0.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.10</version>
|
||||
<scope>test</scope>
|
||||
<groupId>com.vlkan.rfos</groupId>
|
||||
<artifactId>rotating-fos</artifactId>
|
||||
<version>0.9.2</version>
|
||||
</dependency>
|
||||
<!-- 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>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
|
@ -334,14 +355,11 @@
|
|||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.se</groupId>
|
||||
<artifactId>weld-se</artifactId>
|
||||
|
@ -354,24 +372,19 @@
|
|||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework</groupId>
|
||||
<artifactId>jersey-test-framework-core</artifactId>
|
||||
<version>2.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
|
||||
<version>2.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${artifactId}</finalName>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -385,7 +398,6 @@
|
|||
<pluginExecutionFilter>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
|
||||
<versionRange>[1.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
|
@ -403,7 +415,7 @@
|
|||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<version>1.14.0</version>
|
||||
<configuration>
|
||||
<complianceLevel>1.8</complianceLevel>
|
||||
<source>1.8</source>
|
||||
|
@ -433,7 +445,6 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
|
@ -454,32 +465,53 @@
|
|||
<resources>
|
||||
<resource>
|
||||
<directory>${distroDirectory}</directory>
|
||||
<filtering>true</filtering>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Enunciate Maven plugin -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>descriptor.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-maven-plugin</artifactId>
|
||||
<version>${enunciate.version}</version>
|
||||
<configuration></configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>servicearchive</id>
|
||||
<phase>install</phase>
|
||||
<id>assemble</id>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
<goal>assemble</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Copy Enunciate Documentation from your-application/docs to your-application.war -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-enunciate-docs</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</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>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
25
profile.xml
25
profile.xml
|
@ -1,25 +0,0 @@
|
|||
<?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,34 +1,39 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import org.apache.jackrabbit.api.security.user.Group;
|
||||
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.Privilege;
|
||||
|
||||
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.commons.jackrabbit.authorization.AccessControlUtils;
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.apache.jackrabbit.api.security.user.Group;
|
||||
import org.apache.jackrabbit.api.security.user.UserManager;
|
||||
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.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
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.SharedFolder;
|
||||
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||
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;
|
||||
|
||||
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
|
||||
public class AuthorizationChecker {
|
||||
|
||||
|
@ -37,76 +42,113 @@ public class AuthorizationChecker {
|
|||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
public void checkReadAuthorizationControl(Session session, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
||||
Node node = session.getNodeByIdentifier(id);
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
@Inject
|
||||
ACLManagerInterface aclManager;
|
||||
|
||||
public void checkReadAuthorizationControl(Session session, String userToCheck, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
||||
|
||||
Node node = session.getNodeByIdentifier(id);
|
||||
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
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==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id+": it's not a valid StorageHub node");
|
||||
|
||||
//checking if the item is in the owner trash folder
|
||||
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(login)) return;
|
||||
|
||||
//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
|
||||
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;
|
||||
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 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);
|
||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" 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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
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");
|
||||
//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()))
|
||||
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's a protected folder");
|
||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId()+": it's a protected folder");
|
||||
|
||||
if (item.isShared()) {
|
||||
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||
Authorizable UserAuthorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(login);
|
||||
|
||||
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
||||
List<ACL> acls = aclManager.get(item, session);
|
||||
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
||||
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
|
||||
//put it in a different method
|
||||
for (AccessControlEntry entry: entries) {
|
||||
Authorizable authorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(entry.getPrincipal());
|
||||
if ((!authorizable.isGroup() && entry.getPrincipal().getName().equals(login)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
||||
for (Privilege privilege : entry.getPrivileges()){
|
||||
AccessType access = AccessType.fromValue(privilege.getName());
|
||||
if (isNewItem && access!=AccessType.READ_ONLY)
|
||||
for (ACL entry: acls) {
|
||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
||||
if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
||||
for (AccessType privilege : entry.getAccessTypes()){
|
||||
if (isNewItem && privilege!=AccessType.READ_ONLY)
|
||||
return;
|
||||
else
|
||||
if (!isNewItem &&
|
||||
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(login))))
|
||||
(privilege==AccessType.ADMINISTRATOR || privilege==AccessType.WRITE_ALL || (privilege==AccessType.WRITE_OWNER && item.getOwner().equals(userToCheck))))
|
||||
return;
|
||||
|
||||
}
|
||||
|
@ -114,72 +156,56 @@ public class AuthorizationChecker {
|
|||
}
|
||||
}
|
||||
} else
|
||||
if(item.getOwner().equals(login))
|
||||
if(item.getOwner().equals(userToCheck))
|
||||
return;
|
||||
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id);
|
||||
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId());
|
||||
}
|
||||
|
||||
//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 {
|
||||
Node node = session.getNodeByIdentifier(id);
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
|
||||
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
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
/**
|
||||
*
|
||||
* checks if {userToCheck} is an admin for {item}
|
||||
*
|
||||
*/
|
||||
public void checkAdministratorControl(Session session, String userToCheck, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
||||
|
||||
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+": it's not a valid StorageHub node");
|
||||
|
||||
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()) {
|
||||
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||
//put it in a different method
|
||||
List<ACL> acls = aclManager.get(item, session);
|
||||
|
||||
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)
|
||||
for (ACL entry: acls) {
|
||||
if (entry.getPricipal().equals(userToCheck)) {
|
||||
for (AccessType privilege : entry.getAccessTypes()){
|
||||
if (privilege==AccessType.ADMINISTRATOR)
|
||||
return;
|
||||
|
||||
}
|
||||
throw new UserNotAuthorizedException("The user "+login+" 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());
|
||||
|
||||
throw new UserNotAuthorizedException("The user "+userToCheck+" 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,7 +5,17 @@ import java.util.List;
|
|||
|
||||
public class Constants {
|
||||
|
||||
public static final String VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
|
||||
public static final String OLD_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";
|
||||
|
||||
|
@ -19,9 +29,11 @@ public class Constants {
|
|||
|
||||
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
||||
|
||||
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
public static final String HOME_VERSION_PROP = "hl:version";
|
||||
|
||||
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> FOLDERS_TO_EXLUDE = 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> 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.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
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,6 +5,7 @@ import javax.jcr.Repository;
|
|||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitRepository;
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
|
||||
@Singleton
|
||||
|
@ -12,19 +13,22 @@ public class RepositoryInitializerImpl implements RepositoryInitializer{
|
|||
|
||||
private Repository repository;
|
||||
|
||||
|
||||
@Override
|
||||
public Repository getRepository(){
|
||||
public synchronized Repository getRepository(){
|
||||
return repository;
|
||||
}
|
||||
|
||||
public RepositoryInitializerImpl() throws Exception{
|
||||
protected RepositoryInitializerImpl() throws Exception{
|
||||
InitialContext context = new InitialContext();
|
||||
Context environment = (Context) context.lookup("java:comp/env");
|
||||
repository = (Repository) environment.lookup("jcr/repository");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void shutdown() {
|
||||
((JackrabbitRepository)repository).shutdown();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
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,12 +8,16 @@ import javax.ws.rs.core.Application;
|
|||
|
||||
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
|
||||
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.Impersonable;
|
||||
import org.gcube.data.access.storagehub.services.ItemSharing;
|
||||
import org.gcube.data.access.storagehub.services.ItemsCreator;
|
||||
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.WorkspaceManager;
|
||||
import org.gcube.data.access.storagehub.services.admin.ScriptManager;
|
||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||
|
||||
@Path("workspace")
|
||||
|
@ -23,7 +27,7 @@ public class StorageHub extends Application {
|
|||
public Set<Class<?>> getClasses() {
|
||||
final Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||
// register resources and features
|
||||
classes.add(MultiPartFeature.class);
|
||||
classes.add(Impersonable.class);
|
||||
classes.add(WorkspaceManager.class);
|
||||
classes.add(ItemsManager.class);
|
||||
classes.add(ItemsCreator.class);
|
||||
|
@ -31,7 +35,12 @@ public class StorageHub extends Application {
|
|||
classes.add(ItemSharing.class);
|
||||
classes.add(UserManager.class);
|
||||
classes.add(GroupManager.class);
|
||||
classes.add(ScriptManager.class);
|
||||
classes.add(MessageManager.class);
|
||||
classes.add(MultiPartFeature.class);
|
||||
classes.add(SerializableErrorEntityTextWriter.class);
|
||||
classes.add(MyApplicationListener.class);
|
||||
classes.add(DocManager.class);
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
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,6 +1,5 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -8,12 +7,10 @@ import java.net.URL;
|
|||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
|
@ -22,39 +19,36 @@ import javax.jcr.RepositoryException;
|
|||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.Lock;
|
||||
import javax.jcr.lock.LockException;
|
||||
import javax.jcr.version.Version;
|
||||
import javax.jcr.query.Query;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.jackrabbit.util.ISO9075;
|
||||
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.Paths;
|
||||
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.items.AbstractFileItem;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||
import org.gcube.common.storagehub.model.items.ExternalLink;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||
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.types.ItemAction;
|
||||
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.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.VersionHandler;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
|
||||
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.items.builders.FolderCreationParameters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public final static String SERVICE_NAME = "home-library";
|
||||
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||
public final static String SERVICE_NAME = "home-library";
|
||||
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||
private static final String FOLDERS_TYPE = "nthl:workspaceItem";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
|
||||
|
@ -78,7 +72,7 @@ public class Utils {
|
|||
return digest;
|
||||
}
|
||||
|
||||
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
|
||||
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
|
||||
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
|
||||
}
|
||||
|
||||
|
@ -107,36 +101,82 @@ 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());
|
||||
|
||||
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.debug("getting children of node {}", parent.getIdentifier());
|
||||
|
||||
List<T> returnList = new ArrayList<T>();
|
||||
//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 search is {}",xpath);
|
||||
long start = System.currentTimeMillis();
|
||||
NodeIterator iterator = parent.getNodes();
|
||||
@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
|
||||
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>();
|
||||
|
||||
logger.trace("nodeType is {}",nodeTypeToInclude);
|
||||
int count =0;
|
||||
logger.trace("selected range is {}", range);
|
||||
Node2ItemConverter node2Item= new Node2ItemConverter();
|
||||
Set<String> duplicateId = new HashSet<String>();
|
||||
while (iterator.hasNext()){
|
||||
Node current = iterator.nextNode();
|
||||
Node current = iterator.next();
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
logger.debug("current node not excluded "+current.getName());
|
||||
logger.trace("[SEARCH] current node not excluded {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
|
||||
|
||||
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
|
||||
T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
|
||||
if (item==null) continue;
|
||||
if (item==null || (item.isTrashed() && excludeTrashed)) continue;
|
||||
returnList.add(item);
|
||||
}
|
||||
count++;
|
||||
|
||||
duplicateId.add(current.getIdentifier());
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
@ -147,83 +187,10 @@ public class Utils {
|
|||
(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 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 {
|
||||
public static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[2048];
|
||||
int readcount = 0;
|
||||
while ((readcount=in.read(buffer))!=-1) {
|
||||
|
@ -234,39 +201,16 @@ public class Utils {
|
|||
|
||||
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
|
||||
Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||
NodeIterator children = node.getNodes();
|
||||
NodeChildrenFilterIterator children = new NodeChildrenFilterIterator(node);
|
||||
|
||||
while (children.hasNext()) {
|
||||
Node child= children.nextNode();
|
||||
Node child= children.next();
|
||||
if (node2Item.checkNodeType(child, SharedFolder.class)) return true;
|
||||
if (node2Item.checkNodeType(child, FolderItem.class) && hasSharedChildren(child)) return true;
|
||||
}
|
||||
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{
|
||||
try {
|
||||
|
@ -283,7 +227,7 @@ public class Utils {
|
|||
|
||||
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
|
||||
|
||||
logger.debug("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
|
||||
logger.trace("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
|
||||
|
||||
NodeIterator ni = destination.getNodes(nameTocheck);
|
||||
int maxval = 0;
|
||||
|
@ -302,29 +246,43 @@ public class Utils {
|
|||
}
|
||||
}
|
||||
|
||||
public static Node createFolderInternally(Session ses, Node destinationNode, String name, String description, boolean hidden, String login, AccountingHandler accountingHandler) throws BackendGenericError {
|
||||
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
|
||||
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler) throws StorageHubException {
|
||||
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();
|
||||
Calendar now = Calendar.getInstance();
|
||||
item.setName(uniqueName);
|
||||
item.setTitle(uniqueName);
|
||||
item.setDescription(description);
|
||||
item.setDescription(params.getDescription());
|
||||
//TODO: item.setExternalStorage();
|
||||
//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.setLastModificationTime(now);
|
||||
item.setLastModifiedBy(login);
|
||||
item.setOwner(login);
|
||||
item.setLastModifiedBy(params.getUser());
|
||||
item.setOwner(params.getUser());
|
||||
item.setPublicItem(false);
|
||||
|
||||
//to inherit hidden property
|
||||
//item.setHidden(destinationItem.isHidden());
|
||||
|
||||
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
||||
if (accountingHandler!=null)
|
||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||
if (accountingHandler!=null) {
|
||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), null, params.getSession(), params.getUser(), destinationNode, false);
|
||||
accountingHandler.createEntryCreate(item.getTitle(), params.getSession(), newNode, params.getUser(), false);
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
|
||||
|
@ -345,12 +303,19 @@ public class Utils {
|
|||
item.setPublicItem(false);
|
||||
item.setValue(value);
|
||||
|
||||
//to inherit hidden property
|
||||
//item.setHidden(destinationItem.isHidden());
|
||||
try {
|
||||
item.setHidden(destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean());
|
||||
} catch (Throwable e) {
|
||||
item.setHidden(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
||||
if (accountingHandler!=null)
|
||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||
if (accountingHandler!=null) {
|
||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
|
||||
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
|
||||
|
@ -380,4 +345,6 @@ public class Utils {
|
|||
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), login);
|
||||
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import javax.jcr.version.VersionHistory;
|
|||
import javax.jcr.version.VersionIterator;
|
||||
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.types.NodeProperty;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -37,7 +36,7 @@ public class AccountingHandler {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
||||
|
||||
public void createReadObj(String title, Session ses, Node node, boolean saveHistory ) {
|
||||
public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -47,7 +46,7 @@ public class AccountingHandler {
|
|||
|
||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.READ.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
|
||||
|
@ -70,7 +69,26 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createFileUpdated(String title, Session ses, Node node, boolean saveHistory ) {
|
||||
public void createEntryCreate(String title, Session ses, Node node, String login, 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 {
|
||||
|
||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -80,7 +98,7 @@ public class AccountingHandler {
|
|||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
|
||||
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
|
||||
|
@ -107,17 +125,17 @@ public class AccountingHandler {
|
|||
}
|
||||
|
||||
|
||||
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, Node node, boolean saveHistory ) {
|
||||
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
|
||||
try {
|
||||
Node directoryNode = node.getParent();
|
||||
|
||||
if (!directoryNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
directoryNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
||||
|
||||
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
parentNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
||||
}
|
||||
|
||||
Node accountingNodeParent = directoryNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.ADD.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
accountingNode.setProperty(ITEM_TYPE, itemType);
|
||||
|
@ -130,7 +148,7 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, Node parentNode, boolean saveHistory ) {
|
||||
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -139,7 +157,7 @@ public class AccountingHandler {
|
|||
|
||||
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.REMOVAL.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
accountingNode.setProperty(ITEM_TYPE, itemType);
|
||||
|
@ -152,7 +170,7 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, String login, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -161,7 +179,7 @@ public class AccountingHandler {
|
|||
|
||||
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
accountingNode.setProperty(MEMBERS, users.toArray(new String[users.size()]));
|
||||
|
@ -172,7 +190,7 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createUnshareFolder(String title, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||
public void createUnshareFolder(String title, Session ses, String user, Node sharedNode, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -180,8 +198,8 @@ public class AccountingHandler {
|
|||
}
|
||||
|
||||
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UNSHARE.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, user);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
|
||||
|
@ -191,7 +209,7 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createRename(String oldTitle, String newTitle, Node node, Session ses, boolean saveHistory ) {
|
||||
public void createRename(String oldTitle, String newTitle, Node node, String login, Session ses, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -200,7 +218,7 @@ public class AccountingHandler {
|
|||
|
||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.RENAMING.getNodeTypeDefinition());
|
||||
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(OLD_ITEM_NAME, oldTitle);
|
||||
accountingNode.setProperty(NEW_ITEM_NAME, newTitle);
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.items.RootItem;
|
||||
import org.reflections.Reflections;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -24,31 +27,37 @@ public class ClassHandler {
|
|||
|
||||
private Reflections reflection = new Reflections();
|
||||
|
||||
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
|
||||
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
|
||||
private List<String> deprecatedNode = Arrays.asList("nthl:query", "nthl:aquamapsItem", "nthl:timeSeriesItem", "nthl:report", "nthl:reportTemplate", "nthl:workflowReport",
|
||||
"nthl:workflowTemplate", "nthl:gCubeMetadata", "nthl:gCubeDocument", "nthl:gCubeDocumentLink", "nthl:gCubeImageDocumentLink", "nthl:gCubePDFDocumentLink",
|
||||
"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() {
|
||||
|
||||
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
||||
for (Class<?> clazz: classesAnnotated ){
|
||||
if (Item.class.isAssignableFrom(clazz)) {
|
||||
if (RootItem.class.isAssignableFrom(clazz)) {
|
||||
String value = clazz.getAnnotation(RootNode.class).value();
|
||||
log.debug("loading class {} with value {} ", clazz, value );
|
||||
classMap.put(value, (Class<? extends Item>) clazz);
|
||||
typeMap.put((Class<? extends Item>) clazz, value);
|
||||
classMap.put(value, (Class<? extends RootItem>) clazz);
|
||||
typeMap.put((Class<? extends RootItem>) clazz, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Class<? extends Item> get(String nodeType){
|
||||
public Class<? extends RootItem> get(String nodeType){
|
||||
if (classMap.containsKey(nodeType)) return classMap.get(nodeType);
|
||||
else return Item.class;
|
||||
if (deprecatedNode.contains(nodeType)) return Item.class;
|
||||
return null;
|
||||
//throw new RuntimeException("mapping not found for nodetype "+ nodeType);
|
||||
}
|
||||
|
||||
public String getNodeType(Class<? extends Item> clazz){
|
||||
public String getNodeType(Class<? extends RootItem> clazz){
|
||||
if (typeMap.containsKey(clazz)) return typeMap.get(clazz);
|
||||
throw new RuntimeException("mapping not found for nodetype "+ clazz.getSimpleName());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
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,51 +0,0 @@
|
|||
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,35 +1,45 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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.Singleton;
|
||||
import javax.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
import javax.jcr.version.Version;
|
||||
|
||||
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.Paths;
|
||||
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.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.Item;
|
||||
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.contentmanagement.blobstorage.service.IClient;
|
||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
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.LoggerFactory;
|
||||
|
||||
|
@ -38,65 +48,128 @@ public class TrashHandler {
|
|||
|
||||
private static Logger log = LoggerFactory.getLogger(TrashHandler.class);
|
||||
|
||||
@Inject
|
||||
VersionHandler versionHandler;
|
||||
ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
VersionHandler versionHandler;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
||||
@Inject
|
||||
Item2NodeConverter item2Node;
|
||||
|
||||
@Inject
|
||||
StorageBackendHandler storageHandler;
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject FolderPluginHandler managerHandler;
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderHandler;
|
||||
|
||||
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
|
||||
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
||||
for (Item item: itemsToDelete) {
|
||||
removeNodesInternally(ses, item);
|
||||
removeNodesInternally(ses, item, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNodesInternally(Session ses, Item itemToDelete) throws RepositoryException, StorageHubException {
|
||||
public void removeOnlyNodesContent(Session ses, List<Item> itemsToDelete) 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 {
|
||||
Set<String> contentIdsToDelete = new HashSet<>();
|
||||
|
||||
Node nodeToDelete = ses.getNodeByIdentifier(itemToDelete.getId());
|
||||
Set<AbstractFileItem> itemsToDelete = new HashSet<>();
|
||||
Node nodeToDelete = (Node) itemToDelete.getRelatedNode();
|
||||
|
||||
if (itemToDelete instanceof TrashItem) {
|
||||
List<Item> trashChildren = Utils.getItemList(nodeToDelete, Excludes.GET_ONLY_CONTENT, null, true, null);
|
||||
for (Item itemContentToRetrieve: trashChildren)
|
||||
Utils.getAllContentIds(ses, contentIdsToDelete, itemContentToRetrieve, versionHandler);
|
||||
} else {
|
||||
Utils.getAllContentIds(ses, contentIdsToDelete, itemToDelete, versionHandler);
|
||||
}
|
||||
nodeToDelete.remove();
|
||||
retrieveItemsToDelete(itemsToDelete, itemContentToRetrieve);
|
||||
} else
|
||||
retrieveItemsToDelete(itemsToDelete, itemToDelete);
|
||||
|
||||
log.debug("content ids to remove are {}",contentIdsToDelete);
|
||||
if (!onlyContent)
|
||||
nodeToDelete.remove();
|
||||
|
||||
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() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (String id: contentIdsToDelete) {
|
||||
for (ContentPair cp: contentToDelete ) {
|
||||
try {
|
||||
storageHandler.delete(id);
|
||||
log.debug("file with id {} correctly removed on storage",id);
|
||||
cp.getStorageBackend().onDelete(cp.getContent());
|
||||
log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName());
|
||||
}catch(Throwable t) {
|
||||
log.warn("error removing file on storage with id {}",id, t);
|
||||
log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
new Thread(deleteFromStorageRunnable).start();
|
||||
|
||||
ses.save();
|
||||
executor.execute(deleteFromStorageRunnable);
|
||||
if (!onlyContent)
|
||||
ses.save();
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException("the selected node or his parent is locked", e);
|
||||
}catch (Exception e) {
|
||||
|
@ -104,20 +177,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());
|
||||
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 {
|
||||
|
||||
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
|
||||
|
||||
log.debug("preparing thrash item");
|
||||
|
||||
TrashItem trashItem = new TrashItem();
|
||||
trashItem.setDeletedBy(AuthorizationProvider.instance.get().getClient().getId());
|
||||
trashItem.setDeletedBy(login);
|
||||
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
|
||||
Calendar now = Calendar.getInstance();
|
||||
trashItem.setDeletedTime(now);
|
||||
|
@ -131,7 +204,7 @@ public class TrashHandler {
|
|||
trashItem.setName(item.getId());
|
||||
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
|
||||
|
||||
trashItem.setOwner(item.getOwner());
|
||||
trashItem.setOwner(login);
|
||||
trashItem.setLastModificationTime(item.getLastModificationTime());
|
||||
trashItem.setLastModifiedBy(item.getLastModifiedBy());
|
||||
|
||||
|
@ -161,7 +234,7 @@ public class TrashHandler {
|
|||
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
||||
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
|
||||
}
|
||||
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, ses.getNodeByIdentifier(item.getParentId()), true);
|
||||
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true);
|
||||
}catch(Throwable t) {
|
||||
log.error("error exceuting move to trash",t);
|
||||
throw new BackendGenericError(t);
|
||||
|
@ -172,27 +245,69 @@ public class TrashHandler {
|
|||
|
||||
}
|
||||
|
||||
public String restoreItem(Session ses, TrashItem item) throws RepositoryException, BackendGenericError, UserNotAuthorizedException{
|
||||
log.debug("restoring node from trash");
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
public String restoreItem(Session ses, TrashItem item, FolderItem destination, String login) throws RepositoryException, StorageHubException, BackendGenericError{
|
||||
log.debug("restoring node from trash with user ");
|
||||
//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 );
|
||||
|
||||
ses.getWorkspace().getLockManager().lock(originalParent.getPath(), true, true, 0,login);
|
||||
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");
|
||||
Node destinationNode= null;
|
||||
if (destination==null) {
|
||||
boolean originalParentExists = true;
|
||||
boolean originalParentTrashed = false;
|
||||
Node originalParent = null;
|
||||
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;
|
||||
}
|
||||
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();
|
||||
|
||||
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());
|
||||
}
|
||||
return ses.getNode(newNodePath).getIdentifier();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.Set;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
|
@ -27,9 +28,13 @@ import org.gcube.common.storagehub.model.items.FolderItem;
|
|||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||
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.PathUtil;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
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.LoggerFactory;
|
||||
|
||||
|
@ -48,25 +53,38 @@ public class UnshareHandler {
|
|||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
Item2NodeConverter item2Node;
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
SharedFolder sharedItem =(SharedFolder) item;
|
||||
|
||||
Set<String> usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getMap().keySet());
|
||||
usersInSharedFolder.removeAll(users);
|
||||
|
||||
if (users==null || users.size()==0)
|
||||
return unshareAll(login, ses, sharedItem);
|
||||
return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
|
||||
|
||||
if (usersInSharedFolder.size()<=1) {
|
||||
if (users.size()==1 && users.contains(login))
|
||||
return unshareAll(sharedItem.getOwner(), ses , sharedItem);
|
||||
else return unshareAll(login, ses, sharedItem);
|
||||
return unshareAll(sharedItem.getOwner(), ses , sharedItem, withCopyOnUnshare);
|
||||
else return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -85,7 +103,8 @@ 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");
|
||||
|
||||
if (!login.equals(item.getOwner()))
|
||||
|
@ -99,37 +118,66 @@ public class UnshareHandler {
|
|||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
||||
Node unsharedNode;
|
||||
String unsharedNodeIdentifier =null;
|
||||
try {
|
||||
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);
|
||||
|
||||
Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||
adminNode.removeShare();
|
||||
if (withCopyCreation) {
|
||||
|
||||
unsharedNode = createUnsharedFolder(ses, parentNode, directoryName, item.getDescription(), login);
|
||||
Node sharedOwnerNode = null;
|
||||
NodeIterator it = sharedItemNode.getSharedSet();
|
||||
while(it.hasNext()) {
|
||||
Node node = it.nextNode();
|
||||
|
||||
List<Item> itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null);
|
||||
log.info("[UNSHARE] checking node {} starts with {} ",node.getPath(),pathUtil.getHome(login).toPath());
|
||||
|
||||
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()));
|
||||
if (node.getPath().startsWith(pathUtil.getHome(login).toPath())) {
|
||||
sharedOwnerNode =node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath());
|
||||
}
|
||||
|
||||
sharedItemNode.removeSharedSet();
|
||||
ses.save();
|
||||
log.debug("all the users have been removed, the folder is totally unshared");
|
||||
return unsharedNode.getIdentifier();
|
||||
|
||||
return unsharedNodeIdentifier;
|
||||
|
||||
}
|
||||
|
||||
|
@ -137,16 +185,29 @@ public class UnshareHandler {
|
|||
|
||||
|
||||
private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{
|
||||
|
||||
log.info("unshare caller");
|
||||
if (login.equals(item.getOwner()))
|
||||
throw new InvalidCallParameters("the caller is the owner, the folder cannot be unshared");
|
||||
|
||||
if (item.getUsers().getMap().get(login)==null)
|
||||
throw new InvalidCallParameters("the folder is not shared with user "+login);
|
||||
|
||||
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
|
||||
if (item.getUsers().getMap().get(login)!=null) {
|
||||
Node usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
|
||||
usersNode.remove();
|
||||
Node newUsersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
|
||||
|
||||
String parentId = removeSharingForUser(login, ses, item);
|
||||
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());
|
||||
}});
|
||||
}
|
||||
|
||||
Node shareNode = getUserSharingNode(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();
|
||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||
|
@ -162,20 +223,12 @@ public class UnshareHandler {
|
|||
if (entryToDelete!=null)
|
||||
acls.removeAccessControlEntry(entryToDelete);
|
||||
|
||||
log.debug("removed Access control entry for user {}",login);
|
||||
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||
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);
|
||||
|
||||
log.debug("removed Access control entry for user {}",login);
|
||||
|
||||
accountingHandler.createUnshareFolder(item.getTitle(), ses, login, sharedFolderNode, false);
|
||||
|
||||
ses.save();
|
||||
|
||||
return parentId;
|
||||
|
@ -183,10 +236,9 @@ public class UnshareHandler {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private String unsharePartial(Set<String> usersToUnshare, String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException {
|
||||
authChecker.checkAdministratorControl(ses, (SharedFolder)item);
|
||||
log.info("unshare partial");
|
||||
authChecker.checkAdministratorControl(ses, login, (SharedFolder)item);
|
||||
if (usersToUnshare.contains(item.getOwner()))
|
||||
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare owner");
|
||||
|
||||
|
@ -196,7 +248,11 @@ public class UnshareHandler {
|
|||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||
|
||||
for (String user : usersToUnshare) {
|
||||
removeSharingForUser(user, ses, item);
|
||||
Node userShareNode = getUserSharingNode(user, ses, item);
|
||||
|
||||
//not returning an error to correct all the old ACL
|
||||
if (userShareNode != null)
|
||||
userShareNode.removeShare();
|
||||
|
||||
AccessControlEntry entryToDelete= null;
|
||||
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
||||
|
@ -226,6 +282,10 @@ public class UnshareHandler {
|
|||
|
||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||
|
||||
for (String user: usersToUnshare) {
|
||||
accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), ses, user, sharedItemNode, false);
|
||||
}
|
||||
|
||||
ses.save();
|
||||
|
||||
return item.getId();
|
||||
|
@ -233,18 +293,34 @@ public class UnshareHandler {
|
|||
}
|
||||
|
||||
|
||||
private String removeSharingForUser(String user, Session ses, SharedFolder item) throws RepositoryException {
|
||||
String userDirPath = (String)item.getUsers().getMap().get(user);
|
||||
if (userDirPath==null) return null;
|
||||
String[] splitString = userDirPath.split("/");
|
||||
String parentDirectoryId = splitString[0];
|
||||
String directoryName = splitString[1];
|
||||
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||
Node userNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||
userNode.removeShare();
|
||||
accountingHandler.createUnshareFolder(directoryName, ses, parentNode, false);
|
||||
log.debug("directory removed for user {}",user);
|
||||
return parentDirectoryId;
|
||||
private Node getUserSharingNode(String user, Session ses, SharedFolder item) throws RepositoryException {
|
||||
Node shareNode = null;
|
||||
try {
|
||||
String userDirPath = (String)item.getUsers().getMap().get(user);
|
||||
if (userDirPath==null) return null;
|
||||
String[] splitString = userDirPath.split("/");
|
||||
String parentDirectoryId = splitString[0];
|
||||
String directoryName = splitString[1];
|
||||
Node parentNode = null;
|
||||
parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||
shareNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||
}catch (Throwable e) {
|
||||
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,59 +0,0 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
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);
|
||||
|
||||
public void makeVersionableContent(Node node, Session session){
|
||||
public void makeVersionableContent(Node node){
|
||||
try {
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
contentNode.addMixin(JcrConstants.MIX_VERSIONABLE);
|
||||
|
@ -31,8 +31,9 @@ public class VersionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void checkinContentNode(Node node, Session session){
|
||||
public void checkinContentNode(Node node){
|
||||
try {
|
||||
Session session = node.getSession();
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||
versionManager.checkin(contentNode.getPath());
|
||||
|
@ -41,8 +42,9 @@ public class VersionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void checkoutContentNode(Node node, Session session){
|
||||
public void checkoutContentNode(Node node){
|
||||
try {
|
||||
Session session = node.getSession();
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||
versionManager.checkout(contentNode.getPath());
|
||||
|
@ -51,8 +53,9 @@ public class VersionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public List<Version> getContentVersionHistory(Node node, Session session) {
|
||||
public List<Version> getContentVersionHistory(Node node) {
|
||||
try {
|
||||
Session session = node.getSession();
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||
VersionHistory history = versionManager.getVersionHistory(contentNode.getPath());
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.gcube.data.access.storagehub.handlers.content;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.apache.tika.metadata.Metadata;
|
|||
import org.apache.tika.parser.ParseContext;
|
||||
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
|
||||
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.nodes.Content;
|
||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||
|
|
|
@ -8,6 +8,8 @@ import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
|||
import org.gcube.common.storagehub.model.items.PDFFileItem;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PDFContent;
|
||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.itextpdf.text.pdf.PdfReader;
|
||||
|
||||
|
@ -22,20 +24,23 @@ public class PdfHandler implements ContentHandler {
|
|||
|
||||
PDFContent content = new PDFContent();
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class);
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
|
||||
PdfReader reader = new PdfReader(is);
|
||||
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
||||
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
||||
HashMap<String, String> fileInfo = reader.getInfo();
|
||||
content.setAuthor(fileInfo.containsKey(AUTHOR)?fileInfo.get(AUTHOR):"n/a");
|
||||
content.setProducer(fileInfo.containsKey(PRODUCER)?fileInfo.get(PRODUCER):"n/a");
|
||||
content.setTitle(fileInfo.containsKey(TITLE)?fileInfo.get(TITLE):"n/a");
|
||||
try {
|
||||
PdfReader reader = new PdfReader(is);
|
||||
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
||||
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
||||
HashMap<String, String> fileInfo = reader.getInfo();
|
||||
content.setAuthor(fileInfo.containsKey(AUTHOR)?fileInfo.get(AUTHOR):"n/a");
|
||||
content.setProducer(fileInfo.containsKey(PRODUCER)?fileInfo.get(PRODUCER):"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);
|
||||
}
|
||||
|
||||
@Override
|
||||
} @Override
|
||||
public PDFContent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
package org.gcube.data.access.storagehub.handlers.items;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
|
@ -31,11 +31,16 @@ import org.gcube.common.storagehub.model.annotations.ListNodes;
|
|||
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||
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.FolderItem;
|
||||
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.NodeProperty;
|
||||
import org.gcube.data.access.storagehub.NodeChildrenFilterIterator;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -44,7 +49,7 @@ public class Item2NodeConverter {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
|
||||
|
||||
public <T extends Item> Node getNode(Node parentNode, T item){
|
||||
public <T extends RootItem> Node getNode(Node parentNode, T item){
|
||||
try {
|
||||
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
|
||||
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
||||
|
@ -56,7 +61,7 @@ public class Item2NodeConverter {
|
|||
field.setAccessible(true);
|
||||
try{
|
||||
//Class<?> returnType = field.getType();
|
||||
logger.debug("creating node - added field {}",field.getName());
|
||||
logger.trace("creating node - added field {}",field.getName());
|
||||
Values values = getObjectValue(field.getType(), field.get(item));
|
||||
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||
else newNode.setProperty(attribute.value(), values.getValue());
|
||||
|
@ -67,14 +72,14 @@ public class Item2NodeConverter {
|
|||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||
if (nodeAttribute.isReadOnly()) continue;
|
||||
String nodeName = nodeAttribute.value();
|
||||
logger.debug("retrieving field node "+field.getName());
|
||||
logger.trace("retrieving field node "+field.getName());
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Object obj = field.get(item);
|
||||
if (obj!=null)
|
||||
iterateItemNodeAttributeFields(obj, newNode, nodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value",e);
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
|
||||
|
||||
|
@ -113,7 +118,7 @@ public class Item2NodeConverter {
|
|||
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||
else newNode.setProperty(attribute.value(), values.getValue());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value",e);
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
||||
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
||||
|
@ -125,11 +130,11 @@ public class Item2NodeConverter {
|
|||
if (values.isMulti()) newNode.setProperty(entry.getKey(), values.getValues());
|
||||
else newNode.setProperty(entry.getKey(), values.getValue());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value",e);
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
|
||||
} else if (field.isAnnotationPresent(ListNodes.class)){
|
||||
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
||||
logger.trace("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
||||
field.setAccessible(true);
|
||||
List<Object> toSetList = (List<Object>) field.get(object);
|
||||
|
||||
|
@ -145,7 +150,7 @@ public class Item2NodeConverter {
|
|||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
private Values getObjectValue(Class returnType, Object value) throws Exception{
|
||||
public static Values getObjectValue(Class returnType, Object value) throws Exception{
|
||||
|
||||
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
|
||||
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
|
||||
|
@ -204,7 +209,7 @@ public class Item2NodeConverter {
|
|||
else contentNode.setProperty(attribute.value(), values.getValue());
|
||||
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value for attribute "+attribute.value(),e);
|
||||
logger.debug("error setting value for attribute "+attribute.value(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -216,11 +221,41 @@ 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){
|
||||
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
|
||||
|
||||
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
||||
|
||||
Node metadataNode;
|
||||
|
@ -246,7 +281,7 @@ public class Item2NodeConverter {
|
|||
}
|
||||
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value",e);
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,400 @@
|
|||
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,4 +1,4 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
package org.gcube.data.access.storagehub.handlers.items;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
|
@ -21,21 +21,27 @@ import javax.jcr.Property;
|
|||
import javax.jcr.PropertyIterator;
|
||||
import javax.jcr.PropertyType;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.Value;
|
||||
import javax.jcr.version.Version;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
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.AttributeRootNode;
|
||||
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
||||
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||
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.RootItem;
|
||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
||||
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.Reflections;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
@ -43,34 +49,55 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class Node2ItemConverter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
|
||||
|
||||
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{
|
||||
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
|
||||
|
||||
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||
if (classToHandle==null) return null;
|
||||
if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
|
||||
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{
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||
/*Node nodeToRetrieve= node;
|
||||
if (SharedFolder.class.isAssignableFrom(classToHandle)) {
|
||||
NodeIterator it= node.getSharedSet();
|
||||
while (it.hasNext()) {
|
||||
Node sharedNode = it.nextNode();
|
||||
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath().toPath())) {
|
||||
nodeToRetrieve = sharedNode;
|
||||
}
|
||||
if (classToHandle==null) return null;
|
||||
T item = retrieveItem(node, excludes, classToHandle);
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
return retrieveItem(node, excludes, classToHandle);
|
||||
public Content getContentFromVersion(Version node) throws RepositoryException, BackendGenericError{
|
||||
Content content = new Content();
|
||||
setGenericFields(node.getFrozenNode(), Content.class, null, content);
|
||||
return content;
|
||||
}
|
||||
|
||||
public Message getMessageItem(Node node) throws RepositoryException{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,79 +108,99 @@ public class Node2ItemConverter {
|
|||
}catch (Exception e) {
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
item.setId(node.getIdentifier());
|
||||
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
|
||||
|
||||
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
|
||||
try {
|
||||
item.setShared(SharedFolder.class.isInstance(item) ||
|
||||
hasTypedParent(node, SharedFolder.class));
|
||||
}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.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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
setRootItemCommonFields(node, excludes, classToHandle, item);
|
||||
|
||||
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{
|
||||
item.setParentId(node.getParent().getIdentifier());
|
||||
item.setParentPath(node.getParent().getPath());
|
||||
instance.setParentId(node.getParent().getIdentifier());
|
||||
instance.setParentPath(node.getParent().getPath());
|
||||
}catch (Throwable e) {
|
||||
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)){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Class<?> returnType = field.getType();
|
||||
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||
logger.debug("retrieve item - added field {}",field.getName());
|
||||
field.set(instance, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||
logger.trace("retrieve item - added field {}",field.getName());
|
||||
}catch(PathNotFoundException e){
|
||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value for property {} ",attribute.value());
|
||||
logger.debug("error setting value for property {} ",attribute.value());
|
||||
}
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
|
||||
//for now it excludes only first level node
|
||||
if (excludes!=null && excludes.contains(fieldNodeName)) continue;
|
||||
//for now it excludes only first level node
|
||||
logger.trace("retrieving field node "+field.getName());
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Node fieldNode = node.getNode(fieldNodeName);
|
||||
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
|
||||
field.set(item, iterateNodeAttributeFields(field.getType(), fieldNode));
|
||||
field.set(instance, iterateNodeAttributeFields(field.getType(), fieldNode));
|
||||
}catch(PathNotFoundException e){
|
||||
logger.trace("the current node dosn't contain {} node",fieldNodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value",e);
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
||||
|
@ -163,13 +210,12 @@ public class Node2ItemConverter {
|
|||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
@SuppressWarnings("rawtypes")
|
||||
Class returnType = field.getType();
|
||||
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||
}catch(PathNotFoundException e){
|
||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value {}",e.getMessage());
|
||||
logger.debug("error setting value {}",e.getMessage());
|
||||
}
|
||||
} 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());
|
||||
|
@ -188,7 +234,7 @@ public class Node2ItemConverter {
|
|||
}catch(PathNotFoundException e){
|
||||
logger.warn("the property {} is not mapped",prop.getName());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value {}",e.getMessage());
|
||||
logger.debug("error setting value {}",e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +298,7 @@ public class Node2ItemConverter {
|
|||
return obj;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
||||
if (returnType.equals(String.class)) return prop.getString();
|
||||
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
|
||||
|
@ -317,10 +363,11 @@ public class Node2ItemConverter {
|
|||
return values;
|
||||
}
|
||||
|
||||
//Checks if a node is a subtype of classToCompare
|
||||
public boolean checkNodeType(Node node, Class<? extends Item> classToCompare) throws BackendGenericError{
|
||||
try {
|
||||
|
||||
logger.info("class from nodetype is {} and class to compare is {}",ClassHandler.instance().get(node.getPrimaryNodeType().getName()), classToCompare);
|
||||
logger.trace("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()));
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
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();
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
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,4 +1,4 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
package org.gcube.data.access.storagehub.handlers.vres;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -9,6 +9,7 @@ import javax.jcr.SimpleCredentials;
|
|||
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
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;
|
||||
|
||||
|
@ -21,11 +22,11 @@ public class VRE {
|
|||
private VREQueryRetriever vreQueryRetriever;
|
||||
private ExecutorService executor;
|
||||
|
||||
public VRE(Item item, Repository repository, SimpleCredentials credentials, ExecutorService executor) {
|
||||
protected VRE(Item item, Repository repository, SimpleCredentials credentials, Node2ItemConverter node2Item, ExecutorService executor) {
|
||||
super();
|
||||
this.vreFolder = item;
|
||||
this.executor = executor;
|
||||
vreQueryRetriever = new VREQueryRetriever(repository, credentials, vreFolder);
|
||||
vreQueryRetriever = new VREQueryRetriever(repository, credentials, node2Item, vreFolder);
|
||||
result = executor.submit(vreQueryRetriever);
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
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,9 +1,6 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
|
@ -11,9 +8,6 @@ import javax.jcr.Node;
|
|||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.RepositoryException;
|
||||
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.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
|
@ -22,19 +16,13 @@ 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.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
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.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.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
|
@ -47,34 +35,50 @@ import org.gcube.common.storagehub.model.items.SharedFolder;
|
|||
import org.gcube.common.storagehub.model.items.VreFolder;
|
||||
import org.gcube.common.storagehub.model.types.ACLList;
|
||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
||||
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.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("items")
|
||||
public class ACLManager {
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@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);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@RequestScoped
|
||||
@PathParam("id")
|
||||
String id;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
@Inject UnshareHandler unshareHandler;
|
||||
|
||||
@Inject ACLManagerInterface aclManagerDelegate;
|
||||
|
||||
/**
|
||||
* returns the AccessType for all the users in a shared folder
|
||||
|
@ -88,38 +92,21 @@ public class ACLManager {
|
|||
public ACLList getACL() {
|
||||
InnerMethodName.instance.set("getACLById");
|
||||
Session ses = null;
|
||||
List<ACL> acls = new ArrayList<>();
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
String path = ses.getNodeByIdentifier(id).getPath();
|
||||
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);
|
||||
}
|
||||
|
||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
return new ACLList(aclManagerDelegate.get(item, ses));
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr error getting acl", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re));
|
||||
throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
}
|
||||
return new ACLList(acls);
|
||||
|
||||
}
|
||||
|
||||
|
@ -139,13 +126,14 @@ public class ACLManager {
|
|||
@PUT
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Path("{id}/acls")
|
||||
public void setACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
||||
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
||||
InnerMethodName.instance.set("setACLById");
|
||||
Session ses = null;
|
||||
try{
|
||||
try {
|
||||
|
||||
if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified");
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
@ -156,72 +144,35 @@ public class ACLManager {
|
|||
if (item.getOwner().equals(user))
|
||||
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 (accessType!=AccessType.ADMINISTRATOR)
|
||||
throw new InvalidCallParameters("acls in vreFolder cannot be changed, only new admin can be set");
|
||||
if (accessType==AccessType.ADMINISTRATOR) throw new InvalidCallParameters("a VRE admin cannot be changed with this method");
|
||||
|
||||
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();
|
||||
if (!user.equals(folder.getTitle())) throw new InvalidCallParameters("the groupId in the argument is different to the one of the VREFolder");
|
||||
|
||||
} else {
|
||||
|
||||
NodeIterator sharedSet = node.getSharedSet();
|
||||
boolean found = false;
|
||||
while (sharedSet.hasNext() && !found) {
|
||||
Node current = sharedSet.nextNode();
|
||||
if (current.getPath().startsWith(Utils.getWorkspacePath(user).toPath()))
|
||||
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
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();
|
||||
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
|
||||
}
|
||||
|
||||
aclManagerDelegate.update(user, folder, accessType, ses);
|
||||
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr error extracting archive", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
|
||||
throw new WebApplicationException(new BackendGenericError("jcr error setting acl", re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
|
@ -230,18 +181,19 @@ public class ACLManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* remove right for a user only on VRE folder
|
||||
* remove right for a user only on Shared 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
|
||||
*/
|
||||
/*@DELETE
|
||||
//TODO: is this method correct? can ACL be removed, is correct that this means an unshare operation?
|
||||
@DELETE
|
||||
@Consumes(MediaType.TEXT_PLAIN)
|
||||
@Path("{id}/acls/{user}")
|
||||
public void removeACL(@PathParam("user") String user) {
|
||||
|
@ -257,36 +209,16 @@ public class ACLManager {
|
|||
if (!(item instanceof SharedFolder))
|
||||
throw new InvalidItemException("the item is not a shared folder");
|
||||
|
||||
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
|
||||
if (item instanceof VreFolder || ((SharedFolder) item).isVreFolder())
|
||||
throw new InvalidCallParameters("acls in vreFolder cannot be removed with this method");
|
||||
|
||||
SharedFolder folder = ((SharedFolder)item);
|
||||
authChecker.checkAdministratorControl(ses, currentUser, (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");
|
||||
unshareHandler.unshare(ses, Collections.singleton(user), node, currentUser);
|
||||
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr error extracting archive", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing acl", re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
|
@ -294,7 +226,7 @@ public class ACLManager {
|
|||
if (ses!=null)
|
||||
ses.logout();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/acls/write")
|
||||
|
@ -310,7 +242,7 @@ public class ACLManager {
|
|||
throw new InvalidItemException("this method can be applied only to folder");
|
||||
|
||||
try {
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, true);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, true);
|
||||
}catch (UserNotAuthorizedException e) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
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,13 +1,19 @@
|
|||
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.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.security.AccessControlEntry;
|
||||
import javax.jcr.security.AccessControlManager;
|
||||
import javax.jcr.security.Privilege;
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -22,6 +28,7 @@ import javax.ws.rs.PathParam;
|
|||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||
|
@ -34,34 +41,82 @@ import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils
|
|||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
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.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||
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.Item;
|
||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||
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.PathUtil;
|
||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||
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.LoggerFactory;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
||||
|
||||
@Path("groups")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@RequestHeaders({
|
||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
||||
})
|
||||
public class GroupManager {
|
||||
|
||||
|
||||
|
||||
@Context ServletContext context;
|
||||
|
||||
@Inject
|
||||
TrashHandler trashHandler;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
||||
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
VREManager vreManager;
|
||||
|
||||
@Inject
|
||||
GroupHandler groupHandler;
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
public List<String> getGroups(){
|
||||
|
||||
InnerMethodName.instance.set("getGroups");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
List<String> groups= new ArrayList<>();
|
||||
try {
|
||||
|
@ -80,9 +135,9 @@ public class GroupManager {
|
|||
log.info("group {} found",group.getPrincipal().getName());
|
||||
groups.add(group.getPrincipal().getName());
|
||||
}
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error getting groups", e);
|
||||
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 {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
|
@ -92,13 +147,18 @@ public class GroupManager {
|
|||
|
||||
@POST
|
||||
@Path("")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
public String createGroup(@FormParam("group") String group, @FormParam("accessType") AccessType accessType){
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner){
|
||||
|
||||
InnerMethodName.instance.set("createGroup");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
String groupId = null;
|
||||
try {
|
||||
|
||||
log.info("create group called with groupid {} , accessType {} and folderOwner {}",group, accessType, folderOwner);
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
@ -106,10 +166,19 @@ public class GroupManager {
|
|||
Group createdGroup = usrManager.createGroup(group);
|
||||
groupId = createdGroup.getID();
|
||||
|
||||
createVreFolder(groupId, session, accessType!=null?accessType:AccessType.WRITE_OWNER);
|
||||
User user = (User)usrManager.getAuthorizable(folderOwner);
|
||||
|
||||
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();
|
||||
}catch(Exception e) {
|
||||
}catch(StorageHubException se) {
|
||||
log.error("error creating group {}", group, se);
|
||||
GXOutboundErrorResponse.throwException(se);
|
||||
}catch(Throwable e) {
|
||||
log.error("jcr error creating group {}", group, e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
|
@ -122,44 +191,207 @@ public class GroupManager {
|
|||
|
||||
@DELETE
|
||||
@Path("{group}")
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public String deleteGroup(@PathParam("group") String group){
|
||||
|
||||
InnerMethodName.instance.set("deleteGroup");
|
||||
|
||||
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(group);
|
||||
if (authorizable!=null && authorizable.isGroup())
|
||||
authorizable.remove();
|
||||
|
||||
try {
|
||||
getVreFolderNode(session, group).removeSharedSet();
|
||||
Node node = groupHandler.getFolderNodeRelatedToGroup(session, group);
|
||||
List<Item> workspaceItems = Utils.getItemList(node, Excludes.GET_ONLY_CONTENT, null, true, null);
|
||||
trashHandler.removeOnlyNodesContent(session, workspaceItems);
|
||||
node.removeSharedSet();
|
||||
}catch (Exception e) {
|
||||
log.warn("vreFolder {} not found, removing only the group", group);
|
||||
}
|
||||
Authorizable authorizable = usrManager.getAuthorizable(group);
|
||||
if (authorizable.isGroup())
|
||||
authorizable.remove();
|
||||
|
||||
session.save();
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error getting users", e);
|
||||
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 {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
||||
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
|
||||
@Path("{id}")
|
||||
@Path("{id}/admins")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
||||
|
||||
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){
|
||||
|
||||
InnerMethodName.instance.set("addUserToGroup");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
boolean success = false;
|
||||
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));
|
||||
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
@ -167,20 +399,22 @@ public class GroupManager {
|
|||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||
User user = (User)usrManager.getAuthorizable(userId);
|
||||
|
||||
success = group.addMember(user);
|
||||
if (user==null)
|
||||
throw new InvalidCallParameters("user "+userId+" not exists");
|
||||
|
||||
String folderName = group.getPrincipal().getName();
|
||||
Node folder = getVreFolderNode(session, folderName);
|
||||
if (group.isMember(user))
|
||||
throw new InvalidCallParameters("user "+userId+" is already member of group "+groupId);
|
||||
|
||||
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);
|
||||
this.internalAddUserToGroup(session, group, user);
|
||||
|
||||
session.save();
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error adding user {} to group {}", userId, groupId, e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
}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));
|
||||
}finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -188,40 +422,51 @@ public class GroupManager {
|
|||
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
|
||||
@Path("{groupId}/users/{userId}")
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
|
||||
|
||||
InnerMethodName.instance.set("removeUserFromGroup");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
boolean success = false;
|
||||
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));
|
||||
|
||||
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);
|
||||
success = groupHandler.removeUserFromGroup(groupId, userId, session);
|
||||
|
||||
session.save();
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error adding user {} to group {}", userId, groupId, e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
}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));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
|
@ -233,12 +478,18 @@ public class GroupManager {
|
|||
@GET
|
||||
@Path("{groupId}/users")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
|
||||
|
||||
InnerMethodName.instance.set("getUsersOfGroup");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
List<String> users = new ArrayList<>();
|
||||
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));
|
||||
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
@ -253,10 +504,13 @@ public class GroupManager {
|
|||
}
|
||||
|
||||
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error getting users of group {}", groupId, e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
}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));
|
||||
}finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -264,53 +518,53 @@ public class GroupManager {
|
|||
return users;
|
||||
}
|
||||
|
||||
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType) throws Exception{
|
||||
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType, String owner ) throws Exception{
|
||||
|
||||
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
||||
|
||||
String name = groupId;
|
||||
|
||||
String title = groupId.substring(groupId.lastIndexOf("-")+1);
|
||||
String currentScope = ScopeProvider.instance.get();
|
||||
ScopeBean bean = new ScopeBean(currentScope);
|
||||
while (!bean.is(Type.INFRASTRUCTURE)) {
|
||||
bean = bean.enclosingScope();
|
||||
}
|
||||
String root = bean.toString().replaceAll("/", "");
|
||||
|
||||
Node folder= Utils.createFolderInternally(session, sharedRootNode, name, "VREFolder for "+groupId, false, AuthorizationProvider.instance.get().getClient().getId(), null);
|
||||
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.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
|
||||
folder.setProperty(NodeProperty.TITLE.toString(), name);
|
||||
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), title);
|
||||
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), displayName);
|
||||
session.save();
|
||||
|
||||
AccessControlManager acm = session.getAccessControlManager();
|
||||
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 );
|
||||
*/
|
||||
|
||||
|
||||
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
|
||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,groupId), usersPrivileges );
|
||||
acm.setPolicy(folder.getPath(), acls);
|
||||
|
||||
log.debug("vrefolder created with id {}",folder.getIdentifier());
|
||||
}
|
||||
|
||||
private Node getVreFolderNode(JackrabbitSession session, String name) throws InvalidItemException, Exception {
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
private boolean isValidGroupForContext(String group){
|
||||
String currentContext = ScopeProvider.instance.get();
|
||||
String expectedGroupId= currentContext.replace("/", "-").substring(1);
|
||||
return group.equals(expectedGroupId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
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,5 +1,7 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
|
@ -12,17 +14,18 @@ import javax.jcr.security.AccessControlManager;
|
|||
import javax.jcr.security.Privilege;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.NodeConstants;
|
||||
|
@ -39,24 +42,33 @@ import org.gcube.common.storagehub.model.types.NodeProperty;
|
|||
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.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.Item2NodeConverter;
|
||||
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||
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.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("items")
|
||||
public class ItemSharing {
|
||||
@RequestHeaders({
|
||||
@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);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
@ -71,23 +83,131 @@ public class ItemSharing {
|
|||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
UnshareHandler unshareHandler;
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
@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
|
||||
@Path("{id}/share")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Deprecated
|
||||
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
|
||||
InnerMethodName.instance.set("shareFolder");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||
|
||||
|
@ -111,7 +231,7 @@ public class ItemSharing {
|
|||
ses.save();
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,currentUser);
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
@ -122,8 +242,8 @@ public class ItemSharing {
|
|||
|
||||
if (!alreadyShared) {
|
||||
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
||||
addUserToSharing(sharedFolderNode, ses, login, item, adminPrivileges, acls);
|
||||
users.remove(login);
|
||||
addUserToSharing(sharedFolderNode, ses, currentUser, item, adminPrivileges, acls);
|
||||
users.remove(currentUser);
|
||||
}
|
||||
|
||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
||||
|
@ -137,7 +257,7 @@ public class ItemSharing {
|
|||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||
|
||||
|
||||
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, false);
|
||||
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, currentUser, false);
|
||||
|
||||
ses.save();
|
||||
|
||||
|
@ -164,9 +284,8 @@ public class ItemSharing {
|
|||
|
||||
|
||||
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(login))
|
||||
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(currentUser))
|
||||
throw new InvalidItemException("item with id "+id+" cannot be shared");
|
||||
|
||||
String sharedFolderName = node.getIdentifier();
|
||||
|
@ -186,7 +305,7 @@ public class ItemSharing {
|
|||
String userRootWSId;
|
||||
String userPath;
|
||||
if (itemToShare==null) {
|
||||
String userRootWS = Utils.getWorkspacePath(user).toPath();
|
||||
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
|
||||
userRootWSId = ses.getNode(userRootWS).getIdentifier();
|
||||
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
|
||||
}
|
||||
|
@ -215,13 +334,13 @@ public class ItemSharing {
|
|||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public String unshare(@FormDataParam("users") Set<String> users){
|
||||
InnerMethodName.instance.set("unshareFolder");
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try {
|
||||
log.debug("unsharing folder with id {} with users {}", id, users);
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
Node sharedNode = ses.getNodeByIdentifier(id);
|
||||
toReturn = unshareHandler.unshare(ses, users, sharedNode, login);
|
||||
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
|
||||
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr unsharing", re);
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
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.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
|
@ -30,125 +17,105 @@ import javax.ws.rs.core.Context;
|
|||
import javax.ws.rs.core.MediaType;
|
||||
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.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.storagehub.model.NodeConstants;
|
||||
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.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.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.StorageHubAppllicationManager;
|
||||
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.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.ItemHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
|
||||
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.ItemsParameterBuilder;
|
||||
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
|
||||
import org.gcube.smartgears.annotations.ManagedBy;
|
||||
import org.gcube.smartgears.utils.InnerMethodName;
|
||||
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("items")
|
||||
public class ItemsCreator {
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@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 ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
@Context ServletContext context;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
ItemHandler itemHandler;
|
||||
|
||||
@Inject
|
||||
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
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/{id}/create/FOLDER")
|
||||
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("hidden") boolean hidden) {
|
||||
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
|
||||
@FormParam("description") String description, @FormParam("hidden") boolean hidden) {
|
||||
InnerMethodName.instance.set("createItem(FOLDER)");
|
||||
log.info("create folder item called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||
|
||||
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 ){
|
||||
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
|
||||
.description(description).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 ){
|
||||
} catch (RepositoryException re) {
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
} catch (Throwable e) {
|
||||
log.error("unexpected error", e);
|
||||
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();
|
||||
|
||||
}
|
||||
|
@ -158,57 +125,36 @@ public class ItemsCreator {
|
|||
@POST
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/{id}/create/URL")
|
||||
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) {
|
||||
public Response createURL(@PathParam("id") String id, @FormParam("name") String name,
|
||||
@FormParam("description") String description, @FormParam("value") URL value) {
|
||||
InnerMethodName.instance.set("createItem(URL)");
|
||||
log.info("create url called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||
ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name)
|
||||
.description(description).url(value).on(id).with(ses).author(currentUser);
|
||||
|
||||
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.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 ){
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
} catch (StorageHubException she) {
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}catch(RepositoryException re ){
|
||||
} catch (RepositoryException re) {
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
} catch (Throwable e) {
|
||||
log.error("unexpected error", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
if (ses != null)
|
||||
ses.logout();
|
||||
|
||||
}
|
||||
return Response.ok(toReturn).build();
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/create/GCUBEITEM")
|
||||
|
@ -218,93 +164,58 @@ public class ItemsCreator {
|
|||
Session ses = null;
|
||||
String toReturn = null;
|
||||
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
try {
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder()
|
||||
.item(item).on(id).with(ses).author(currentUser);
|
||||
|
||||
Node destination;
|
||||
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 ){
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
} catch (StorageHubException she) {
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}catch(RepositoryException re ){
|
||||
} catch (RepositoryException re) {
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
} catch (Throwable e) {
|
||||
log.error("unexpected error", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
if (ses != null)
|
||||
ses.logout();
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Path("/{id}/create/FILE")
|
||||
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
||||
@FormDataParam("description") String description,
|
||||
@FormDataParam("file") InputStream stream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||
@FormDataParam("description") String description, @FormDataParam("file") InputStream stream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail) {
|
||||
InnerMethodName.instance.set("createItem(FILE)");
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
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();
|
||||
try {
|
||||
|
||||
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);
|
||||
|
||||
Node destination = ses.getNodeByIdentifier(id);
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
|
||||
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 ){
|
||||
} catch (RepositoryException re) {
|
||||
log.error("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);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}catch(Throwable e ){
|
||||
} catch (Throwable e) {
|
||||
log.error("unexpected error", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
}finally{
|
||||
if (ses!=null && ses.isLive()) {
|
||||
} finally {
|
||||
if (ses != null && ses.isLive()) {
|
||||
log.info("session closed");
|
||||
ses.logout();
|
||||
}
|
||||
|
@ -313,249 +224,39 @@ public class ItemsCreator {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Path("/{id}/create/ARCHIVE")
|
||||
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)");
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
if (parentFolderName==null) throw new InvalidCallParameters("new folder name is null");
|
||||
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
try {
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
Node destination = ses.getNodeByIdentifier(id);
|
||||
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter
|
||||
.builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail).on(id).with(ses)
|
||||
.author(currentUser);
|
||||
|
||||
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||
throw new InvalidItemException("the destination item is not a folder");
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
|
||||
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){
|
||||
} catch (RepositoryException | ArchiveException | IOException re) {
|
||||
log.error("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);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
} finally{
|
||||
if (ses!=null)
|
||||
} catch (Throwable e) {
|
||||
log.error("unexpected error", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
} finally {
|
||||
if (ses != null)
|
||||
ses.logout();
|
||||
|
||||
}
|
||||
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,8 +44,7 @@ import javax.ws.rs.core.StreamingOutput;
|
|||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.gcube.common.encryption.StringEncrypter;
|
||||
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.common.scope.impl.ScopeBean;
|
||||
|
@ -58,12 +57,16 @@ 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.PluginInitializationException;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
||||
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.items.Item;
|
||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||
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.ItemWrapper;
|
||||
import org.gcube.common.storagehub.model.service.VersionList;
|
||||
|
@ -71,30 +74,40 @@ 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.Constants;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.Range;
|
||||
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.accounting.AccountingHandler;
|
||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||
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.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.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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
||||
|
||||
|
||||
@Path("items")
|
||||
public class ItemsManager {
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@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);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
@ -115,10 +128,18 @@ public class ItemsManager {
|
|||
@Inject
|
||||
TrashHandler trashHandler;
|
||||
|
||||
@Inject PathUtil pathUtil;
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
@Inject Item2NodeConverter item2Node;
|
||||
|
||||
@Inject StorageBackendHandler storageBackend;
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderPluginHandler;
|
||||
|
||||
@Inject
|
||||
CompressHandler compressHandler;
|
||||
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
|
@ -130,14 +151,14 @@ public class ItemsManager {
|
|||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = node2Item.getItem(node, excludes);
|
||||
}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 searching 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()));
|
||||
|
@ -149,16 +170,90 @@ public class ItemsManager {
|
|||
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
|
||||
@Path("{id}/items/{name}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
|
||||
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
|
||||
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;
|
||||
List<Item> toReturn = new ArrayList<>();
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
//NOT using the internal pattern matching of jcr because of title for shared folder
|
||||
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
|
||||
|
@ -191,8 +286,8 @@ public class ItemsManager {
|
|||
}
|
||||
|
||||
return new ItemList(toReturn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/children/count")
|
||||
|
@ -204,7 +299,7 @@ public class ItemsManager {
|
|||
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
|
@ -231,7 +326,7 @@ public class ItemsManager {
|
|||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
|
@ -250,6 +345,36 @@ public class ItemsManager {
|
|||
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
|
||||
@Path("{id}/children/paged")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
@ -259,7 +384,7 @@ public class ItemsManager {
|
|||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
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) {
|
||||
log.error("id {} not found",id,e);
|
||||
|
@ -280,16 +405,14 @@ public class ItemsManager {
|
|||
|
||||
@GET
|
||||
@Path("publiclink/{id}")
|
||||
@AuthorizationControl(allowed={"URIResolver"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
|
||||
public Response resolvePublicLink() {
|
||||
InnerMethodName.instance.set("resolvePubliclink");
|
||||
|
||||
log.warn("arrived id is {}",id);
|
||||
Session ses = null;
|
||||
try{
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
String complexId = id;
|
||||
|
||||
if (id.startsWith(enchriptedPrefix)) {
|
||||
|
@ -321,16 +444,21 @@ public class ItemsManager {
|
|||
|
||||
log.warn("item id to retrieve is {}",itemId);
|
||||
|
||||
Node selectedNode = ses.getNodeByIdentifier(itemId);
|
||||
Node selectedNode;
|
||||
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));
|
||||
|
||||
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
|
||||
|
||||
if (versionName!=null)
|
||||
return downloadVersionInternal(ses, login, itemId, versionName, false);
|
||||
return downloadVersionInternal(ses, currentUser, itemId, versionName, false);
|
||||
else
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
||||
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
|
@ -355,7 +483,7 @@ public class ItemsManager {
|
|||
URL toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
Node selectedNode = ses.getNodeByIdentifier(id);
|
||||
|
||||
|
@ -438,7 +566,7 @@ public class ItemsManager {
|
|||
Item folder= null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
Node currentNode =ses.getNodeByIdentifier(id);
|
||||
log.trace("current node is {}",currentNode.getPath());
|
||||
|
||||
|
@ -474,7 +602,7 @@ public class ItemsManager {
|
|||
Item sharedParent= null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
Node currentNode =ses.getNodeByIdentifier(id);
|
||||
log.trace("current node is {}",currentNode.getPath());
|
||||
|
||||
|
@ -517,7 +645,7 @@ public class ItemsManager {
|
|||
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
|
||||
|
@ -525,7 +653,7 @@ public class ItemsManager {
|
|||
if (!(currentItem instanceof AbstractFileItem))
|
||||
throw new InvalidItemException("this item is not versioned");
|
||||
|
||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node, ses);
|
||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
|
||||
|
||||
for (Version version: jcrVersions) {
|
||||
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
|
||||
|
@ -551,11 +679,10 @@ public class ItemsManager {
|
|||
InnerMethodName.instance.set("downloadSpecificVersion");
|
||||
Session ses = null;
|
||||
try{
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
return downloadVersionInternal(ses, login, id, versionName, true);
|
||||
return downloadVersionInternal(ses, currentUser, id, versionName, true);
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error downloading version", re);
|
||||
|
@ -576,16 +703,17 @@ public class ItemsManager {
|
|||
if (!(currentItem instanceof AbstractFileItem))
|
||||
throw new InvalidItemException("this item is not a file");
|
||||
|
||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(id), ses);
|
||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
|
||||
|
||||
for (Version version: jcrVersions) {
|
||||
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
|
||||
if (version.getName().equals(versionName)) {
|
||||
long size = version.getFrozenNode().getProperty(NodeProperty.SIZE.toString()).getLong();
|
||||
String mimeType = version.getFrozenNode().getProperty(NodeProperty.MIME_TYPE.toString()).getString();
|
||||
String storageId = version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
|
||||
Content content = node2Item.getContentFromVersion(version);
|
||||
|
||||
final InputStream streamToWrite = storageBackend.download(storageId);
|
||||
FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
|
||||
final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
|
||||
|
||||
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 ext = FilenameUtils.getExtension(currentItem.getTitle());
|
||||
|
@ -593,15 +721,15 @@ public class ItemsManager {
|
|||
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
||||
|
||||
if (withAccounting)
|
||||
accountingHandler.createReadObj(fileName, ses, node, true);
|
||||
accountingHandler.createReadObj(fileName, ses, node, login, true);
|
||||
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
return Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+fileName)
|
||||
.header("Content-Length", size)
|
||||
.header("Content-Type", mimeType)
|
||||
.header("Content-Length", content.getSize())
|
||||
.header("Content-Type", content.getMimeType())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -613,26 +741,29 @@ public class ItemsManager {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("getAnchestors");
|
||||
org.gcube.common.storagehub.model.Path absolutePath = Utils.getWorkspacePath();
|
||||
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
|
||||
Session ses = null;
|
||||
List<Item> toReturn = new LinkedList<>();
|
||||
try{
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
Node currentNode = ses.getNodeByIdentifier(id);
|
||||
Item currentItem = node2Item.getItem(currentNode, excludes);
|
||||
log.trace("current node is {}",currentNode.getPath());
|
||||
while (!(currentNode.getPath()+"/").equals(absolutePath.toPath())) {
|
||||
while (!(currentNode.getPath().matches("/Home/[^/]{1,}/Workspace"))) {
|
||||
if (currentItem instanceof SharedFolder){
|
||||
NodeIterator sharedSetIterator = currentNode.getSharedSet();
|
||||
boolean found = false;
|
||||
while (sharedSetIterator.hasNext()) {
|
||||
Node sharedNode = sharedSetIterator.nextNode();
|
||||
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath(login).toPath())) {
|
||||
if (sharedNode.getPath().startsWith(absolutePath.toPath())) {
|
||||
currentNode = sharedNode.getParent();
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) break;
|
||||
currentItem = node2Item.getItem(currentNode, excludes);
|
||||
}else {
|
||||
currentNode = currentNode.getParent();
|
||||
|
@ -669,17 +800,16 @@ public class ItemsManager {
|
|||
Session ses = null;
|
||||
Response response = null;
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
final Node node = ses.getNodeByIdentifier(id);
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
final Item item = node2Item.getItem(node, null);
|
||||
if (item instanceof AbstractFileItem){
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
||||
} else if (item instanceof FolderItem){
|
||||
|
||||
try {
|
||||
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler, excludes);
|
||||
final Deque<Item> allNodes = compressHandler.getAllNodesForZip((FolderItem)item, ses, currentUser, accountingHandler, excludes);
|
||||
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
|
||||
StreamingOutput so = new StreamingOutput() {
|
||||
|
||||
|
@ -690,7 +820,7 @@ public class ItemsManager {
|
|||
long start = System.currentTimeMillis();
|
||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||
log.debug("writing StreamOutput");
|
||||
Utils.zipNode(zos, allNodes, login, originalPath, storageBackend);
|
||||
compressHandler.zipNode(zos, allNodes, currentUser, originalPath);
|
||||
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
|
||||
} catch (Exception e) {
|
||||
log.error("error writing stream",e);
|
||||
|
@ -706,7 +836,7 @@ public class ItemsManager {
|
|||
.header("Content-Length", -1l)
|
||||
.build();
|
||||
|
||||
accountingHandler.createReadObj(item.getTitle(), ses, ses.getNodeByIdentifier(item.getId()), false);
|
||||
accountingHandler.createReadObj(item.getTitle(), ses, (Node) item.getRelatedNode(), currentUser, false);
|
||||
}finally {
|
||||
if (ses!=null) ses.save();
|
||||
}
|
||||
|
@ -725,12 +855,14 @@ public class ItemsManager {
|
|||
return response;
|
||||
}
|
||||
|
||||
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException {
|
||||
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, BackendGenericError {
|
||||
|
||||
final InputStream streamToWrite = storageBackend.download(fileItem.getContent().getStorageId());
|
||||
FolderManager folderManager = folderPluginHandler.getFolderManager(fileItem);
|
||||
|
||||
final InputStream streamToWrite = folderManager.getStorageBackend().download(fileItem.getContent());
|
||||
|
||||
if (withAccounting)
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), ses, ses.getNodeByIdentifier(fileItem.getId()), true);
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), ses, (Node) fileItem.getRelatedNode(), login, true);
|
||||
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
|
@ -751,13 +883,12 @@ public class ItemsManager {
|
|||
|
||||
Session ses = null;
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||
|
@ -778,12 +909,11 @@ public class ItemsManager {
|
|||
if (!(destinationItem instanceof FolderItem))
|
||||
throw new InvalidItemException("destination item is not a folder");
|
||||
|
||||
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");
|
||||
boolean movingSharedItemOutside = item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier()));
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
@ -791,13 +921,18 @@ public class ItemsManager {
|
|||
String uniqueName =(Utils.checkExistanceAndGetUniqueName(ses, destination, nodeToMove.getName()));
|
||||
String newPath = String.format("%s/%s",destination.getPath(), uniqueName);
|
||||
|
||||
ses.getWorkspace().move(nodeToMove.getPath(), newPath);
|
||||
Utils.setPropertyOnChangeNode(ses.getNode(newPath), login, ItemAction.MOVED);
|
||||
ses.move(nodeToMove.getPath(), newPath);
|
||||
Utils.setPropertyOnChangeNode(ses.getNode(newPath), currentUser, ItemAction.MOVED);
|
||||
|
||||
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||
|
||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting , ses, destination, false);
|
||||
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, originalParent, false);
|
||||
if (movingSharedItemOutside)
|
||||
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
|
||||
|
||||
//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();
|
||||
}finally {
|
||||
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||
|
@ -826,13 +961,11 @@ public class ItemsManager {
|
|||
Session ses = null;
|
||||
String newFileIdentifier = null;
|
||||
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));
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||
authChecker.checkReadAuthorizationControl(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
final Node nodeToCopy = ses.getNodeByIdentifier(id);
|
||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||
|
@ -844,8 +977,8 @@ public class ItemsManager {
|
|||
throw new InvalidItemException("folder cannot be copied");
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,currentUser);
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
@ -856,20 +989,23 @@ public class ItemsManager {
|
|||
Node newNode = ses.getNode(newPath);
|
||||
newFileIdentifier = newNode.getIdentifier();
|
||||
|
||||
//TODO: folderHandler.onCopy(source, destination);
|
||||
|
||||
if (item instanceof AbstractFileItem) {
|
||||
FolderManager manager = folderPluginHandler.getFolderManager(item);
|
||||
((AbstractFileItem) item).getContent().setRemotePath(newPath);
|
||||
String newStorageID = storageBackend.copy((AbstractFileItem) item);
|
||||
String newStorageID = manager.getStorageBackend().onCopy((AbstractFileItem) item);
|
||||
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
|
||||
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
||||
}
|
||||
|
||||
Utils.setPropertyOnChangeNode(newNode, login, ItemAction.CLONED);
|
||||
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), login);
|
||||
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);
|
||||
|
||||
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, destination, false);
|
||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
|
||||
|
||||
|
||||
ses.save();
|
||||
|
@ -900,12 +1036,11 @@ public class ItemsManager {
|
|||
Session ses = null;
|
||||
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||
|
||||
|
@ -919,8 +1054,8 @@ public class ItemsManager {
|
|||
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,currentUser);
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
@ -930,9 +1065,9 @@ public class ItemsManager {
|
|||
|
||||
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
|
||||
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
||||
Utils.setPropertyOnChangeNode(nodeToMove, login, ItemAction.RENAMED);
|
||||
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
|
||||
ses.move(nodeToMove.getPath(), newPath);
|
||||
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), ses, false);
|
||||
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), currentUser, ses, false);
|
||||
ses.save();
|
||||
}finally {
|
||||
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||
|
@ -954,6 +1089,96 @@ public class ItemsManager {
|
|||
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
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/metadata")
|
||||
|
@ -963,21 +1188,20 @@ public class ItemsManager {
|
|||
Session ses = null;
|
||||
|
||||
try{
|
||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,login);
|
||||
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
|
||||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
try {
|
||||
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), login);
|
||||
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), currentUser);
|
||||
ses.save();
|
||||
}finally {
|
||||
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
||||
|
@ -1013,21 +1237,24 @@ public class ItemsManager {
|
|||
|
||||
//TODO check if it is possible to change all the ACL on a workspace
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||
|
||||
final Node nodeToDelete = ses.getNodeByIdentifier(id);
|
||||
|
||||
Item itemToDelete = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
|
||||
|
||||
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");
|
||||
|
||||
if (itemToDelete.isExternalManaged() && !force)
|
||||
throw new InvalidItemException("External managed Items cannot be moved to Trash");
|
||||
|
||||
log.debug("item is trashed? {}", itemToDelete.isTrashed());
|
||||
|
||||
if (!itemToDelete.isTrashed() && !force)
|
||||
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete);
|
||||
else
|
||||
if (!itemToDelete.isTrashed() && !force) {
|
||||
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete, currentUser);
|
||||
}else
|
||||
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
|
||||
|
||||
}catch (LockException e) {
|
||||
|
|
|
@ -0,0 +1,434 @@
|
|||
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,4 +5,6 @@ import javax.jcr.Repository;
|
|||
public interface RepositoryInitializer {
|
||||
|
||||
Repository getRepository();
|
||||
|
||||
void shutdown();
|
||||
}
|
||||
|
|
|
@ -2,13 +2,17 @@ package org.gcube.data.access.storagehub.services;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.query.QueryResult;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
|
@ -20,49 +24,86 @@ import javax.ws.rs.PathParam;
|
|||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
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.QueryBuilder;
|
||||
import org.apache.jackrabbit.api.security.user.User;
|
||||
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
|
||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
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.types.NodeProperty;
|
||||
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
||||
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.PathUtil;
|
||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||
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.items.builders.FolderCreationParameters;
|
||||
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("users")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@RequestHeaders({
|
||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
||||
})
|
||||
public class UserManager {
|
||||
|
||||
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
|
||||
|
||||
@Context ServletContext context;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
UnshareHandler unshareHandler;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
TrashHandler trashHandler;
|
||||
|
||||
@Inject
|
||||
GroupHandler groupHandler;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
public List<String> getUsers(){
|
||||
|
||||
InnerMethodName.instance.set("getUsers");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
List<String> users= new ArrayList<>();
|
||||
List<String> users = null;
|
||||
try {
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
|
||||
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
|
||||
|
||||
@Override
|
||||
|
@ -71,11 +112,19 @@ public class UserManager {
|
|||
}
|
||||
});
|
||||
|
||||
Set<String> usersSet= new HashSet<>();
|
||||
String adminUser = context.getInitParameter(Constants.ADMIN_PARAM_NAME);
|
||||
|
||||
while (result.hasNext()) {
|
||||
Authorizable user = result.next();
|
||||
log.debug("user {} found",user.getPrincipal().getName());
|
||||
users.add(user.getPrincipal().getName());
|
||||
if (user.getPrincipal().getName().equals(adminUser)) continue;
|
||||
usersSet.add(user.getPrincipal().getName());
|
||||
}
|
||||
|
||||
users = new ArrayList<>(usersSet);
|
||||
Collections.sort(users);
|
||||
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error getting users", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
|
@ -86,36 +135,87 @@ public class UserManager {
|
|||
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
|
||||
@Path("")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
|
||||
|
||||
InnerMethodName.instance.set("createUser");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
String userId = null;
|
||||
try {
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
||||
User createdUser = usrManager.createUser(user, password);
|
||||
|
||||
userId = createdUser.getID();
|
||||
|
||||
Node homeNode = session.getNode("/Home");
|
||||
Node userHome = homeNode.addNode(user, "nthl:home");
|
||||
|
||||
userHome.setProperty(Constants.HOME_VERSION_PROP, 1l);
|
||||
|
||||
//creating workspace folder
|
||||
Node workspaceFolder = Utils.createFolderInternally(session, userHome, Constants.WORKSPACE_ROOT_FOLDER_NAME, "workspace of "+user, false, user, null);
|
||||
FolderCreationParameters wsFolderParameters = FolderCreationParameters.builder().name(Constants.WORKSPACE_ROOT_FOLDER_NAME).description("workspace of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
||||
Utils.createFolderInternally(wsFolderParameters, null);
|
||||
//creating thrash folder
|
||||
Utils.createFolderInternally(session, workspaceFolder, Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
|
||||
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
|
||||
Utils.createFolderInternally(trashFolderParameters, null);
|
||||
//creating Vre container folder
|
||||
Utils.createFolderInternally(session, workspaceFolder, Constants.VRE_FOLDER_PARENT_NAME, "special folder container of "+user, false, user, null);
|
||||
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(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();
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error creating user {}", user, e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
}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));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
|
@ -126,51 +226,144 @@ public class UserManager {
|
|||
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
|
||||
public String deleteUser(@PathParam("id") String id){
|
||||
@Path("{user}")
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
public String deleteUser(@PathParam("user") final String user){
|
||||
|
||||
InnerMethodName.instance.set("deleteUser");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
String userId = null;
|
||||
try {
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
||||
org.gcube.common.storagehub.model.Path path = Utils.getWorkspacePath(id);
|
||||
User authorizable = (User) usrManager.getAuthorizable(new PrincipalImpl(user));
|
||||
|
||||
if (authorizable!=null)
|
||||
removeUserFromBelongingGroup(session, authorizable, usrManager);
|
||||
else log.warn("user was already deleted from jackrabbit, trying to delete folders");
|
||||
|
||||
String sql2Query = String.format("SELECT * FROM [nthl:workspaceSharedItem] AS node WHERE ISDESCENDANTNODE('%s')", path.toPath());
|
||||
unshareUsersFolders(session, user);
|
||||
|
||||
log.info("query sent is {}",sql2Query);
|
||||
removeUserHomeAndDeleteFiles(session, 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);
|
||||
//FINALIZE user removal
|
||||
if (authorizable!=null && !authorizable.isGroup()) {
|
||||
log.info("removing user {}", user);
|
||||
authorizable.remove();
|
||||
}
|
||||
} else log.warn("the user {} was already deleted, it should never happen", user);
|
||||
|
||||
session.save();
|
||||
}catch(Exception e) {
|
||||
log.error("jcr error getting users", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
}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));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
||||
return userId;
|
||||
return user;
|
||||
}
|
||||
|
||||
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,87 +1,91 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.query.Query;
|
||||
import javax.jcr.query.QueryResult;
|
||||
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.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
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 org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
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.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.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.logical.And;
|
||||
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
|
||||
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.TrashItem;
|
||||
import org.gcube.common.storagehub.model.service.ItemList;
|
||||
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||
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.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
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.VRE;
|
||||
import org.gcube.data.access.storagehub.handlers.VREManager;
|
||||
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.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.smartgears.annotations.ManagedBy;
|
||||
import org.gcube.smartgears.utils.InnerMethodName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
||||
|
||||
|
||||
@Path("")
|
||||
public class WorkspaceManager {
|
||||
|
||||
@Path("/")
|
||||
@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);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
Evaluators evaluator;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@Inject
|
||||
ServletContext context;
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
VREManager vreManager;
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
@Inject
|
||||
TrashHandler trashHandler;
|
||||
|
||||
|
@ -92,9 +96,11 @@ public class WorkspaceManager {
|
|||
@Inject Node2ItemConverter node2Item;
|
||||
@Inject Item2NodeConverter item2Node;
|
||||
|
||||
@Inject StorageBackendHandler storageBackend;
|
||||
@Inject
|
||||
FolderPluginHandler folderHandler;
|
||||
|
||||
@Path("")
|
||||
|
||||
@Path("/")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
|
||||
|
@ -102,25 +108,24 @@ public class WorkspaceManager {
|
|||
Session ses = null;
|
||||
org.gcube.common.storagehub.model.Path absolutePath;
|
||||
if (relPath==null)
|
||||
absolutePath = Utils.getWorkspacePath();
|
||||
else absolutePath = Paths.append(Utils.getWorkspacePath(), relPath);
|
||||
absolutePath = pathUtil.getWorkspacePath(currentUser);
|
||||
else absolutePath = Paths.append(pathUtil.getWorkspacePath(currentUser), relPath);
|
||||
|
||||
Item toReturn = null;
|
||||
try{
|
||||
long start = System.currentTimeMillis();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
//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);
|
||||
//TODO: remove when all user will have TRASH
|
||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
||||
if (!ses.nodeExists(trashPath.toPath())) {
|
||||
Utils.createFolderInternally(ses, ses.getNode(Utils.getWorkspacePath().toPath()) , Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
|
||||
Node wsNode = ses.getNode(pathUtil.getWorkspacePath(currentUser).toPath());
|
||||
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();
|
||||
}
|
||||
|
||||
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||
Node node = ses.getNode(absolutePath.toPath());
|
||||
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, node.getIdentifier());
|
||||
toReturn = node2Item.getItem(node, excludes);
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error getting workspace item", re);
|
||||
|
@ -136,38 +141,17 @@ public class WorkspaceManager {
|
|||
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")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemWrapper<Item> getVreRootFolder(){
|
||||
InnerMethodName.instance.set("getVreRootFolder");
|
||||
Session ses = null;
|
||||
JackrabbitSession ses = null;
|
||||
Item vreItem = null;
|
||||
try {
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
vreItem = getVreFolderItem(ses).getVreFolder();
|
||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
vreItem = vreManager.getVreFolderItem(ses, currentUser, excludes).getVreFolder();
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error getting vrefolder", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||
|
@ -186,13 +170,12 @@ public class WorkspaceManager {
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList getVreFolderRecentsDocument(){
|
||||
InnerMethodName.instance.set("getVreFolderRecents");
|
||||
Session ses = null;
|
||||
JackrabbitSession ses = null;
|
||||
List<Item> recentItems = Collections.emptyList();
|
||||
try{
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
VRE vre = getVreFolderItem(ses);
|
||||
VRE vre = vreManager.getVreFolderItem(ses, currentUser, excludes);
|
||||
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
|
||||
recentItems = vre.getRecents();
|
||||
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
|
||||
|
@ -220,12 +203,12 @@ public class WorkspaceManager {
|
|||
public ItemWrapper<Item> getTrashRootFolder(){
|
||||
InnerMethodName.instance.set("getTrashRootFolder");
|
||||
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;
|
||||
try{
|
||||
long start = System.currentTimeMillis();
|
||||
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));
|
||||
|
||||
Node folder = ses.getNode(trashPath.toPath());
|
||||
|
@ -242,18 +225,18 @@ public class WorkspaceManager {
|
|||
}
|
||||
|
||||
return new ItemWrapper<Item>(item);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Path("trash/empty")
|
||||
@DELETE
|
||||
public String emptyTrash(){
|
||||
InnerMethodName.instance.set("emptyTrash");
|
||||
Session ses = null;
|
||||
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
String toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
||||
Node trashNode = ses.getNode(trashPath.toPath());
|
||||
List<Item> itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
|
||||
trashHandler.removeNodes(ses, itemsToDelete);
|
||||
|
@ -273,32 +256,39 @@ public class WorkspaceManager {
|
|||
}
|
||||
|
||||
@PUT
|
||||
@Consumes(MediaType.TEXT_PLAIN)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("trash/restore")
|
||||
public String restoreItem(String identifier){
|
||||
public String restoreItem(@FormParam("trashedItemId") String trashedItemId,@FormParam("destinationId") String destinationFolderId){
|
||||
InnerMethodName.instance.set("restoreItem");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
|
||||
log.info("restoring node with id {}", identifier);
|
||||
|
||||
//TODO check if it is possible to change all the ACL on a workspace
|
||||
log.info("restoring node with id {}", trashedItemId);
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
|
||||
|
||||
final Node nodeToRestore = ses.getNodeByIdentifier(identifier);
|
||||
final Node nodeToRestore = ses.getNodeByIdentifier(trashedItemId);
|
||||
|
||||
Item itemToRestore = node2Item.getItem(nodeToRestore, Excludes.ALL);
|
||||
|
||||
if (!(itemToRestore instanceof TrashItem))
|
||||
throw new InvalidItemException("Only trash items can be restored");
|
||||
|
||||
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore);
|
||||
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
|
||||
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 ){
|
||||
log.error("error restoring item with id {}",identifier, re);
|
||||
log.error("error restoring item with id {}",trashedItemId, re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
|
@ -319,12 +309,13 @@ public class WorkspaceManager {
|
|||
public ItemList getVreFolders(){
|
||||
InnerMethodName.instance.set("getVreFolders");
|
||||
Session ses = null;
|
||||
|
||||
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||
List<? extends Item> toReturn = null;
|
||||
org.gcube.common.storagehub.model.Path vrePath = null;
|
||||
try{
|
||||
log.info("vres folder path is {}",vrePath.toPath());
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
vrePath = pathUtil.getVREsPath(currentUser, ses);
|
||||
log.info("vres folder path is {}",vrePath.toPath());
|
||||
|
||||
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
|
||||
}catch(RepositoryException re ){
|
||||
log.error("error reading the node children of {}",vrePath, re);
|
||||
|
@ -346,10 +337,11 @@ public class WorkspaceManager {
|
|||
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
|
||||
InnerMethodName.instance.set("getVreFoldersPaged");
|
||||
Session ses = null;
|
||||
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||
org.gcube.common.storagehub.model.Path vrePath = null;
|
||||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
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);
|
||||
}catch(RepositoryException re ){
|
||||
log.error("(paged) error reading the node children of {}",vrePath, re);
|
||||
|
@ -367,64 +359,11 @@ public class WorkspaceManager {
|
|||
|
||||
|
||||
|
||||
@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")
|
||||
@GET
|
||||
public String getTotalItemsCount(){
|
||||
InnerMethodName.instance.set("getTotalItemsCount");
|
||||
return storageBackend.getTotalItemsCount();
|
||||
return folderHandler.getDefault().getStorageBackend().getTotalItemsCount();
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,7 +371,7 @@ public class WorkspaceManager {
|
|||
@GET
|
||||
public String getTotalVolume(){
|
||||
InnerMethodName.instance.set("getTotalSize");
|
||||
return storageBackend.getTotalVolume();
|
||||
return folderHandler.getDefault().getStorageBackend().getTotalSizeStored();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
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;
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
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,10 +1,11 @@
|
|||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import java.util.UUID;
|
||||
|
||||
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.StorageBackend;
|
||||
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||
|
@ -14,7 +15,6 @@ import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class GCubeStorageBackend implements StorageBackend {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(GCubeStorageBackend.class);
|
||||
|
@ -22,9 +22,13 @@ public class GCubeStorageBackend implements StorageBackend {
|
|||
private final static String SERVICE_NAME = "home-library";
|
||||
private final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||
|
||||
|
||||
|
||||
protected GCubeStorageBackend() {}
|
||||
|
||||
@Override
|
||||
public InputStream getContent(String id) {
|
||||
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(id);
|
||||
public InputStream download(Content content) {
|
||||
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(content.getStorageId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -33,35 +37,38 @@ public class GCubeStorageBackend implements StorageBackend {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String copy(String idToCopy, String path) {
|
||||
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(idToCopy).to(path);
|
||||
log.info("copying storage Id {} to newPath {} and the id returned by storage is {}", idToCopy, path, newStorageID);
|
||||
public String onCopy(AbstractFileItem item) {
|
||||
log.info("copying storage Id {} to newPath {}", item.getContent().getStorageId(), item.getPath());
|
||||
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(item.getContent().getStorageId()).to(item.getPath());
|
||||
log.info("The id returned by storage is {}", newStorageID);
|
||||
return newStorageID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String move(String idToMove) {
|
||||
return idToMove;
|
||||
public String onMove(AbstractFileItem item) {
|
||||
return item.getContent().getStorageId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaInfo upload(InputStream stream, String itemPath) {
|
||||
public MetaInfo upload(InputStream stream, String relPath, String name) {
|
||||
log.debug("uploading file");
|
||||
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
||||
String storageId =storageClient.put(true).LFile(stream).RFile(itemPath);
|
||||
String uid = UUID.randomUUID().toString();
|
||||
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);
|
||||
MetaInfo info = new MetaInfo();
|
||||
info.setSize(size);
|
||||
info.setStorageId(storageId);
|
||||
info.setRemotePath(itemPath);
|
||||
info.setRemotePath(remotePath);
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
public void onDelete(Content content) {
|
||||
log.debug("deleting");
|
||||
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
|
||||
storageClient.remove().RFileById(id);
|
||||
storageClient.remove().RFileById(content.getStorageId());
|
||||
}
|
||||
|
||||
private static StorageClient getStorageClient(String login){
|
||||
|
@ -82,7 +89,4 @@ public class GCubeStorageBackend implements StorageBackend {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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,3 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
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>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,313 +1,297 @@
|
|||
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
|
||||
(as defined below) which is provided under the terms of this Licence. Any use of
|
||||
the Work, other than as authorised under this Licence is prohibited (to the
|
||||
extent such use is covered by a right of the copyright holder of the Work).
|
||||
This European Union Public Licence (the “EUPL”) applies to the Work or Software
|
||||
(as defined below) which is provided under the terms of this Licence. Any use of
|
||||
the Work, other than as authorised under this Licence is prohibited (to the
|
||||
extent such use is covered by a right of the copyright holder of the Work).
|
||||
|
||||
The Original Work is provided under the terms of this Licence when the Licensor
|
||||
(as defined below) has placed the following notice immediately following the
|
||||
copyright notice for the Original Work:
|
||||
The Original Work is provided under the terms of this Licence when the Licensor
|
||||
(as defined below) has placed the following notice immediately following the
|
||||
copyright notice for the Original Work:
|
||||
|
||||
Licensed under the EUPL V.1.1
|
||||
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
|
||||
|
||||
1. Definitions
|
||||
In this Licence, the following terms have the following meaning:
|
||||
|
||||
In this Licence, the following terms have the following meaning:
|
||||
- The Licence: this Licence.
|
||||
|
||||
- The Licence: this Licence.
|
||||
- The Original Work or the Software: the software distributed and/or
|
||||
communicated by the Licensor under this Licence, available as Source Code and
|
||||
also as Executable Code as the case may be.
|
||||
|
||||
- The Original Work or the Software: the software distributed and/or
|
||||
communicated by the Licensor under this Licence, available as Source Code and
|
||||
also as Executable Code as the case may be.
|
||||
- Derivative Works: the works or software that could be created by the Licensee,
|
||||
based upon the Original Work or modifications thereof. This Licence does not
|
||||
define the extent of modification or dependence on the Original Work required
|
||||
in order to classify a work as a Derivative Work; this extent is determined by
|
||||
copyright law applicable in the country mentioned in Article 15.
|
||||
|
||||
- Derivative Works: the works or software that could be created by the Licensee,
|
||||
based upon the Original Work or modifications thereof. This Licence does not
|
||||
define the extent of modification or dependence on the Original Work required
|
||||
in order to classify a work as a Derivative Work; this extent is determined by
|
||||
copyright law applicable in the country mentioned in Article 15.
|
||||
- The Work: the Original Work and/or its Derivative Works.
|
||||
|
||||
- The Work: the Original Work and/or its Derivative Works.
|
||||
- The Source Code: the human-readable form of the Work which is the most
|
||||
convenient for people to study and modify.
|
||||
|
||||
- The Source Code: the human-readable form of the Work which is the most
|
||||
convenient for people to study and modify.
|
||||
- The Executable Code: any code which has generally been compiled and which is
|
||||
meant to be interpreted by a computer as a program.
|
||||
|
||||
- The Executable Code: any code which has generally been compiled and which is
|
||||
meant to be interpreted by a computer as a program.
|
||||
- The Licensor: the natural or legal person that distributes and/or communicates
|
||||
the Work under the Licence.
|
||||
|
||||
- The Licensor: the natural or legal person that distributes and/or communicates
|
||||
the Work under the Licence.
|
||||
- Contributor(s): any natural or legal person who modifies the Work under the
|
||||
Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||
|
||||
- Contributor(s): any natural or legal person who modifies the Work under the
|
||||
Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
||||
Software under the terms of the Licence.
|
||||
|
||||
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
||||
Software under the terms of the Licence.
|
||||
- Distribution and/or Communication: any act of selling, giving, lending,
|
||||
renting, distributing, communicating, transmitting, or otherwise making
|
||||
available, on-line or off-line, copies of the Work or providing access to its
|
||||
essential functionalities at the disposal of any other natural or legal
|
||||
person.
|
||||
|
||||
- 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:
|
||||
|
||||
2. Scope of the rights granted by the Licence
|
||||
- use the Work in any circumstance and for all usage, reproduce the Work, modify
|
||||
- the Original Work, and make Derivative Works based upon the Work, communicate
|
||||
- to the public, including the right to make available or display the Work or
|
||||
- copies thereof to the public and perform publicly, as the case may be, the
|
||||
- Work, distribute the Work or copies thereof, lend and rent the Work or copies
|
||||
- thereof, sub-license rights in the Work or copies thereof.
|
||||
|
||||
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:
|
||||
Those rights can be exercised on any media, supports and formats, whether now
|
||||
known or later invented, as far as the applicable law permits so.
|
||||
|
||||
- use the Work in any circumstance and for all usage, reproduce the Work, modify
|
||||
- the Original Work, and make Derivative Works based upon the Work, communicate
|
||||
- to the public, including the right to make available or display the Work or
|
||||
- copies thereof to the public and perform publicly, as the case may be, the
|
||||
- Work, distribute the Work or copies thereof, lend and rent the Work or copies
|
||||
- thereof, sub-license rights in the Work or copies thereof.
|
||||
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.
|
||||
|
||||
Those rights can be exercised on any media, supports and formats, whether now
|
||||
known or later invented, as far as the applicable law permits so.
|
||||
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.
|
||||
|
||||
In the countries where moral rights apply, the Licensor waives his right to
|
||||
exercise his moral right to the extent allowed by law in order to make effective
|
||||
the licence of the economic rights here above listed.
|
||||
|
||||
The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
|
||||
any patents held by the Licensor, to the extent necessary to make use of the
|
||||
rights granted on the Work under this Licence.
|
||||
3. Communication of the Source Code
|
||||
|
||||
The Licensor may provide the Work either in its Source Code form, or as
|
||||
Executable Code. If the Work is provided as Executable Code, the Licensor
|
||||
provides in addition a machine-readable copy of the Source Code of the Work
|
||||
along with each copy of the Work that the Licensor distributes or indicates, in
|
||||
a notice following the copyright notice attached to the Work, a repository where
|
||||
the Source Code is easily and freely accessible for as long as the Licensor
|
||||
continues to distribute and/or communicate the Work.
|
||||
|
||||
|
||||
3. Communication of the Source Code
|
||||
4. Limitations on copyright
|
||||
|
||||
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.
|
||||
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
||||
any exception or limitation to the exclusive rights of the rights owners in the
|
||||
Original Work or Software, of the exhaustion of those rights or of other
|
||||
applicable limitations thereto.
|
||||
|
||||
|
||||
5. Obligations of the Licensee
|
||||
|
||||
4. Limitations on copyright
|
||||
The grant of the rights mentioned above is subject to some restrictions and
|
||||
obligations imposed on the Licensee. Those obligations are the following:
|
||||
|
||||
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
||||
any exception or limitation to the exclusive rights of the rights owners in the
|
||||
Original Work or Software, of the exhaustion of those rights or of other
|
||||
applicable limitations thereto.
|
||||
Attribution right: the Licensee shall keep intact all copyright, patent or
|
||||
trademarks notices and all notices that refer to the Licence and to the
|
||||
disclaimer of warranties. The Licensee must include a copy of such notices and a
|
||||
copy of the Licence with every copy of the Work he/she distributes and/or
|
||||
communicates. The Licensee must cause any Derivative Work to carry prominent
|
||||
notices stating that the Work has been modified and the date of modification.
|
||||
|
||||
Copyleft clause: If the Licensee distributes and/or communicates copies of the
|
||||
Original Works or Derivative Works based upon the Original Work, this
|
||||
Distribution and/or Communication will be done under the terms of this Licence
|
||||
or of a later version of this Licence unless the Original Work is expressly
|
||||
distributed only under this version of the Licence. The Licensee (becoming
|
||||
Licensor) cannot offer or impose any additional terms or conditions on the Work
|
||||
or Derivative Work that alter or restrict the terms of the Licence.
|
||||
|
||||
Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
|
||||
Works or copies thereof based upon both the Original Work and another work
|
||||
licensed under a Compatible Licence, this Distribution and/or Communication can
|
||||
be done under the terms of this Compatible Licence. For the sake of this clause,
|
||||
“Compatible Licence” refers to the licences listed in the appendix attached to
|
||||
this Licence. Should the Licensee’s obligations under the Compatible Licence
|
||||
conflict with his/her obligations under this Licence, the obligations of the
|
||||
Compatible Licence shall prevail.
|
||||
|
||||
5. Obligations of the Licensee
|
||||
Provision of Source Code: When distributing and/or communicating copies of the
|
||||
Work, the Licensee will provide a machine-readable copy of the Source Code or
|
||||
indicate a repository where this Source will be easily and freely available for
|
||||
as long as the Licensee continues to distribute and/or communicate the Work.
|
||||
|
||||
The grant of the rights mentioned above is subject to some restrictions and
|
||||
obligations imposed on the Licensee. Those obligations are the following:
|
||||
Legal Protection: This Licence does not grant permission to use the trade names,
|
||||
trademarks, service marks, or names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the copyright notice.
|
||||
|
||||
Attribution right: the Licensee shall keep intact all copyright, patent or
|
||||
trademarks notices and all notices that refer to the Licence and to the
|
||||
disclaimer of warranties. The Licensee must include a copy of such notices and a
|
||||
copy of the Licence with every copy of the Work he/she distributes and/or
|
||||
communicates. The Licensee must cause any Derivative Work to carry prominent
|
||||
notices stating that the Work has been modified and the date of modification.
|
||||
|
||||
Copyleft clause: If the Licensee distributes and/or communicates copies of the
|
||||
Original Works or Derivative Works based upon the Original Work, this
|
||||
Distribution and/or Communication will be done under the terms of this Licence
|
||||
or of a later version of this Licence unless the Original Work is expressly
|
||||
distributed only under this version of the Licence. The Licensee (becoming
|
||||
Licensor) cannot offer or impose any additional terms or conditions on the Work
|
||||
or Derivative Work that alter or restrict the terms of the Licence.
|
||||
6. Chain of Authorship
|
||||
|
||||
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.
|
||||
The original Licensor warrants that the copyright in the Original Work granted
|
||||
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
|
||||
Provision of Source Code: When distributing and/or communicating copies of the
|
||||
Work, the Licensee will provide a machine-readable copy of the Source Code or
|
||||
indicate a repository where this Source will be easily and freely available for
|
||||
as long as the Licensee continues to distribute and/or communicate the Work.
|
||||
Each Contributor warrants that the copyright in the modifications he/she brings
|
||||
to the Work are owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
|
||||
Legal Protection: This Licence does not grant permission to use the trade names,
|
||||
trademarks, service marks, or names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the copyright notice.
|
||||
Each time You accept the Licence, the original Licensor and subsequent
|
||||
Contributors grant You a licence to their contributions to the Work, under the
|
||||
terms of this Licence.
|
||||
|
||||
|
||||
7. Disclaimer of Warranty
|
||||
|
||||
6. Chain of Authorship
|
||||
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.
|
||||
|
||||
The original Licensor warrants that the copyright in the Original Work granted
|
||||
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
For the above reason, the Work is provided under the Licence on an “as is” basis
|
||||
and without warranties of any kind concerning the Work, including without
|
||||
limitation merchantability, fitness for a particular purpose, absence of defects
|
||||
or errors, accuracy, non-infringement of intellectual property rights other than
|
||||
copyright as stated in Article 6 of this Licence.
|
||||
|
||||
Each Contributor warrants that the copyright in the modifications he/she brings
|
||||
to the Work are owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
This disclaimer of warranty is an essential part of the Licence and a condition
|
||||
for the grant of any rights to the Work.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
9. Additional agreements
|
||||
|
||||
For the above reason, the Work is provided under the Licence on an “as is” basis
|
||||
and without warranties of any kind concerning the Work, including without
|
||||
limitation merchantability, fitness for a particular purpose, absence of defects
|
||||
or errors, accuracy, non-infringement of intellectual property rights other than
|
||||
copyright as stated in Article 6 of this Licence.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
8. Disclaimer of Liability
|
||||
Similarly, you irrevocably accept this Licence and all of its terms and
|
||||
conditions by exercising any rights granted to You by Article 2 of this Licence,
|
||||
such as the use of the Work, the creation by You of a Derivative Work or the
|
||||
Distribution and/or Communication by You of the Work or copies thereof.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
12. Termination of the Licence
|
||||
|
||||
The Licence and the rights granted hereunder will terminate automatically upon
|
||||
any breach by the Licensee of the terms of the Licence.
|
||||
|
||||
Such a termination will not terminate the licences of any person who has
|
||||
received the Work from the Licensee under the Licence, provided such persons
|
||||
remain in full compliance with the Licence.
|
||||
|
||||
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.
|
||||
13. Miscellaneous
|
||||
|
||||
Similarly, you irrevocably accept this Licence and all of its terms and
|
||||
conditions by exercising any rights granted to You by Article 2 of this Licence,
|
||||
such as the use of the Work, the creation by You of a Derivative Work or the
|
||||
Distribution and/or Communication by You of the Work or copies thereof.
|
||||
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.
|
||||
|
||||
11. Information to the public
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
12. Termination of the Licence
|
||||
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.
|
||||
|
||||
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.
|
||||
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:
|
||||
|
||||
13. Miscellaneous
|
||||
- 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.
|
||||
|
||||
Without prejudice of Article 9 above, the Licence represents the complete
|
||||
agreement between the Parties as to the Work licensed hereunder.
|
||||
|
||||
If any provision of the Licence is invalid or unenforceable under applicable
|
||||
law, this will not affect the validity or enforceability of the Licence as a
|
||||
whole. Such provision will be construed and/or reformed so as necessary to make
|
||||
it valid and enforceable.
|
||||
===
|
||||
|
||||
The European Commission may publish other linguistic versions and/or new
|
||||
versions of this Licence, so far this is required and reasonable, without
|
||||
reducing the scope of the rights granted by the Licence. New versions of the
|
||||
Licence will be published with a unique version number.
|
||||
|
||||
All linguistic versions of this Licence, approved by the European Commission,
|
||||
have identical value. Parties can take advantage of the linguistic version of
|
||||
their choice.
|
||||
Appendix
|
||||
|
||||
|
||||
“Compatible Licences” according to article 5 EUPL are:
|
||||
|
||||
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.
|
||||
- GNU General Public License (GNU GPL) v. 2
|
||||
|
||||
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.
|
||||
- Open Software License (OSL) v. 2.1, v. 3.0
|
||||
|
||||
- Common Public License v. 1.0
|
||||
|
||||
- Eclipse Public License v. 1.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
|
||||
- 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
|
||||
open-source software toolkit used for building and operating Hybrid Data
|
||||
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
||||
by favouring the realisation of reuse oriented policies.
|
||||
open-source software toolkit used for building and operating Hybrid Data
|
||||
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
||||
by favouring the realisation of reuse oriented policies.
|
||||
|
||||
The projects leading to this software have received funding from a series of
|
||||
European Union programmes including:
|
||||
* the Sixth Framework Programme for Research and Technological Development -
|
||||
DILIGENT (grant no. 004260);
|
||||
* the Seventh Framework Programme for research, technological development and
|
||||
demonstration - D4Science (grant no. 212488), D4Science-II (grant no.
|
||||
239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine
|
||||
(grant no. 283644);
|
||||
* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680),
|
||||
EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant
|
||||
no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
|
||||
European Union programmes including:
|
||||
* the Sixth Framework Programme for Research and Technological Development -
|
||||
DILIGENT (grant no. 004260);
|
||||
* the Seventh Framework Programme for research, technological development and
|
||||
demonstration - D4Science (grant no. 212488), D4Science-II (grant no.
|
||||
239019),ENVRI (grant no. 283465), EUBrazilOpenBio (grant no. 288754), iMarine
|
||||
(grant no. 283644);
|
||||
* the H2020 research and innovation programme - BlueBRIDGE (grant no. 675680),
|
||||
EGIEngage (grant no. 654142), ENVRIplus (grant no. 654182), Parthenos (grant
|
||||
no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
|
||||
|
||||
|
||||
Version
|
||||
--------------------------------------------------
|
||||
|
||||
1.0.7-SNAPSHOT (2019-09-16)
|
||||
1.4.2 (20230524-150450)
|
||||
|
||||
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:
|
||||
${scm.url}
|
||||
https://code-repo.d4science.org/gCubeSystem/storagehub
|
||||
|
||||
Binaries can be downloaded from the gCube website:
|
||||
https://www.gcube-system.org/
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<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>
|
|
@ -0,0 +1,26 @@
|
|||
.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.logical.And;
|
||||
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.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//@RunWith(WeldJunit4Runner.class)
|
||||
public class Expressions {
|
||||
|
||||
/*
|
||||
private static Logger log = LoggerFactory.getLogger(Expression.class);
|
||||
|
||||
@Inject
|
||||
|
@ -36,12 +36,21 @@ public class Expressions {
|
|||
|
||||
}
|
||||
|
||||
*/
|
||||
@Test
|
||||
public void test2() {
|
||||
String groupId ="/gcube/devsec/devVre";
|
||||
String title = groupId.substring(groupId.lastIndexOf("/")+1);
|
||||
System.out.println(title);
|
||||
public void test() {
|
||||
String entirePath = "sp2/comic/";
|
||||
/*String[] parentPathSplit = entirePath.split("/");
|
||||
System.out.println(parentPathSplit.length);
|
||||
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,6 +5,7 @@ import static org.mockito.Matchers.anyString;
|
|||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.jcr.Node;
|
||||
|
@ -13,18 +14,23 @@ import javax.jcr.nodetype.NodeType;
|
|||
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
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 {
|
||||
|
||||
Logger logger = LoggerFactory.getLogger(TestFields.class);
|
||||
|
||||
//@Test
|
||||
@Test
|
||||
public void iterateOverFields() throws Exception{
|
||||
|
||||
Property prop = mock(Property.class);
|
||||
|
@ -63,4 +69,21 @@ 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,19 +1,5 @@
|
|||
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 {
|
||||
|
||||
/*@Test
|
||||
|
|
Loading…
Reference in New Issue