Compare commits
141 Commits
storagehub
...
master
Author | SHA1 | Date |
---|---|---|
Lucio Lelii | 078516a971 | |
Lucio Lelii | 1b724a8d8b | |
Lucio Lelii | 34e7820514 | |
Lucio Lelii | 47a4564ffa | |
Lucio Lelii | c324cf2507 | |
Lucio Lelii | 8cd39a77de | |
Lucio Lelii | 41448b297a | |
Lucio Lelii | 17118d0869 | |
Lucio Lelii | 6652cba390 | |
Lucio Lelii | 10baca947a | |
Lucio Lelii | 81cb8994ae | |
lucio | a41f4a564d | |
lucio | 1bcd502f25 | |
Massimiliano Assante | 8dd4df456b | |
Massimiliano Assante | 2e5ffc2d5f | |
lucio | 6850309b27 | |
lucio | 63b4916520 | |
lucio | 57cf44ade2 | |
lucio | 244a13845b | |
lucio | 8f56d9f276 | |
lucio | 6e1a62a2ab | |
lucio | 749dc7e603 | |
Lucio Lelii | 19a902c737 | |
Lucio Lelii | 29728077ae | |
lucio | 6384ce5a34 | |
lucio | b097ad8a84 | |
Lucio Lelii | 743e06dbb9 | |
lucio | c36f1764e9 | |
lucio | e9ebebdbbf | |
lucio | 7f87628687 | |
lucio | 42137b24a0 | |
lucio | 413b5cdfdf | |
lucio | 0f59bc8d8c | |
lucio | afbaceffa9 | |
lucio | e36f4eb776 | |
lucio | 4955cdcad6 | |
lucio | 4fd099c7cf | |
lucio | a9cc80f424 | |
lucio | 50b2c80a1a | |
lucio | 3584bdaf29 | |
lucio | 98ee8ea8e9 | |
lucio | b805869feb | |
lucio | 16f61a0a61 | |
lucio | cf78d06b64 | |
lucio | 1736417057 | |
lucio | 994608da26 | |
lucio | 76639ed5f1 | |
lucio | 38874c9529 | |
lucio | 32b35e4060 | |
lucio | 8df806bf49 | |
lucio | 26bc4c93ac | |
lucio | 335204d3ee | |
lucio | 4878f8bb18 | |
lucio | eefa46cbf6 | |
lucio | e11b2147da | |
lucio | 0becded125 | |
lucio | c4d5cffe02 | |
lucio | f75f7d86d9 | |
lucio | 2452a25349 | |
lucio | 87cc8a3ff9 | |
lucio | b34ad84baf | |
lucio | 7e875a5dfb | |
lucio | 10982ea64d | |
lucio | a0cd2e8ccf | |
lucio | e5dda6bb8b | |
lucio | d1d45a8056 | |
lucio | 56f8ffb838 | |
Lucio Lelii | d216459747 | |
lucio | 4d118372f3 | |
lucio | 0cc0949698 | |
lucio | 884f40b759 | |
lucio | a1b69aee6a | |
lucio | 09879535d2 | |
lucio | 7d96327512 | |
Lucio Lelii | 443d9cabd4 | |
Lucio Lelii | 2629c5c387 | |
Lucio Lelii | 3a7aa8b8e3 | |
Lucio Lelii | d0a7197c5c | |
Lucio Lelii | 0420e2ba3e | |
Lucio Lelii | 2033a4b79f | |
Lucio Lelii | bca553aa5f | |
Lucio Lelii | 4bd37f8963 | |
Lucio Lelii | b3913ba9c1 | |
Lucio Lelii | 1f6329c38e | |
Lucio Lelii | 4083b7c120 | |
Lucio Lelii | a500df61a1 | |
Lucio Lelii | 7019740af7 | |
Lucio Lelii | 2012500de8 | |
Lucio Lelii | 8b235da142 | |
Lucio Lelii | 0649acb8a9 | |
Lucio Lelii | 2e7fc876cf | |
Lucio Lelii | 9b568a09ec | |
Lucio Lelii | 55b6d8e09a | |
Lucio Lelii | e60a07abe9 | |
Lucio Lelii | 1525afef9e | |
Lucio Lelii | fad2e7ffb9 | |
Lucio Lelii | b625fafcc8 | |
Lucio Lelii | 80d15ccef7 | |
Lucio Lelii | 6d72896662 | |
Lucio Lelii | a87d6ab3da | |
Lucio Lelii | 3b5686e705 | |
Lucio Lelii | d36a3314ba | |
Lucio Lelii | 6dd371070e | |
Lucio Lelii | 6af9fce70f | |
Lucio Lelii | ac2ca4c360 | |
Lucio Lelii | b5b3669af5 | |
Lucio Lelii | 88406a3bf2 | |
Lucio Lelii | 6756c2890c | |
Lucio Lelii | 4d38cc6e72 | |
Lucio Lelii | e1db5df7c9 | |
Lucio Lelii | 25105ca041 | |
Lucio Lelii | 5de8dee586 | |
Lucio Lelii | 3e6e203f36 | |
Lucio Lelii | bfa702bf0f | |
Lucio Lelii | 50124d8a49 | |
Lucio Lelii | 9dea04e74e | |
Lucio Lelii | 28044da030 | |
Lucio Lelii | b0141e6b6f | |
Lucio Lelii | 14a71d4aa7 | |
Lucio Lelii | 3b0bb084b6 | |
Lucio Lelii | c4ea5bb05c | |
Lucio Lelii | ce071c1f7e | |
Lucio Lelii | 805b72155d | |
Lucio Lelii | e43faf6f92 | |
Lucio Lelii | 492873bd7e | |
Lucio Lelii | d2b3151edc | |
Lucio Lelii | 9d3bd619bd | |
Lucio Lelii | 6d3e9394c4 | |
Lucio Lelii | d672386824 | |
Lucio Lelii | 57e0113216 | |
Lucio Lelii | 4f87677674 | |
Lucio Lelii | e11bb536a7 | |
lucio.lelii | af9290cbca | |
lucio.lelii | db30621608 | |
Lucio Lelii | 70391906e2 | |
Lucio Lelii | ca23f94e09 | |
Lucio Lelii | 8d11063f6b | |
lucio.lelii | 9facccdf46 | |
lucio.lelii | da7385f62f | |
lucio.lelii | 29b728b057 | |
lucio.lelii | 7ee17adeac |
40
.classpath
40
.classpath
|
@ -1,16 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
|
@ -18,23 +36,5 @@
|
|||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
target
|
||||
/Storagehub-TODO
|
||||
/postgres-data/
|
||||
.classpath
|
||||
.settings/org.eclipse.jdt.core.prefs
|
||||
/.project
|
||||
/.externalToolBuilders/
|
||||
/.settings/
|
||||
|
|
14
.project
14
.project
|
@ -6,8 +6,13 @@
|
|||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/org.eclipse.wst.common.project.facet.core.builder.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
|
@ -16,8 +21,13 @@
|
|||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
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=17
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=17
|
||||
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.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
org.eclipse.jdt.core.compiler.source=17
|
||||
|
|
|
@ -1,5 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -23,7 +40,24 @@
|
|||
|
||||
|
||||
<wb-module deploy-name="storagehub">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -47,7 +81,24 @@
|
|||
|
||||
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -71,61 +122,79 @@
|
|||
|
||||
|
||||
<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="storagehub-model-1.1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
|
||||
|
||||
|
||||
|
||||
<dependent-module archiveName="common-smartgears-app-3.0.1-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/common-smartgears-app/common-smartgears-app">
|
||||
|
||||
|
||||
|
||||
<dependency-type>uses</dependency-type>
|
||||
|
||||
|
||||
|
||||
</dependent-module>
|
||||
<dependent-module archiveName="storagehub-script-utils-1.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-scripting-util/storagehub-scripting-util">
|
||||
|
||||
|
||||
|
||||
<dependent-module archiveName="authorization-control-library-2.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-2.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
|
||||
|
||||
|
||||
|
||||
<dependency-type>uses</dependency-type>
|
||||
|
||||
|
||||
|
||||
</dependent-module>
|
||||
|
||||
|
||||
|
||||
<dependent-module archiveName="storagehub-script-utils-2.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-scripting-util/storagehub-scripting-util">
|
||||
|
||||
|
||||
|
||||
<dependency-type>uses</dependency-type>
|
||||
|
||||
|
||||
|
||||
</dependent-module>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -149,7 +218,24 @@
|
|||
|
||||
|
||||
<property name="context-root" value="storagehub"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -173,7 +259,24 @@
|
|||
|
||||
|
||||
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -197,7 +300,24 @@
|
|||
|
||||
|
||||
</wb-module>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faceted-project>
|
||||
<fixed facet="wst.jsdt.web"/>
|
||||
<installed facet="java" version="1.8"/>
|
||||
<installed facet="jst.web" version="3.0"/>
|
||||
<installed facet="jst.jaxrs" version="2.0"/>
|
||||
<installed facet="wst.jsdt.web" version="1.0"/>
|
||||
<installed facet="jst.web" version="4.0"/>
|
||||
<installed facet="java" version="17"/>
|
||||
</faceted-project>
|
||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,15 +1,22 @@
|
|||
# Changelog
|
||||
# Changelog for "storagehub"
|
||||
|
||||
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.0] - [2021-10-07]
|
||||
## [v2.0.0]
|
||||
|
||||
- ceph as default storage
|
||||
- vre folders can define specific bucket as backend
|
||||
- enunciate docs
|
||||
- dockerization of the service
|
||||
|
||||
## [v1.4.0] 2021-10-07
|
||||
|
||||
- slow query removed from VRE retrieving and recents
|
||||
- incident #22184 solved
|
||||
- incident solved [#22184]
|
||||
|
||||
## [v1.3.2] - [2021-09-28]
|
||||
- fix 22087
|
||||
- fix 22087
|
||||
|
||||
## [v1.3.1] - [2021-09-08]
|
||||
|
||||
|
@ -17,7 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
|
||||
## [v1.3.0] - [2021-03-31]
|
||||
|
||||
- possibility to impersonate people added
|
||||
possibility to impersonate people added
|
||||
|
||||
## [v1.2.5] - [2021-03-11]
|
||||
|
||||
|
@ -41,8 +48,6 @@ method for description update added
|
|||
|
||||
bug on Archive uploader solved
|
||||
|
||||
|
||||
|
||||
## [v1.2.0] - [2020-04-15]
|
||||
|
||||
trash items changes owner on restore
|
||||
|
@ -51,20 +56,14 @@ 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,22 @@
|
|||
# Docker Instruction
|
||||
|
||||
Instruction to generate e run storagehub docker image
|
||||
|
||||
## Dockerfile - DokerCompose
|
||||
|
||||
This image is ready to be deployed in a new environment.
|
||||
The Dockerfile generate an image without configurations (container, service etc.), all the configurations must be provided at image start time.
|
||||
In fact the docker-compose.yml requires 3 environmental variables set at start time: APP_PORT, JACKRABBIT_FOLDER, CONTAINER_SERVICE_FILE_FOLDER.
|
||||
|
||||
```
|
||||
APP_PORT=8080 JACKRABBIT_FOLDER=/data/jackrabbit CONTAINER_SERVICE_FILE_FOLDER=/etc/smartgears-config docker compose up
|
||||
```
|
||||
|
||||
## Dockerfile - DokerCompose standalone
|
||||
|
||||
The image generated from Dockerfile-standalone contains all the configuration to run on a fully isolated container.
|
||||
The docker-compose-standalone.yml contains the declaration of all the services needed (postgres and minio) teking all the configuration from the local ./docker folder
|
||||
|
||||
```
|
||||
docker compose -f docker-compose-standalone.yml up
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
FROM d4science/smartgears-distribution:4.0.1-SNAPSHOT-java17-tomcat10.1.19
|
||||
COPY ./target/storagehub.war /tomcat/webapps/
|
||||
COPY ./docker/storagehub.xml /tomcat/conf/Catalina/localhost/
|
|
@ -0,0 +1,13 @@
|
|||
FROM d4science/smartgears-distribution:4.0.0-SNAPSHOT-java17-tomcat10.1.19
|
||||
|
||||
#install unzip
|
||||
RUN apt-get update && apt-get install unzip
|
||||
|
||||
COPY ./target/storagehub-test-storages.war /tomcat/webapps/storagehub.war
|
||||
COPY ./docker/jackrabbit /app/jackrabbit
|
||||
COPY ./docker/storagehub.xml /tomcat/conf/Catalina/localhost/
|
||||
COPY ./docker/logback.xml /etc/
|
||||
COPY ./docker/local/container.ini /etc/
|
||||
RUN unzip /tomcat/webapps/storagehub.war -d /tomcat/webapps/storagehub
|
||||
RUN rm /tomcat/webapps/storagehub.war
|
||||
#COPY ./docker/local/storage-settings.properties /tomcat/webapps/storagehub/WEB-INF/classes/
|
|
@ -0,0 +1,8 @@
|
|||
FROM smartgears-distribution:4.0.0-java17-tomcat10.1.19
|
||||
COPY ./target/storagehub.war /tomcat/webapps/
|
||||
COPY ./docker/jackrabbit /app/jackrabbit
|
||||
COPY ./docker/storagehub.xml /tomcat/conf/Catalina/localhost/
|
||||
COPY ./docker/logback.xml /etc/
|
||||
COPY ./docker/container.ini /etc/
|
||||
RUN mkdir -p /etc/config/storagehub
|
||||
COPY ./docker/storage-settings.properties /etc/config/storagehub/
|
|
@ -0,0 +1,155 @@
|
|||
// TO REMOVE
|
||||
[nthl:ExternalLink] > nthl:workspaceLeafItem
|
||||
- hl:value (String) mandatory
|
||||
|
||||
[nthl:externalUrl] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:query] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:aquamapsItem] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:timeSeriesItem] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:report] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:reportTemplate] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:workflowReport] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:workflowTemplate] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeMetadata] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeDocument] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeDocumentLink] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeImageDocumentLink] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubePDFDocumentLink] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeImageDocument] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubePDFDocument] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeURLDocument] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:gCubeAnnotation] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:externalResourceLink] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:tabularDataLink] > nthl:workspaceLeafItem
|
||||
|
||||
[nthl:documentAlternativeLink] > nt:base
|
||||
- hl:parentUri (String) mandatory
|
||||
- hl:uri (String) mandatory
|
||||
- hl:name (String) mandatory
|
||||
- hl:mimeType (String) mandatory
|
||||
|
||||
[nthl:documentPartLink] > nthl:documentAlternativeLink
|
||||
|
||||
[nthl:documentItemContent] > nthl:workspaceLeafItemContent
|
||||
- hl:collectionName (String) mandatory
|
||||
- hl:oid (String) mandatory
|
||||
+ hl:metadata (nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
+ hl:annotations (nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
+ hl:alternatives (nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
+ hl:parts (nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
|
||||
[nthl:metadataItemContent] > nthl:workspaceLeafItemContent, nthl:file
|
||||
- hl:schema (String) mandatory
|
||||
- hl:language (String) mandatory
|
||||
- hl:collectionName (String) mandatory
|
||||
- hl:oid (String) mandatory
|
||||
|
||||
[nthl:annotationItemContet] > nthl:workspaceLeafItemContent
|
||||
- hl:oid (String) mandatory
|
||||
+ hl:annotations (nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
|
||||
[nthl:queryItemContent] > nthl:workspaceLeafItemContent
|
||||
- hl:query (String) mandatory
|
||||
- hl:queryType (String) mandatory
|
||||
|
||||
[nthl:aquamapsItemContent] > nthl:workspaceLeafItemContent, nthl:file
|
||||
- hl:mapName (String) mandatory
|
||||
- hl:mapType (String) mandatory
|
||||
- hl:author (String) mandatory
|
||||
- hl:numberOfSpecies (Long) mandatory
|
||||
- hl:boundingBox (String) mandatory
|
||||
- hl:PSOThreshold (Double) mandatory
|
||||
- hl:numberOfImages (Long) mandatory
|
||||
+ hl:images(nt:unstructured)
|
||||
= nt:unstructured
|
||||
mandatory autocreated
|
||||
|
||||
[nthl:timeSeriesItemContent] > nthl:workspaceLeafItemContent, nthl:file
|
||||
- hl:id (String) mandatory
|
||||
- hl:title (String) mandatory
|
||||
- hl:description (String) mandatory
|
||||
- hl:creator (String) mandatory
|
||||
- hl:created (String) mandatory
|
||||
- hl:publisher (String) mandatory
|
||||
- hl:sourceId (String) mandatory
|
||||
- hl:sourceName (String) mandatory
|
||||
- hl:rights (String) mandatory
|
||||
- hl:dimension (Long) mandatory
|
||||
- hl:headerLabels (String)
|
||||
|
||||
[nthl:reportItemContent] > nthl:workspaceLeafItemContent, nthl:file
|
||||
- hl:created (Date) mandatory
|
||||
- hl:lastEdit (Date) mandatory
|
||||
- hl:author (String) mandatory
|
||||
- hl:lastEditBy (String) mandatory
|
||||
- hl:templateName (String) mandatory
|
||||
- hl:numberOfSection (Long) mandatory
|
||||
- hl:status (String) mandatory
|
||||
|
||||
[nthl:reportTemplateContent] > nthl:workspaceLeafItemContent, nthl:file
|
||||
- hl:created (Date) mandatory
|
||||
- hl:lastEdit (Date) mandatory
|
||||
- hl:author (String) mandatory
|
||||
- hl:lastEditBy (String) mandatory
|
||||
- hl:numberOfSection (Long) mandatory
|
||||
- hl:status (String) mandatory
|
||||
|
||||
[nthl:externalResourceLinkContent] > nthl:workspaceLeafItemContent
|
||||
- hl:mimeType (String)
|
||||
- hl:size (long) mandatory
|
||||
- hl:resourceId (String) mandatory
|
||||
- hl:servicePlugin (String) mandatory
|
||||
|
||||
[nthl:tabularDataLinkContent] > nthl:workspaceLeafItemContent
|
||||
- hl:tableID (String) mandatory
|
||||
- hl:tableTemplateID (String) mandatory
|
||||
- hl:provenance (String) mandatory
|
||||
- hl:runtimeResourceID (String) mandatory
|
||||
- hl:operator (String)
|
||||
|
||||
[nthl:smartFolderContent] > nt:base
|
||||
- hl:query (String) mandatory
|
||||
- hl:folderId (String)
|
||||
|
||||
[nthl:folderBulkCreator] > nt:base
|
||||
- hl:folderId (String) mandatory
|
||||
- hl:status (Long)
|
||||
= '0'
|
||||
mandatory autocreated
|
||||
- hl:failures (Long)
|
||||
= '0'
|
||||
mandatory autocreated
|
||||
- hl:requests (Long) mandatory
|
||||
|
||||
[nthl:rootFolderBulkCreator] > nt:folder
|
||||
+ * (nthl:folderBulkCreator)
|
||||
= nthl:folderBulkCreator
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
nodeType to remove on new import from a backup:
|
||||
externalUrl
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
NAME=storagehub
|
||||
PORT=8100
|
||||
DEBUG_PORT=5005
|
||||
debug=false
|
||||
compile=false
|
||||
|
||||
mvn clean package
|
||||
|
||||
docker compose -f docker-compose-standalone.yml build
|
||||
|
||||
docker compose -f docker-compose-standalone.yml up
|
|
@ -1 +0,0 @@
|
|||
${gcube.license}
|
|
@ -1,66 +0,0 @@
|
|||
The gCube System - ${name}
|
||||
--------------------------------------------------
|
||||
|
||||
${description}
|
||||
|
||||
|
||||
${gcube.description}
|
||||
|
||||
${gcube.funding}
|
||||
|
||||
|
||||
Version
|
||||
--------------------------------------------------
|
||||
|
||||
${version} (${buildDate})
|
||||
|
||||
Please see the file named "changelog.xml" in this directory for the release notes.
|
||||
|
||||
|
||||
Authors
|
||||
--------------------------------------------------
|
||||
|
||||
|
||||
* Lucio Lelii (lucio.lelii-AT-isti.cnr.it), CNR Pisa,
|
||||
Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo".
|
||||
|
||||
Maintainers
|
||||
-----------
|
||||
|
||||
|
||||
* Lucio Lelii (lucio.lelii-AT-isti.cnr.it), CNR Pisa,
|
||||
Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo".
|
||||
|
||||
Download information
|
||||
--------------------------------------------------
|
||||
|
||||
Source code is available from SVN:
|
||||
${scm.url}
|
||||
|
||||
Binaries can be downloaded from the gCube website:
|
||||
${gcube.website}
|
||||
|
||||
|
||||
Installation
|
||||
--------------------------------------------------
|
||||
|
||||
Installation documentation is available on-line in the gCube Wiki:
|
||||
${gcube.wikiRoot}/Home_Library_2.0_API_Framework_Specification
|
||||
|
||||
Documentation
|
||||
--------------------------------------------------
|
||||
|
||||
Documentation is available on-line in the gCube Wiki:
|
||||
${gcube.wikiRoot}/StorageHub_API_Framework_Specification
|
||||
|
||||
Support
|
||||
--------------------------------------------------
|
||||
|
||||
Bugs and support requests can be reported in the gCube issue tracking tool:
|
||||
${gcube.issueTracking}
|
||||
|
||||
|
||||
Licensing
|
||||
--------------------------------------------------
|
||||
|
||||
This software is licensed under the terms you may find in the file named "LICENSE" in this directory.
|
|
@ -1,7 +0,0 @@
|
|||
<application mode='online'>
|
||||
<name>StorageHub</name>
|
||||
<group>DataAccess</group>
|
||||
<version>${version}</version>
|
||||
<description>Storage Hub webapp</description>
|
||||
<local-persistence location='target' />
|
||||
</application>
|
|
@ -0,0 +1,50 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
elb:
|
||||
image: haproxy
|
||||
ports:
|
||||
- "8100:8100"
|
||||
volumes:
|
||||
- ./docker/haproxy:/usr/local/etc/haproxy
|
||||
postgres:
|
||||
image: postgres:10.5
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_DB=workspace-db
|
||||
- POSTGRES_USER=ws-db-user
|
||||
- POSTGRES_PASSWORD=dbPwd
|
||||
logging:
|
||||
options:
|
||||
max-size: 10m
|
||||
max-file: "3"
|
||||
ports:
|
||||
- '5423:5432'
|
||||
volumes:
|
||||
- ./postgres-data:/var/lib/postgresql/data
|
||||
- ./sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
|
||||
storagehub:
|
||||
build:
|
||||
dockerfile: ./Dockerfile-local
|
||||
ports:
|
||||
- '8080:8080'
|
||||
- '4954:4954'
|
||||
environment:
|
||||
- ADMINISTRATION_PORT_ENABLED=true
|
||||
- DOMAIN_NAME=docker_domain
|
||||
- JPDA_OPTS="-agentlib:jdwp=transport=dt_socket,address=0.0.0.0:4954,server=y,suspend=n"
|
||||
- JPDA_ADDRESS=*:4954
|
||||
minio:
|
||||
image: minio/minio
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
volumes:
|
||||
- minio_storage:/data
|
||||
environment:
|
||||
MINIO_ROOT_USER: SHUBTEST
|
||||
MINIO_ROOT_PASSWORD: wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
command: server --console-address ":9001" /data
|
||||
|
||||
volumes:
|
||||
minio_storage: {}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16.2
|
||||
restart: always
|
||||
environment:
|
||||
- POSTGRES_DB=workspace-db
|
||||
- POSTGRES_USER=ws-db-user
|
||||
- POSTGRES_PASSWORD=dbPwd
|
||||
logging:
|
||||
options:
|
||||
max-size: 10m
|
||||
max-file: "3"
|
||||
ports:
|
||||
- '5423:5432'
|
||||
volumes:
|
||||
- ./data/postgres-data:/var/lib/postgresql/data
|
||||
copy the sql script to create tables
|
||||
- ./data/sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
|
||||
storagehub:
|
||||
build:
|
||||
dockerfile: Dockerfile-standalone
|
||||
environment:
|
||||
_JAVA_OPTIONS:
|
||||
-Xdebug
|
||||
-agentlib:jdwp=transport=dt_socket,server=y,suspend=${SUSPEND:-n},address=*:5005
|
||||
ports:
|
||||
- '8081:8080'
|
||||
- '5005:5005'
|
||||
volumes:
|
||||
- /tmp:/tomcat/temp
|
||||
|
||||
minio:
|
||||
image: minio/minio
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
volumes:
|
||||
- minio_storage:/data
|
||||
environment:
|
||||
MINIO_ROOT_USER: SHUBTEST
|
||||
MINIO_ROOT_PASSWORD: wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
command: server --console-address ":9001" /data
|
||||
|
||||
volumes:
|
||||
minio_storage: {}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
storagehub:
|
||||
image: d4science/storagehub:latest
|
||||
ports:
|
||||
- '${APP_PORT}:8080'
|
||||
volumes:
|
||||
- ${JACKRABBIT_FOLDER}:/app/jackrabbit
|
||||
- ${SMARTGEARS_CONFIG_FOLDER}:/etc
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
[node]
|
||||
mode = offline
|
||||
hostname = dlib29.isti.cnr.it
|
||||
protocol= http
|
||||
port = 8080
|
||||
infrastructure = gcube
|
||||
authorizeChildrenContext = true
|
||||
publicationFrequencyInSeconds = 60
|
||||
|
||||
[properties]
|
||||
SmartGearsDistribution = 4.0.0-SNAPSHOT
|
||||
SmartGearsDistributionBundle = UnBundled
|
||||
|
||||
[site]
|
||||
country = it
|
||||
location = pisa
|
||||
|
||||
[authorization]
|
||||
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
|
||||
factory.endpoint = https://accounts.cloud-dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
|
||||
credentials.class = org.gcube.smartgears.security.SimpleCredentials
|
||||
credentials.clientID = node-whn-test-uno-d-d4s.d4science.org
|
||||
credentials.secret = 979bd3bc-5cc4-11ec-bf63-0242ac130002
|
|
@ -0,0 +1,18 @@
|
|||
# haproxy.cfg
|
||||
global
|
||||
lua-load /usr/local/etc/haproxy/send_to_all_whnmanager.lua
|
||||
|
||||
frontend http
|
||||
bind *:8100
|
||||
mode http
|
||||
timeout client 10s
|
||||
http-request use-service lua.broadcast_to_nodes if { path /whn-manager meth PUT DELETE }
|
||||
use_backend all
|
||||
|
||||
backend all
|
||||
mode http
|
||||
option httpchk
|
||||
http-check send meth GET uri /storagehub/gcube/resource/health
|
||||
http-check expect status 200
|
||||
server s1 storagehub:8080 check
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
local function broadcast_to_nodes(req)
|
||||
-- Get all servers in the backend
|
||||
local servers = pxn.get_servers("all")
|
||||
|
||||
for _, server in ipairs(servers) do
|
||||
-- Forward the request to each server
|
||||
pxn.http_request({
|
||||
"PUT", -- Method
|
||||
server["address"], -- Address of the server
|
||||
tonumber(server["port"]), -- Port of the server
|
||||
req.method, -- HTTP method
|
||||
req.uri, -- URI
|
||||
req.headers, -- Headers
|
||||
req.body -- Body
|
||||
})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
core.register_service("broadcast_to_nodes", "http", broadcast_to_nodes)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#bootstrap properties for the repository startup servlet.
|
||||
#Fri Jul 21 05:19:29 CEST 2017
|
||||
java.naming.factory.initial=org.apache.jackrabbit.core.jndi.provider.DummyInit$
|
||||
repository.home=jackrabbit
|
||||
rmi.enabled=true
|
||||
repository.config=jackrabbit/repository.xml
|
||||
repository.name=jackrabbit.repository
|
||||
rmi.host=localhost
|
||||
java.naming.provider.url=http\://www.apache.org/jackrabbit
|
||||
jndi.enabled=true
|
||||
rmi.port=0
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
license agreements. See the NOTICE file distributed with this work for additional
|
||||
information regarding copyright ownership. The ASF licenses this file to
|
||||
You under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
|
||||
by applicable law or agreed to in writing, software distributed under the
|
||||
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||
OF ANY KIND, either express or implied. See the License for the specific
|
||||
language governing permissions and limitations under the License. -->
|
||||
<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 2.0//EN" "http://jackrabbit.apache.org/dtd/repository-2.0.dtd">
|
||||
<Repository>
|
||||
<!-- virtual file system where the repository stores global state (e.g.
|
||||
registered namespaces, custom node types, etc.) -->
|
||||
<FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
|
||||
<param name="driver" value="org.postgresql.Driver" />
|
||||
<param name="schema" value="postgresql" />
|
||||
<param name="url" value="jdbc:postgresql://postgres:5432/workspace-db" />
|
||||
<param name="user" value="ws-db-user" />
|
||||
<param name="password" value="dbPwd" />
|
||||
<param name="schemaObjectPrefix" value="rep_" />
|
||||
</FileSystem>
|
||||
<!-- data store configuration -->
|
||||
<DataStore class="org.apache.jackrabbit.core.data.db.DbDataStore">
|
||||
<param name="driver" value="org.postgresql.Driver" />
|
||||
<param name="databaseType" value="postgresql" />
|
||||
<param name="url" value="jdbc:postgresql://postgres:5432/workspace-db" />
|
||||
<param name="user" value="ws-db-user" />
|
||||
<param name="password" value="dbPwd" />
|
||||
<param name="minRecordLength" value="1024" />
|
||||
<param name="maxConnections" value="3" />
|
||||
<param name="copyWhenReading" value="true" />
|
||||
<param name="tablePrefix" value="datastore_" />
|
||||
<param name="schemaObjectPrefix" value="" />
|
||||
</DataStore>
|
||||
<!-- security configuration -->
|
||||
<Security appName="Jackrabbit">
|
||||
<SecurityManager class="org.apache.jackrabbit.core.DefaultSecurityManager" />
|
||||
<AccessManager class="org.apache.jackrabbit.core.security.DefaultAccessManager" />
|
||||
<LoginModule class="org.apache.jackrabbit.core.security.authentication.DefaultLoginModule">
|
||||
<param name="adminId" value="admin" />
|
||||
<param name="adminPassword" value="admin" />
|
||||
</LoginModule>
|
||||
</Security>
|
||||
<!-- location of workspaces root directory and name of default workspace -->
|
||||
<Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default" />
|
||||
<Workspace name="${wsp.name}">
|
||||
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
|
||||
<param name="path" value="${wsp.home}" />
|
||||
</FileSystem>
|
||||
<PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
|
||||
<param name="driver" value="org.postgresql.Driver" />
|
||||
<param name="url" value="jdbc:postgresql://postgres:5432/workspace-db" />
|
||||
<param name="schema" value="postgresql" />
|
||||
<param name="user" value="ws-db-user" />
|
||||
<param name="password" value="dbPwd" />
|
||||
<param name="schemaObjectPrefix" value="pm_${wsp.name}_" />
|
||||
<param name="bundleCacheSize" value="600" />
|
||||
<param name="errorHandling" value="IGNORE_MISSING_BLOBS" />
|
||||
<param name="consistencyFix" value="false" />
|
||||
<param name="consistencyCheck" value="false" />
|
||||
</PersistenceManager>
|
||||
<!-- Search index and the file system it uses. class: FQN of class implementing
|
||||
the QueryHandler interface -->
|
||||
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
|
||||
<param name="path" value="${wsp.home}/index" />
|
||||
<param name="supportHighlighting" value="true" />
|
||||
<param name="autoRepair" value="true" />
|
||||
<param name="onWorkspaceInconsistency" value="log" />
|
||||
<param name="indexingConfiguration" value="${rep.home}/indexing_configuration.xml" />
|
||||
<param name="resultFetchSize" value="50" />
|
||||
<param name="cacheSize" value="100000" />
|
||||
<param name="enableConsistencyCheck" value="false" />
|
||||
<param name="forceConsistencyCheck" value="false" />
|
||||
</SearchIndex>
|
||||
</Workspace>
|
||||
<!-- Configures the versioning -->
|
||||
<Versioning rootPath="${rep.home}/version">
|
||||
<!-- Configures the filesystem to use for versioning for the respective
|
||||
persistence manager -->
|
||||
<FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
|
||||
<param name="path" value="${rep.home}/version" />
|
||||
</FileSystem>
|
||||
<PersistenceManager class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
|
||||
<param name="driver" value="org.postgresql.Driver" />
|
||||
<param name="url" value="jdbc:postgresql://postgres:5432/workspace-db" />
|
||||
<param name="schema" value="postgresql" />
|
||||
<param name="user" value="ws-db-user" />
|
||||
<param name="password" value="dbPwd" />
|
||||
<param name="schemaObjectPrefix" value="pm_version_" />
|
||||
<param name="bundleCacheSize" value="600" />
|
||||
<param name="consistencyFix" value="false" />
|
||||
<param name="consistencyCheck" value="false" />
|
||||
</PersistenceManager>
|
||||
</Versioning>
|
||||
<!-- Cluster configuration -->
|
||||
<!-- Cluster id="storagehub1.d4science.org" syncDelay="2000">
|
||||
<Journal class="org.apache.jackrabbit.core.journal.DatabaseJournal">
|
||||
<param name="driver" value="org.postgresql.Driver" />
|
||||
<param name="url" value="jdbc:postgresql://postgres/workspace-db" />
|
||||
<param name="databaseType" value="postgresql" />
|
||||
<param name="schemaObjectPrefix" value="journal_" />
|
||||
<param name="user" value="ws-db-user" />
|
||||
<param name="password" value="dbPwd" />
|
||||
<param name="revision" value="${rep.home}/revision.log" />
|
||||
<param name="janitorEnabled" value="false"/>
|
||||
<set to true if you want to daily clean the journal table https://wiki.apache.org/jackrabbit/Clustering#Removing_Old_Revisions>
|
||||
</Journal>
|
||||
</Cluster > -->
|
||||
</Repository>
|
|
@ -0,0 +1,23 @@
|
|||
[node]
|
||||
mode = offline
|
||||
hostname = dlib29.isti.cnr.it
|
||||
protocol= http
|
||||
port = 8080
|
||||
infrastructure = gcube
|
||||
authorizeChildrenContext = true
|
||||
publicationFrequencyInSeconds = 60
|
||||
|
||||
[properties]
|
||||
SmartGearsDistribution = 4.0.0-SNAPSHOT
|
||||
SmartGearsDistributionBundle = UnBundled
|
||||
|
||||
[site]
|
||||
country = it
|
||||
location = pisa
|
||||
|
||||
[authorization]
|
||||
factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory
|
||||
factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
|
||||
credentials.class = org.gcube.smartgears.security.SimpleCredentials
|
||||
credentials.clientID = node-whn-test-uno-d-d4s.d4science.org
|
||||
credentials.secret = 979bd3bc-5cc4-11ec-bf63-0242ac130002
|
|
@ -0,0 +1,10 @@
|
|||
default.bucketName = storagehub-dev
|
||||
default.key = SHUBTEST
|
||||
default.secret = wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
default.url = minio:9000
|
||||
default.createBucket = true
|
||||
volatile.bucketName = storagehub-volatile-dev
|
||||
volatile.key = SHUBTEST
|
||||
volatile.secret = wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
volatile.url = minio:9000
|
||||
volatile.createBucket = true
|
|
@ -0,0 +1,25 @@
|
|||
<configuration scan="true" debug="true">
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>Ï
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
||||
|
||||
<logger name="org.gcube" level="DEBUG" />
|
||||
<logger name="org.gcube.smartgears" level="TRACE" />
|
||||
<logger name="org.gcube.smartgears.handlers" level="TRACE"/>
|
||||
<logger name="org.gcube.common.events" level="WARN" />
|
||||
<logger name="org.gcube.data.publishing" level="ERROR" />
|
||||
<logger name="org.gcube.documentstore" level="ERROR" />
|
||||
<logger name="org.gcube.common.core.publisher.is.legacy" level="TRACE" />
|
||||
<logger name="org.gcube.data.access" level="TRACE" />
|
||||
<logger name="org.gcube.data.access.storagehub.handlers" level="DEBUG"/>
|
||||
|
||||
<root level="WARN">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,6 @@
|
|||
${{adminId}}=workspace
|
||||
${{adminPwd}}=gcube
|
||||
${{db-host}}=postgres
|
||||
${{ws-db}}=workspace-db
|
||||
${{dbUser}}=ws-db-user
|
||||
${{dbPwd}}=dbPwd
|
|
@ -0,0 +1,10 @@
|
|||
default.bucketName=storagehub-dev
|
||||
default.key=SHUBTEST
|
||||
default.secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
default.url=http://minio:9000/
|
||||
default.createBucket=true
|
||||
volatile.bucketName=storagehub-volatile-dev
|
||||
volatile.key=SHUBTEST
|
||||
volatile.secret=wJalrXUtnFEMI/K7MDENG/bPxRfiCY
|
||||
volatile.url=http://minio:9000/
|
||||
volatile.createBucket=true
|
|
@ -0,0 +1,10 @@
|
|||
<Context path="/storagehub">
|
||||
<Resource
|
||||
name="jcr/repository"
|
||||
auth="Container"
|
||||
type="javax.jcr.Repository"
|
||||
factory="org.apache.jackrabbit.core.jndi.BindableRepositoryFactory"
|
||||
configFilePath="/app/jackrabbit/repository.xml"
|
||||
repHomeDir="/app/jackrabbit/workspaces"
|
||||
/>
|
||||
</Context>
|
|
@ -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>
|
|
@ -0,0 +1,6 @@
|
|||
name: StorageHub
|
||||
group: DataAccess
|
||||
version: ${version}
|
||||
description: ${description}
|
||||
excludes:
|
||||
- path: /workspace/api-docs/*
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program and the accompanying materials are made available under the
|
||||
terms of the Eclipse Distribution License v. 1.0, which is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
-->
|
||||
<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
|
||||
version="4.0" bean-discovery-mode="all">
|
||||
|
||||
</beans>
|
|
@ -2,11 +2,7 @@
|
|||
<web-app>
|
||||
<context-param>
|
||||
<param-name>admin-username</param-name>
|
||||
<param-value>workspacerep.imarine</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>admin-pwd</param-name>
|
||||
<param-value>gcube2010*onan</param-value>
|
||||
<param-value>admin</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>resolver-basepath</param-name>
|
408
pom.xml
408
pom.xml
|
@ -1,143 +1,121 @@
|
|||
<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>
|
||||
<version>1.2.0</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.gcube.data.access</groupId>
|
||||
<artifactId>storagehub</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<version>2.0.0</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>
|
||||
<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.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>
|
||||
|
||||
<jackrabbit.version>2.22.0</jackrabbit.version>
|
||||
<jackson.version>2.15.3</jackson.version>
|
||||
<slf4j.version>2.0.12</slf4j.version>
|
||||
<tika.version>2.6.0</tika.version>
|
||||
<aspectj-plugin.version>1.14.0</aspectj-plugin.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.17.1</enunciate.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<java_version>17</java_version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.gcube.distribution</groupId>
|
||||
<artifactId>gcube-smartgears-bom</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>4.0.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.8.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
|
||||
</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,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.common</groupId>
|
||||
<artifactId>storagehub-model</artifactId>
|
||||
<version>[1.0.0,2.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.data.access</groupId>
|
||||
<artifactId>storagehub-script-utils</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT,2.0.0)</version>
|
||||
<version>[2.0.0-SNAPSHOT,3.0.0)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>itextpdf</artifactId>
|
||||
<version>5.5.13.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>
|
||||
</dependency>
|
||||
|
||||
<!-- JCR dependencies -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.jcr</groupId>
|
||||
<artifactId>jcr</artifactId>
|
||||
|
@ -153,79 +131,74 @@
|
|||
<artifactId>jackrabbit-core</artifactId>
|
||||
<version>${jackrabbit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jackrabbit</groupId>
|
||||
<artifactId>jackrabbit-jcr-server</artifactId>
|
||||
<version>${jackrabbit.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- <dependency> <groupId>org.apache.jackrabbit</groupId>
|
||||
<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>
|
||||
<version>${tika.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/net.bull.javamelody/javamelody-core -->
|
||||
<dependency>
|
||||
<groupId>net.bull.javamelody</groupId>
|
||||
<artifactId>javamelody-core</artifactId>
|
||||
<version>1.82.0</version>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-parsers-standard-package</artifactId>
|
||||
<version>${tika.version}</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>
|
||||
|
||||
|
||||
<!-- jersey & weld -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
|
||||
<!--
|
||||
https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
|
||||
<dependency>
|
||||
<groupId>javax.interceptor</groupId>
|
||||
<artifactId>javax.interceptor-api</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<groupId>jakarta.interceptor</groupId>
|
||||
<artifactId>jakarta.interceptor-api</artifactId>
|
||||
<version>2.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
|
||||
<dependency>
|
||||
<groupId>javax.enterprise</groupId>
|
||||
<artifactId>cdi-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<groupId>jakarta.enterprise</groupId>
|
||||
<artifactId>jakarta.enterprise.cdi-api</artifactId>
|
||||
<version>4.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
<groupId>jakarta.ws.rs</groupId>
|
||||
<artifactId>jakarta.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet</artifactId>
|
||||
|
@ -234,14 +207,12 @@
|
|||
<groupId>org.glassfish.jersey.containers</groupId>
|
||||
<artifactId>jersey-container-servlet-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
|
||||
<!--
|
||||
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>
|
||||
|
@ -254,92 +225,58 @@
|
|||
<groupId>org.glassfish.jersey.ext.cdi</groupId>
|
||||
<artifactId>jersey-cdi1x-servlet</artifactId>
|
||||
</dependency>
|
||||
<!--
|
||||
https://mvnrepository.com/artifact/org.jboss.weld.servlet/weld-servlet-core -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.servlet</groupId>
|
||||
<artifactId>weld-servlet-core</artifactId>
|
||||
<version>3.1.0.Final</version>
|
||||
<version>5.1.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
|
||||
<dependency>
|
||||
<groupId>org.jboss</groupId>
|
||||
<artifactId>jandex</artifactId>
|
||||
<version>2.2.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
|
||||
<!--
|
||||
https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.core</groupId>
|
||||
<artifactId>jersey-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-multipart</artifactId>
|
||||
</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>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.contentmanagement</groupId>
|
||||
<artifactId>storage-manager-wrapper</artifactId>
|
||||
<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>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.7.0</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>
|
||||
<version>1.22</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>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
|
@ -352,111 +289,103 @@
|
|||
<version>10.8.2.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.jeeunit</groupId>
|
||||
<artifactId>jeeunit</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.vlkan.rfos</groupId>
|
||||
<artifactId>rotating-fos</artifactId>
|
||||
<version>0.9.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-to-slf4j -->
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j -->
|
||||
<dependency>
|
||||
<groupId>org.jboss.weld.se</groupId>
|
||||
<artifactId>weld-se</artifactId>
|
||||
<version>2.2.10.Final</version>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>2.0.7</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>
|
||||
<!-- Storage dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.gcube.contentmanagement</groupId>
|
||||
<artifactId>storage-manager-core</artifactId>
|
||||
<version>[4.0.0-SNAPSHOT,5.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.gcube.contentmanagement</groupId>
|
||||
<artifactId>storage-manager-wrapper</artifactId>
|
||||
<version>[4.0.0-SNAPSHOT,5.0.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.763</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/io.minio/minio
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>8.3.3</version>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<version>1.16.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework</groupId>
|
||||
<artifactId>jersey-test-framework-core</artifactId>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.m2e</groupId>
|
||||
<artifactId>lifecycle-mapping</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<lifecycleMappingMetadata>
|
||||
<pluginExecutions>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<versionRange>[1.0,)</versionRange>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<execute />
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>aspectj-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<version>${aspectj-plugin.version}</version>
|
||||
<configuration>
|
||||
<complianceLevel>1.8</complianceLevel>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<complianceLevel>17</complianceLevel>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<aspectLibraries>
|
||||
<aspectLibrary>
|
||||
<groupId>org.gcube.common</groupId>
|
||||
|
@ -464,10 +393,18 @@
|
|||
</aspectLibrary>
|
||||
</aspectLibraries>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>1.9.21.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile</goal> <!-- use this goal to weave
|
||||
all your main classes -->
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
@ -486,22 +423,41 @@
|
|||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Enunciate Maven plugin -->
|
||||
<plugin>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-maven-plugin</artifactId>
|
||||
<version>${enunciate.version}</version>
|
||||
<configuration></configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>assemble</id>
|
||||
<goals>
|
||||
<goal>assemble</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Copy Enunciate Documentation from your-application/docs to
|
||||
your-application.war -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-profile</id>
|
||||
<id>copy-enunciate-docs</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<outputDirectory>${webappDirectory}</outputDirectory>
|
||||
<outputDirectory>target</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${distroDirectory}</directory>
|
||||
<targetPath>
|
||||
${project.build.directory}/${project.artifactId}/api-docs</targetPath>
|
||||
<directory>
|
||||
${project.build.directory}/api-docs</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
@ -511,5 +467,35 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
<finalName>storagehub-test-storages</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<target>
|
||||
<copy todir="${basedir}/target/classes">
|
||||
<fileset
|
||||
dir="${basedir}/target/test-classes"
|
||||
includes="org/gcube/data/access/storages/**/*" />
|
||||
</copy>
|
||||
</target>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -2,8 +2,8 @@ package org.gcube.data.access.storagehub;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
@ -49,7 +49,7 @@ public class AuthorizationChecker {
|
|||
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);
|
||||
|
@ -74,20 +74,20 @@ public class AuthorizationChecker {
|
|||
//SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
|
||||
//if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return;
|
||||
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
||||
List<ACL> acls = aclManager.get(item, session);
|
||||
List<ACL> acls = aclManager.getByItem(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());
|
||||
log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPrincipal());
|
||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPrincipal());
|
||||
|
||||
if (authorizable==null) {
|
||||
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPricipal());
|
||||
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPrincipal());
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) return;
|
||||
if (!authorizable.isGroup() && entry.getPrincipal().equals(userToCheck)) return;
|
||||
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
|
||||
}catch (Throwable e) {
|
||||
log.warn("someting went wrong checking authorizations",e);
|
||||
|
@ -103,13 +103,13 @@ public class AuthorizationChecker {
|
|||
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();
|
||||
if (item instanceof FolderItem folder)
|
||||
return folder.isPublicItem();
|
||||
else return false;
|
||||
} else {
|
||||
if (item instanceof FolderItem)
|
||||
if (item instanceof FolderItem folder)
|
||||
try {
|
||||
return ((FolderItem) item).isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
|
||||
return (folder.isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(folder.getParentId(), session, Excludes.ALL)));
|
||||
}catch (Throwable e) {
|
||||
log.warn("error checking public parents",e);
|
||||
return false;
|
||||
|
@ -136,13 +136,13 @@ public class AuthorizationChecker {
|
|||
if (item.isShared()) {
|
||||
|
||||
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
|
||||
List<ACL> acls = aclManager.get(item, session);
|
||||
List<ACL> acls = aclManager.getByItem(item, session);
|
||||
UserManager userManager = ((JackrabbitSession) session).getUserManager();
|
||||
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
|
||||
//put it in a different method
|
||||
for (ACL entry: acls) {
|
||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
|
||||
if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
||||
Authorizable authorizable = userManager.getAuthorizable(entry.getPrincipal());
|
||||
if ((!authorizable.isGroup() && entry.getPrincipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
|
||||
for (AccessType privilege : entry.getAccessTypes()){
|
||||
if (isNewItem && privilege!=AccessType.READ_ONLY)
|
||||
return;
|
||||
|
@ -194,10 +194,10 @@ public class AuthorizationChecker {
|
|||
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+": it's not a valid StorageHub node");
|
||||
|
||||
if (item.isShared()) {
|
||||
List<ACL> acls = aclManager.get(item, session);
|
||||
List<ACL> acls = aclManager.getByItem(item, session);
|
||||
|
||||
for (ACL entry: acls) {
|
||||
if (entry.getPricipal().equals(userToCheck)) {
|
||||
if (entry.getPrincipal().equals(userToCheck)) {
|
||||
for (AccessType privilege : entry.getAccessTypes()){
|
||||
if (privilege==AccessType.ADMINISTRATOR)
|
||||
return;
|
||||
|
|
|
@ -3,6 +3,8 @@ package org.gcube.data.access.storagehub;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jcr.SimpleCredentials;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
|
||||
|
@ -17,6 +19,8 @@ public class Constants {
|
|||
|
||||
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe";
|
||||
|
||||
//public static final String MYSHARED_PARENT_NAME = "MyShared";
|
||||
|
||||
public static final String SHARED_FOLDER_PATH = "/Share";
|
||||
|
||||
public static final String WORKSPACE_ROOT_FOLDER_NAME ="Workspace";
|
||||
|
@ -25,10 +29,6 @@ public class Constants {
|
|||
|
||||
public static final String QUERY_LANGUAGE ="JCR-SQL2";
|
||||
|
||||
public static final String ADMIN_PARAM_NAME ="admin-username";
|
||||
|
||||
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
||||
|
||||
public static final String HOME_VERSION_PROP = "hl:version";
|
||||
|
||||
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
|
@ -36,4 +36,9 @@ public class Constants {
|
|||
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);
|
||||
|
||||
public static final String ADMIN_USER ="admin";
|
||||
|
||||
public static final SimpleCredentials JCR_CREDENTIALS = new SimpleCredentials(ADMIN_USER,"admin".toCharArray());
|
||||
|
||||
}
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MultipleOutputStream {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(MultipleOutputStream.class);
|
||||
|
||||
private MyPipedInputStream[] pipedInStreams;
|
||||
|
||||
private InputStream is;
|
||||
|
||||
private MyPipedOututStream[] pipedOutStreams;
|
||||
|
||||
private int index=0;
|
||||
|
||||
public MultipleOutputStream(InputStream is, int number) throws IOException{
|
||||
this.is = is;
|
||||
|
||||
|
||||
logger.debug("requested {} piped streams ",number);
|
||||
|
||||
pipedInStreams = new MyPipedInputStream[number];
|
||||
pipedOutStreams = new MyPipedOututStream[number];
|
||||
|
||||
for (int i =0; i<number; i++) {
|
||||
pipedOutStreams[i] = new MyPipedOututStream();
|
||||
pipedInStreams[i] = new MyPipedInputStream(pipedOutStreams[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void startWriting() throws IOException{
|
||||
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
byte[] buf = new byte[1024*64];
|
||||
int read=-1;
|
||||
int writeTot = 0;
|
||||
while ((read =bis.read(buf))!=-1){
|
||||
for (int i=0; i< pipedInStreams.length; i++) {
|
||||
if (!pipedInStreams[i].isClosed()) {
|
||||
pipedOutStreams[i].write(buf, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
writeTot+= read;
|
||||
if (allOutStreamClosed())
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
for (int i=0; i< pipedOutStreams.length; i++) {
|
||||
if (!pipedOutStreams[i].isClosed()) {
|
||||
logger.debug("closing outputstream {}",i);
|
||||
pipedOutStreams[i].close();
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("total written {} ",writeTot);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean allOutStreamClosed() {
|
||||
for (int i=0; i<pipedOutStreams.length; i++) {
|
||||
if (!pipedOutStreams[i].isClosed())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized InputStream get() {
|
||||
logger.debug("requesting piped streams {}",index);
|
||||
if (index>=pipedInStreams.length) return null;
|
||||
return pipedInStreams[index++];
|
||||
}
|
||||
|
||||
|
||||
public class MyPipedOututStream extends PipedOutputStream{
|
||||
|
||||
boolean close = false;
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.close = true;
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the close
|
||||
*/
|
||||
public boolean isClosed() {
|
||||
return close;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
try{
|
||||
super.write(b, off, len);
|
||||
}catch(IOException io){
|
||||
this.close = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class MyPipedInputStream extends PipedInputStream{
|
||||
|
||||
boolean close = false;
|
||||
|
||||
public MyPipedInputStream(PipedOutputStream src) throws IOException {
|
||||
super(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.close = true;
|
||||
logger.debug(Thread.currentThread().getName()+" close MyPipedInputStream");
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the close
|
||||
*/
|
||||
public boolean isClosed() {
|
||||
return close;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,10 +1,6 @@
|
|||
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.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.glassfish.jersey.server.monitoring.ApplicationEvent;
|
||||
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
|
||||
import org.glassfish.jersey.server.monitoring.RequestEvent;
|
||||
|
@ -12,21 +8,21 @@ import org.glassfish.jersey.server.monitoring.RequestEventListener;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
|
||||
@Provider
|
||||
public class MyApplicationListener implements ApplicationEventListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
StoragehubRepository repository = StoragehubRepository.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();
|
||||
repository.shutdown();
|
||||
log.info("Jackrabbit repository stopped");
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
@ -46,8 +46,13 @@ public class PathUtil {
|
|||
}
|
||||
|
||||
public Path getSharedWithMePath(String login){
|
||||
return Paths.append(getWorkspacePath(login),Constants.SHARED_WITH_ME_PARENT_NAME);
|
||||
return Paths.append(getHome(login),Constants.SHARED_WITH_ME_PARENT_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
public Path getMySharedPath(String login){
|
||||
return Paths.append(getHome(login),Constants.MYSHARED_PARENT_NAME);
|
||||
}*/
|
||||
|
||||
public Path getVREsPath(String login, Session session) throws RepositoryException {
|
||||
Path home = getHome(login);
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
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
|
||||
public class RepositoryInitializerImpl implements RepositoryInitializer{
|
||||
|
||||
private Repository repository;
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized Repository getRepository(){
|
||||
return repository;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -4,8 +4,8 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.StreamingOutput;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||
import org.gcube.contentmanager.storageclient.model.protocol.smp.Handler;
|
||||
import org.gcube.contentmanager.storageclient.wrapper.AccessType;
|
||||
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
|
||||
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StorageFactory {
|
||||
|
||||
public final static String SERVICE_NAME = "home-library";
|
||||
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
|
||||
|
||||
private static Map<String, IClient> clientUserMap = new WeakHashMap<String, IClient>();
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(StorageFactory.class);
|
||||
|
||||
public static IClient getGcubeStorage(){
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
if (!clientUserMap.containsKey(login)){
|
||||
IClient storage = new StorageClient(SERVICE_CLASS, SERVICE_NAME,
|
||||
login, AccessType.SHARED, MemoryType.PERSISTENT).getClient();
|
||||
log.info("******* Storage activateProtocol for Storage **********");
|
||||
Handler.activateProtocol();
|
||||
clientUserMap.put(login, storage);
|
||||
return storage;
|
||||
} else return clientUserMap.get(login);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,17 +3,19 @@ package org.gcube.data.access.storagehub;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Application;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.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.DocsGenerator;
|
||||
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.StorageManager;
|
||||
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;
|
||||
|
@ -36,6 +38,8 @@ public class StorageHub extends Application {
|
|||
classes.add(GroupManager.class);
|
||||
classes.add(ScriptManager.class);
|
||||
classes.add(MessageManager.class);
|
||||
classes.add(StorageManager.class);
|
||||
classes.add(DocsGenerator.class);
|
||||
classes.add(MultiPartFeature.class);
|
||||
classes.add(SerializableErrorEntityTextWriter.class);
|
||||
classes.add(MyApplicationListener.class);
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.gcube.common.storagehub.model.exporter.DumpData;
|
||||
import org.gcube.data.access.storagehub.handlers.DataHandler;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.smartgears.ApplicationManager;
|
||||
import org.gcube.smartgears.ContextProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StorageHubApplicationManager implements ApplicationManager {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(StorageHubApplicationManager.class);
|
||||
|
||||
private boolean alreadyShutDown = false;
|
||||
private boolean alreadyInit = false;
|
||||
|
||||
|
||||
private StoragehubRepository repository;
|
||||
|
||||
// private static NotificationClient notificationClient;
|
||||
|
||||
/*
|
||||
* public static NotificationClient getNotificationClient() { return
|
||||
* notificationClient; }
|
||||
*/
|
||||
|
||||
public StorageHubApplicationManager() {
|
||||
repository = StoragehubRepository.repository;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onInit() {
|
||||
|
||||
logger.info("onInit Called on storagehub");
|
||||
try {
|
||||
if (!alreadyInit) {
|
||||
logger.info("jackrabbit initialization started");
|
||||
|
||||
repository.initContainerAtFirstStart();
|
||||
|
||||
DataHandler dh = new DataHandler();
|
||||
|
||||
Path shubSpecificConf = ContextProvider.get().appSpecificConfigurationFolder();
|
||||
Path importPath = Paths.get(shubSpecificConf.toString(), "import");
|
||||
Path mainFileImportPath = Paths.get(importPath.toString(), "data.json");
|
||||
if (importPath.toFile().exists() && mainFileImportPath.toFile().exists()) {
|
||||
JackrabbitSession session = null;
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
DumpData data = mapper.readValue(mainFileImportPath.toFile(), DumpData.class);
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
dh.importData((JackrabbitSession) session, data);
|
||||
session.save();
|
||||
} catch (RepositoryException e) {
|
||||
logger.error("error importing data", e);
|
||||
} catch (IOException je) {
|
||||
logger.error("error parsing json data, invalid schema file", je);
|
||||
} finally {
|
||||
if (session != null)
|
||||
session.logout();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
alreadyInit = true;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.error("unexpected error initiliazing storagehub", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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,41 +0,0 @@
|
|||
package org.gcube.data.access.storagehub;
|
||||
|
||||
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
import org.gcube.smartgears.ApplicationManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StorageHubAppllicationManager implements ApplicationManager {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(StorageHubAppllicationManager.class);
|
||||
|
||||
private boolean alreadyShutDown = false;
|
||||
|
||||
|
||||
public static RepositoryInitializer repository;
|
||||
|
||||
@Override
|
||||
public synchronized void onInit() {
|
||||
logger.info("jackrabbit initialization started");
|
||||
try {
|
||||
repository = new RepositoryInitializerImpl();
|
||||
} catch (Exception e) {
|
||||
logger.error("ERROR INITIALIZING REPOSITORY",e);
|
||||
}
|
||||
repository.getRepository();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onShutdown() {
|
||||
if (!alreadyShutDown)
|
||||
try {
|
||||
logger.info("jackrabbit is shutting down");
|
||||
repository.shutdown();
|
||||
alreadyShutDown= true;
|
||||
} catch (Exception e) {
|
||||
logger.warn("the database was not shutdown properly",e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import java.io.OutputStream;
|
|||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
@ -30,18 +31,24 @@ import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
|||
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.ExternalLink;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||
import org.gcube.common.storagehub.model.items.GenericFileItem;
|
||||
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.storages.MetaInfo;
|
||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||
import org.gcube.common.storagehub.model.types.FolderInfoType;
|
||||
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.items.builders.FolderCreationParameters;
|
||||
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
|
||||
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
|
||||
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -72,11 +79,25 @@ public class Utils {
|
|||
return digest;
|
||||
}
|
||||
|
||||
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
|
||||
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
|
||||
public static long getItemCount(Node parent, boolean showHidden, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{
|
||||
return getItemList(parent, Excludes.ALL, null, showHidden, itemTypePredicate).size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static FolderInfoType getFolderInfo(Node parent) throws RepositoryException, BackendGenericError{
|
||||
FolderInfoType info = new FolderInfoType(0, 0);
|
||||
List<Item> items = getItemList(parent, Excludes.GET_ONLY_CONTENT, null, false, null);
|
||||
for (Item item: items)
|
||||
if (item instanceof FolderItem) {
|
||||
FolderInfoType fit = getFolderInfo((Node) item.getRelatedNode());
|
||||
info.setCount(info.getCount() + fit.getCount());
|
||||
info.setSize(info.getSize() + fit.getSize());
|
||||
} else if (item instanceof AbstractFileItem gfi)
|
||||
info.setSize(info.getSize() + gfi.getContent().getSize());
|
||||
info.setCount(info.getCount() + items.size());
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
public static void acquireLockWithWait(Session ses, String nodePath, boolean isDeep, String login, int maxTries) throws RepositoryException, ItemLockedException {
|
||||
|
||||
Lock lock = null;
|
||||
|
@ -101,7 +122,7 @@ 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{
|
||||
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, ItemTypePredicate itemTypePredicate, String nameParam) throws RepositoryException, BackendGenericError{
|
||||
String xpath = String.format("/jcr:root%s//element(*,nthl:workspaceItem)[jcr:like(fn:lower-case(@jcr:title), '%s')]",ISO9075.encodePath(parent.getPath()), nameParam.toLowerCase());
|
||||
|
||||
//String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
|
||||
|
@ -125,26 +146,26 @@ public class Utils {
|
|||
|
||||
};
|
||||
|
||||
return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, nodeTypeToInclude);
|
||||
return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, itemTypePredicate);
|
||||
}
|
||||
|
||||
|
||||
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(Node parent, List<String> excludes, Range range, boolean showHidden, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{
|
||||
return getItemList(null, parent, excludes, range, showHidden, itemTypePredicate);
|
||||
}
|
||||
|
||||
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{
|
||||
public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, ItemTypePredicate itemTypePredicate) 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);
|
||||
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, itemTypePredicate);
|
||||
}
|
||||
|
||||
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{
|
||||
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, ItemTypePredicate itemTypePredicate) 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();
|
||||
|
@ -171,7 +192,7 @@ public class Utils {
|
|||
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);
|
||||
T item = node2Item.getFilteredItem(current, excludes, itemTypePredicate);
|
||||
if (item==null || (item.isTrashed() && excludeTrashed)) continue;
|
||||
returnList.add(item);
|
||||
}
|
||||
|
@ -188,7 +209,7 @@ public class Utils {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||
byte[] buffer = new byte[2048];
|
||||
|
@ -211,19 +232,20 @@ public class Utils {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
|
||||
String escapedName = Text.escapeIllegalJcrChars(name);
|
||||
try {
|
||||
destination.getNode(name);
|
||||
destination.getNode(escapedName);
|
||||
}catch(PathNotFoundException pnf) {
|
||||
return Text.escapeIllegalJcrChars(name);
|
||||
return escapedName;
|
||||
} catch (Exception e) {
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
|
||||
try {
|
||||
String filename = FilenameUtils.getBaseName(name);
|
||||
String ext = FilenameUtils.getExtension(name);
|
||||
String filename = FilenameUtils.getBaseName(escapedName);
|
||||
String ext = FilenameUtils.getExtension(escapedName);
|
||||
|
||||
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
|
||||
|
||||
|
@ -240,20 +262,23 @@ public class Utils {
|
|||
|
||||
|
||||
String newName = ext.isEmpty()? String.format("%s(%d)", filename,maxval+1) : String.format("%s(%d).%s", filename,maxval+1, ext) ;
|
||||
return Text.escapeIllegalJcrChars(newName);
|
||||
return newName;
|
||||
} catch (Exception e) {
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler) throws StorageHubException {
|
||||
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler, boolean isInternalWSFolder) throws StorageHubException {
|
||||
logger.debug("creating folder {} in {}", params.getName(), params.getParentId());
|
||||
|
||||
|
||||
Node destinationNode;
|
||||
FolderItem destinationItem;
|
||||
try {
|
||||
destinationNode = params.getSession().getNodeByIdentifier(params.getParentId());
|
||||
}catch (RepositoryException e) {
|
||||
destinationItem = (FolderItem) new Node2ItemConverter().getItem(destinationNode, Excludes.ALL);
|
||||
}catch (RepositoryException e) {
|
||||
logger.error("id not found",e);
|
||||
throw new IdNotFoundException(params.getParentId());
|
||||
}
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName());
|
||||
|
@ -263,6 +288,20 @@ public class Utils {
|
|||
item.setName(uniqueName);
|
||||
item.setTitle(uniqueName);
|
||||
item.setDescription(params.getDescription());
|
||||
|
||||
if (isInternalWSFolder) {
|
||||
item.setBackend(StorageBackendHandler.getDefaultPayloadForFolder());
|
||||
} else {
|
||||
|
||||
if (params.getBackend() != null)
|
||||
item.setBackend(params.getBackend());
|
||||
else {
|
||||
if (destinationItem.getBackend() != null)
|
||||
item.setBackend(destinationItem.getBackend());
|
||||
else
|
||||
item.setBackend(StorageBackendHandler.getDefaultPayloadForFolder());
|
||||
}
|
||||
}
|
||||
//TODO: item.setExternalStorage();
|
||||
//item.setCreationTime(now);
|
||||
|
||||
|
@ -312,6 +351,7 @@ public class Utils {
|
|||
|
||||
|
||||
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
|
||||
|
||||
if (accountingHandler!=null) {
|
||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
|
||||
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
|
||||
|
@ -346,5 +386,11 @@ public class Utils {
|
|||
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||
}
|
||||
|
||||
public static void setContentFromMetaInfo(AbstractFileItem item, MetaInfo contentInfo) {
|
||||
item.getContent().setSize(contentInfo.getSize());
|
||||
item.getContent().setRemotePath(contentInfo.getRemotePath());
|
||||
item.getContent().setSize(contentInfo.getSize());
|
||||
item.getContent().setPayloadBackend(contentInfo.getPayloadBackend());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,21 +4,17 @@ import java.util.Calendar;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.UnsupportedRepositoryOperationException;
|
||||
import javax.jcr.version.Version;
|
||||
import javax.jcr.version.VersionHistory;
|
||||
import javax.jcr.version.VersionIterator;
|
||||
import javax.jcr.version.VersionManager;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
|
||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class AccountingHandler {
|
||||
|
||||
|
@ -32,11 +28,12 @@ public class AccountingHandler {
|
|||
private static final String OLD_ITEM_NAME = "hl:oldItemName";
|
||||
private static final String NEW_ITEM_NAME = "hl:newItemName";
|
||||
|
||||
private static final String BASE_VERSION ="1.0";
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
||||
|
||||
public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
||||
public void createReadObj(String title, String version, Session ses, Node node, String login, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -49,20 +46,8 @@ public class AccountingHandler {
|
|||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
|
||||
try {
|
||||
VersionManager vManager = ses.getWorkspace().getVersionManager();
|
||||
VersionHistory history = vManager.getVersionHistory(node.getNode("jcr:content").getPath());
|
||||
VersionIterator versions = history.getAllVersions();
|
||||
Version version= null;
|
||||
while (versions.hasNext()) {
|
||||
version = versions.nextVersion();
|
||||
}
|
||||
if (version!=null)
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, version.getName());
|
||||
}catch(UnsupportedRepositoryOperationException uropex) {
|
||||
logger.warn("version cannot be retrieved", uropex);
|
||||
}
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, version!=null?version:BASE_VERSION);
|
||||
|
||||
if (saveHistory) ses.save();
|
||||
} catch (RepositoryException e) {
|
||||
logger.warn("error trying to retrieve accountign node",e);
|
||||
|
@ -81,6 +66,8 @@ public class AccountingHandler {
|
|||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, BASE_VERSION);
|
||||
|
||||
|
||||
if (saveHistory) ses.save();
|
||||
} catch (RepositoryException e) {
|
||||
|
@ -88,7 +75,7 @@ public class AccountingHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public void createFileUpdated(String title, Session ses, Node node, String login, boolean saveHistory ) {
|
||||
public void createFileUpdated(String title, String version, Session ses, Node node, String login, boolean saveHistory ) {
|
||||
try {
|
||||
|
||||
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||
|
@ -97,25 +84,34 @@ public class AccountingHandler {
|
|||
|
||||
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
|
||||
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, version);
|
||||
|
||||
if (saveHistory) ses.save();
|
||||
} catch (RepositoryException e) {
|
||||
logger.warn("error trying to retrieve accountign node",e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createVersionDeleted(String title, String version, 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.DELETE.getNodeTypeDefinition());
|
||||
|
||||
|
||||
accountingNode.setProperty(USER, login);
|
||||
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||
accountingNode.setProperty(ITEM_NAME, title);
|
||||
|
||||
try {
|
||||
VersionManager vManager = ses.getWorkspace().getVersionManager();
|
||||
VersionHistory history = vManager.getVersionHistory(node.getNode("jcr:content").getPath());
|
||||
VersionIterator versions = history.getAllVersions();
|
||||
Version version= null;
|
||||
while (versions.hasNext()) {
|
||||
version = versions.nextVersion();
|
||||
}
|
||||
if (version!=null)
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, version.getName());
|
||||
|
||||
}catch(UnsupportedRepositoryOperationException uropex) {
|
||||
logger.warn("version cannot be retrieved", uropex);
|
||||
}
|
||||
accountingNode.setProperty(VERSION_ACCOUNTING, version);
|
||||
|
||||
|
||||
if (saveHistory) ses.save();
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.exception;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
public class MyAuthException extends WebApplicationException {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MyAuthException(Throwable cause) {
|
||||
super(cause, Status.FORBIDDEN);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
public class ACLHandler {
|
||||
|
||||
}
|
|
@ -40,11 +40,12 @@ public class ClassHandler {
|
|||
|
||||
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
||||
for (Class<?> clazz: classesAnnotated ){
|
||||
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 RootItem>) clazz);
|
||||
typeMap.put((Class<? extends RootItem>) clazz, value);
|
||||
if (RootItem.class.isAssignableFrom(clazz) && clazz.isAnnotationPresent(RootNode.class)) {
|
||||
String[] values = clazz.getAnnotation(RootNode.class).value();
|
||||
log.debug("loading class {} with values {} ", clazz, values );
|
||||
for (String value: values)
|
||||
classMap.put(value, (Class<? extends RootItem>) clazz);
|
||||
typeMap.put((Class<? extends RootItem>) clazz, values[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,21 +8,24 @@ import java.util.List;
|
|||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import jakarta.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.version.Version;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.Path;
|
||||
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.common.storagehub.model.storages.StorageBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
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.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -31,9 +34,12 @@ public class CompressHandler {
|
|||
private Logger logger = LoggerFactory.getLogger(CompressHandler.class);
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler pluginHandler;
|
||||
StorageBackendHandler storageBackendHandler;
|
||||
|
||||
public Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||
@Inject
|
||||
VersionHandler versionHandler;
|
||||
|
||||
public Deque<Item> getAllNodesForZip(FolderItem directory, String login, 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);
|
||||
|
@ -42,11 +48,17 @@ public class CompressHandler {
|
|||
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){
|
||||
tempQueue.addAll(getAllNodesForZip((FolderItem) item, login, session, accountingHandler, excludes));
|
||||
else if (item instanceof AbstractFileItem fileItem){
|
||||
logger.trace("adding file {}",item.getPath());
|
||||
AbstractFileItem fileItem = (AbstractFileItem) item;
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
|
||||
String versionName = null;
|
||||
try {
|
||||
Version version = versionHandler.getCurrentVersion((Node) item.getRelatedNode());
|
||||
versionName = version.getName();
|
||||
}catch(RepositoryException e) {
|
||||
logger.warn("current version of {} cannot be retreived", item.getId());
|
||||
}
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), versionName, session, (Node) item.getRelatedNode(), login, false);
|
||||
queue.addLast(item);
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +67,9 @@ public class CompressHandler {
|
|||
}
|
||||
|
||||
|
||||
public void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath) throws Exception{
|
||||
public void zipNode(ZipOutputStream zos, Deque<Item> queue, Path originalPath) throws Exception{
|
||||
logger.trace("originalPath is {}",originalPath.toPath());
|
||||
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
|
||||
Path actualPath = Paths.getPath("");
|
||||
while (!queue.isEmpty()) {
|
||||
Item item = queue.pop();
|
||||
if (item instanceof FolderItem) {
|
||||
|
@ -71,11 +83,14 @@ public class CompressHandler {
|
|||
}finally {
|
||||
zos.closeEntry();
|
||||
}
|
||||
} else if (item instanceof AbstractFileItem){
|
||||
} else if (item instanceof AbstractFileItem fileItem){
|
||||
try {
|
||||
AbstractFileItem fileItem = (AbstractFileItem)item;
|
||||
FolderManager manager = pluginHandler.getFolderManager(fileItem);
|
||||
InputStream streamToWrite = manager.getStorageBackend().download(fileItem.getContent());
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(fileItem.getContent().getPayloadBackend());
|
||||
|
||||
StorageBackend sb = sbf.create(fileItem.getContent().getPayloadBackend());
|
||||
|
||||
InputStream streamToWrite = sb.download(fileItem.getContent());
|
||||
if (streamToWrite == null){
|
||||
logger.warn("discarding item {} ",item.getName());
|
||||
continue;
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import javax.jcr.SimpleCredentials;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
|
||||
public class CredentialHandler {
|
||||
|
||||
private static SimpleCredentials credentials;
|
||||
|
||||
public static SimpleCredentials getAdminCredentials(ServletContext context) {
|
||||
if (credentials==null)
|
||||
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
|
||||
return credentials;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.gcube.common.storagehub.model.acls.ACL;
|
||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.exporter.DumpData;
|
||||
import org.gcube.common.storagehub.model.exporter.GroupData;
|
||||
import org.gcube.common.storagehub.model.exporter.UserData;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.types.SHUBUser;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
|
||||
import org.gcube.data.access.storagehub.services.delegates.ACLManagerDelegate;
|
||||
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
|
||||
import org.gcube.data.access.storagehub.services.delegates.UserManagerDelegate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class DataHandler {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(DataHandler.class);
|
||||
|
||||
@Inject
|
||||
UserManagerDelegate userHandler;
|
||||
|
||||
@Inject
|
||||
GroupManagerDelegate groupHandler;
|
||||
|
||||
@Inject
|
||||
ACLManagerDelegate aclHandler;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
VREManager vreManager;
|
||||
|
||||
public DumpData exportData(JackrabbitSession session) throws RepositoryException,StorageHubException {
|
||||
DumpData data = new DumpData();
|
||||
|
||||
List<SHUBUser> users = userHandler.getAllUsers(session);
|
||||
|
||||
List<UserData> usersData = users.stream().map(u -> new UserData(u.getUserName()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> groups = groupHandler.getGroups(session);
|
||||
|
||||
logger.debug("found users {} ",usersData);
|
||||
logger.debug("found groups {} ",groups);
|
||||
|
||||
List<GroupData> groupsData = new ArrayList<GroupData>(groups.size());
|
||||
for (String group : groups) {
|
||||
logger.debug("searching for group {}",group);
|
||||
Item vreFolderItem = vreManager.getVreFolderItemByGroupName(session, group, null).getVreFolder();
|
||||
String owner = vreFolderItem.getOwner();
|
||||
List<ACL> acls = aclHandler.getByItem(vreFolderItem, session);
|
||||
|
||||
AccessType accessType = AccessType.READ_ONLY;
|
||||
List<ACL> otherAccess = new ArrayList<ACL>(acls.size() - 1);
|
||||
for (ACL acl : acls)
|
||||
if (acl.getPrincipal().equals(group))
|
||||
accessType = acl.getAccessTypes().get(0);
|
||||
else
|
||||
otherAccess.add(acl);
|
||||
|
||||
List<String> members = groupHandler.getUsersBelongingToGroup(session, group);
|
||||
|
||||
groupsData.add(new GroupData(group, owner, members, accessType, otherAccess));
|
||||
}
|
||||
|
||||
Map<String, List<Item>> itemsPerUser = new HashMap<String, List<Item>>();
|
||||
for (SHUBUser user : users ) {
|
||||
logger.debug("getting all the files in {} workspace folder ",user.getUserName());
|
||||
String homePath = pathUtil.getWorkspacePath(user.getUserName()).toPath();
|
||||
Node homeNode = session.getNode(homePath);
|
||||
List<Item> items = Utils.getItemList(homeNode, Collections.emptyList(), null, true, null);
|
||||
items.forEach(i -> i.setParentId(null));
|
||||
itemsPerUser.put(user.getUserName(), retrieveSubItems(items));
|
||||
|
||||
}
|
||||
|
||||
data.setUsers(usersData);
|
||||
data.setGroups(groupsData);
|
||||
data.setItemPerUser(itemsPerUser);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
List<Item> retrieveSubItems(List<Item> items) throws StorageHubException, RepositoryException {
|
||||
List<Item> toReturn = new ArrayList<Item>();
|
||||
for (Item item: items )
|
||||
if (item instanceof FolderItem f) {
|
||||
if (f.isShared()) continue;
|
||||
toReturn.addAll(retrieveSubItems(Utils.getItemList((Node) f.getRelatedNode(), Collections.emptyList(), null, true, null)));
|
||||
} else
|
||||
toReturn.add(item);
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
public void importData(JackrabbitSession session, DumpData data) {
|
||||
data.getUsers().forEach(u -> {
|
||||
try {
|
||||
userHandler.createUser(session, u.getUserName(), "pwd");
|
||||
} catch (RepositoryException | StorageHubException e) {
|
||||
logger.warn("error importing user {} ", u.getUserName(), e);
|
||||
}
|
||||
});
|
||||
|
||||
data.getGroups().forEach(g -> {
|
||||
try {
|
||||
groupHandler.createGroup(session, g.getName(), g.getAccessType(), g.getFolderOwner(), true);
|
||||
for (String member : g.getMembers())
|
||||
try {
|
||||
groupHandler.addUserToGroup(session, member, g.getName());
|
||||
}catch(Throwable t ) {
|
||||
logger.warn("error adding user {} to group {}", member, g.getName(), t);
|
||||
}
|
||||
|
||||
Item vreFolderItem = vreManager.getVreFolderItemByGroupName(session, g.getName(), null).getVreFolder();
|
||||
|
||||
for (ACL acl : g.getAcls()) {
|
||||
aclHandler.update(acl.getPrincipal(), (Node)vreFolderItem.getRelatedNode(), acl.getAccessTypes().get(0), session);
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
logger.warn("error importing group {} ", g.getName(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.version.Version;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.Paths;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageIdNotFoundException;
|
||||
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.nodes.Content;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
import org.gcube.common.storagehub.model.storages.StorageNames;
|
||||
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
|
||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.StreamingOutput;
|
||||
|
||||
@Singleton
|
||||
public class DownloadHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DownloadHandler.class);
|
||||
|
||||
@Inject
|
||||
private AccountingHandler accountingHandler;
|
||||
|
||||
@Inject
|
||||
private StorageBackendHandler storageBackendHandler;
|
||||
|
||||
@Inject
|
||||
private CompressHandler compressHandler;
|
||||
|
||||
@Inject
|
||||
private VersionHandler versionHandler;
|
||||
|
||||
@Inject
|
||||
private Node2ItemConverter node2Item;
|
||||
|
||||
public Response downloadFolderItem(Session ses, String login, FolderItem item, boolean withAccounting ) throws StorageHubException, RepositoryException {
|
||||
try {
|
||||
final Deque<Item> allNodes = compressHandler.getAllNodesForZip((FolderItem)item, login, ses, accountingHandler, Excludes.GET_ONLY_CONTENT);
|
||||
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
|
||||
StreamingOutput so = new StreamingOutput() {
|
||||
|
||||
@Override
|
||||
public void write(OutputStream os) {
|
||||
|
||||
try(ZipOutputStream zos = new ZipOutputStream(os)){
|
||||
long start = System.currentTimeMillis();
|
||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||
log.debug("writing StreamOutput");
|
||||
compressHandler.zipNode(zos, allNodes, originalPath);
|
||||
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
|
||||
} catch (Exception e) {
|
||||
log.error("error writing stream",e);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Response response = Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+item.getTitle()+".zip")
|
||||
.header("Content-Type", "application/zip")
|
||||
.header("Content-Length", -1l)
|
||||
.build();
|
||||
|
||||
if (withAccounting)
|
||||
accountingHandler.createReadObj(item.getTitle(), null, ses, (Node) item.getRelatedNode(), login, false);
|
||||
return response;
|
||||
}finally {
|
||||
if (ses!=null) ses.save();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Response downloadFileItem(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, StorageHubException {
|
||||
|
||||
Content content = fileItem.getContent();
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(content.getPayloadBackend());
|
||||
|
||||
StorageBackend sb = sbf.create(content.getPayloadBackend());
|
||||
|
||||
InputStream streamToWrite = sb.download(content);
|
||||
|
||||
if (withAccounting) {
|
||||
String versionName = null;
|
||||
try {
|
||||
Version version = versionHandler.getCurrentVersion((Node) fileItem.getRelatedNode());
|
||||
versionName = version.getName();
|
||||
}catch(RepositoryException e) {
|
||||
log.warn("current version of {} cannot be retreived", fileItem.getId());
|
||||
}
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), versionName, ses, (Node) fileItem.getRelatedNode(), login, true);
|
||||
}
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
return Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+fileItem.getName())
|
||||
.header("Content-Length", fileItem.getContent().getSize())
|
||||
.header("Content-Type", fileItem.getContent().getMimeType())
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
public Response downloadVersionedItem(Session ses, String login, AbstractFileItem currentItem, String versionName, boolean withAccounting) throws RepositoryException, StorageHubException{
|
||||
|
||||
|
||||
List<Version> jcrVersions = versionHandler.getContentVersionHistory((Node)currentItem.getRelatedNode());
|
||||
|
||||
for (Version version: jcrVersions) {
|
||||
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
|
||||
if (version.getName().equals(versionName)) {
|
||||
Content content = node2Item.getContentFromVersion(version);
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(content.getPayloadBackend());
|
||||
StorageBackend sb = sbf.create(content.getPayloadBackend());
|
||||
|
||||
InputStream streamToWrite = null;
|
||||
try {
|
||||
streamToWrite = sb.download(content);
|
||||
}catch (StorageIdNotFoundException e) {
|
||||
//TODO: temporary code, it will last until the MINIO porting will not finish
|
||||
if (sbf.getName().equals(StorageNames.MONGO_STORAGE)) {
|
||||
sbf = storageBackendHandler.get(StorageNames.DEFAULT_S3_STORAGE);
|
||||
sbf.create(new PayloadBackend(StorageNames.DEFAULT_S3_STORAGE, null));
|
||||
} else
|
||||
throw e;
|
||||
}
|
||||
|
||||
log.debug("retrieved storage id is {} with storageBackend {} (stream is null? {})",content.getStorageId(), sbf.getName(), streamToWrite==null );
|
||||
|
||||
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
|
||||
String ext = FilenameUtils.getExtension(currentItem.getTitle());
|
||||
|
||||
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
||||
|
||||
if (withAccounting)
|
||||
accountingHandler.createReadObj(currentItem.getTitle(), versionName, ses, (Node) currentItem.getRelatedNode(), login, true);
|
||||
|
||||
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
return Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+fileName)
|
||||
.header("Content-Length", content.getSize())
|
||||
.header("Content-Type", content.getMimeType())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
throw new InvalidItemException("the version is not valid");
|
||||
}
|
||||
|
||||
|
||||
public Response downloadFileFromStorageBackend(String storageId, String storageName) throws RepositoryException, PluginInitializationException, PluginNotFoundException, StorageHubException {
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(storageName);
|
||||
|
||||
StorageBackend sb = sbf.create(new PayloadBackend(storageName, null));
|
||||
|
||||
InputStream streamToWrite = sb.download(storageId);
|
||||
|
||||
Map<String, String> userMetadata = sb.getFileMetadata(storageId);
|
||||
|
||||
log.info("returned metadata from storageBackend are: {}", userMetadata);
|
||||
|
||||
long size = Long.parseLong(userMetadata.get("size"));
|
||||
|
||||
String title = userMetadata.get("title");
|
||||
String contentType = userMetadata.get("content-type");
|
||||
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
return Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+title)
|
||||
.header("Content-Length", size)
|
||||
.header("Content-Type", contentType)
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.apache.jackrabbit.api.security.user.Group;
|
||||
import org.apache.jackrabbit.api.security.user.User;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.services.GroupManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class GroupHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
public boolean removeUserFromGroup(String groupId, String userId, JackrabbitSession session) throws StorageHubException, RepositoryException {
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||
User user = (User)usrManager.getAuthorizable(userId);
|
||||
|
||||
if (!group.isMember(user))
|
||||
throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId);
|
||||
|
||||
//delete folder on user
|
||||
String folderName = group.getPrincipal().getName();
|
||||
Node folder = getFolderNodeRelatedToGroup(session, folderName);
|
||||
|
||||
NodeIterator ni = folder.getSharedSet();
|
||||
while (ni.hasNext()) {
|
||||
Node node = ni.nextNode();
|
||||
if (node.getPath().startsWith(pathUtil.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
|
||||
node.removeShare();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return group.removeMember(user);
|
||||
|
||||
}
|
||||
|
||||
public Node getFolderNodeRelatedToGroup(JackrabbitSession session, String name) throws ItemNotFoundException, RepositoryException {
|
||||
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
||||
|
||||
Node vreFolder = null;
|
||||
try {
|
||||
vreFolder = sharedRootNode.getNode(name);
|
||||
}catch (PathNotFoundException e) {
|
||||
log.debug("is an old HL VRE");
|
||||
}
|
||||
|
||||
if (vreFolder==null) {
|
||||
NodeIterator nodes = sharedRootNode.getNodes();
|
||||
while (nodes.hasNext()) {
|
||||
Node node = nodes.nextNode();
|
||||
if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
|
||||
vreFolder= node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vreFolder==null) throw new ItemNotFoundException("vre folder not found for group "+name);
|
||||
return vreFolder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import static org.gcube.common.storagehub.model.Constants.enchriptedPrefix;
|
||||
import static org.gcube.common.storagehub.model.Constants.enchriptedVolatile;
|
||||
import static org.gcube.common.storagehub.model.Constants.versionPrefix;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import org.gcube.common.encryption.encrypter.StringEncrypter;
|
||||
import org.gcube.common.security.AuthorizedTasks;
|
||||
import org.gcube.common.security.secrets.Secret;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.data.access.storagehub.types.LinkType;
|
||||
import org.gcube.data.access.storagehub.types.PublicLink;
|
||||
import org.gcube.smartgears.ContextProvider;
|
||||
|
||||
@Singleton
|
||||
public class PublicLinkHandler {
|
||||
|
||||
public String getForItem(String itemId, ServletContext context) throws BackendGenericError{
|
||||
return getUrl(itemId, enchriptedPrefix, context);
|
||||
}
|
||||
|
||||
public String getForVersionedItem(String itemId, String version, ServletContext context) throws BackendGenericError {
|
||||
return getUrl(String.format("%s%s%s",itemId, versionPrefix, version), enchriptedPrefix, context);
|
||||
}
|
||||
|
||||
public String getForVolatile(String fileId, String storageName, ServletContext context) throws BackendGenericError {
|
||||
return getUrl(String.format("%s_%s",fileId, storageName), enchriptedVolatile, context);
|
||||
}
|
||||
|
||||
public PublicLink resolveEnchriptedId(String enchriptedId) throws StorageHubException {
|
||||
|
||||
String complexId = enchriptedId;
|
||||
boolean isVolatile = false;
|
||||
if (enchriptedId.startsWith(enchriptedPrefix) || enchriptedId.startsWith(enchriptedVolatile) ) {
|
||||
final String enchriptedValue = enchriptedId.startsWith(enchriptedPrefix) ? enchriptedPrefix : enchriptedVolatile;
|
||||
isVolatile = enchriptedId.startsWith(enchriptedVolatile);
|
||||
|
||||
try {
|
||||
String infraContext = String.format("/%s", ContextProvider.get().container().configuration().infrastructure());
|
||||
|
||||
Secret infraSecret = ContextProvider.get().container().authorizationProvider().getSecretForContext(infraContext);
|
||||
|
||||
complexId = AuthorizedTasks.executeSafely(() -> {
|
||||
return StringEncrypter.getEncrypter().decrypt(
|
||||
new String(Base64.getUrlDecoder().decode(enchriptedId.replace(enchriptedValue, ""))));
|
||||
}, infraSecret);
|
||||
|
||||
}catch(Throwable e){
|
||||
throw new BackendGenericError("invalid public url",e);
|
||||
}
|
||||
}
|
||||
|
||||
if (isVolatile) {
|
||||
String[] volatileIdSplit = complexId.split("_");
|
||||
return new VolatilePublicLink(volatileIdSplit[0], volatileIdSplit[1]);
|
||||
}else {
|
||||
if (complexId.contains(versionPrefix)) {
|
||||
String[] split = complexId.split(versionPrefix);
|
||||
String itemId = split[0];
|
||||
String versionName = split[1];
|
||||
|
||||
return new ItemPublicLink(itemId, versionName);
|
||||
} else
|
||||
return new ItemPublicLink(complexId);
|
||||
}
|
||||
}
|
||||
|
||||
private String getUrl(String toEnchript, String prefix, ServletContext context) throws BackendGenericError{
|
||||
String infraContext = String.format("/%s", ContextProvider.get().container().configuration().infrastructure());
|
||||
Secret infraSecret = ContextProvider.get().container().authorizationProvider().getSecretForContext(infraContext);
|
||||
|
||||
|
||||
try {
|
||||
String enchriptedQueryString = AuthorizedTasks.executeSafely(
|
||||
() -> {return StringEncrypter.getEncrypter().encrypt(toEnchript);},infraSecret);
|
||||
|
||||
|
||||
String basepath = context.getInitParameter("resolver-basepath");
|
||||
String filePublicUrl = String.format("%s/%s%s",basepath, prefix, Base64.getUrlEncoder().encodeToString(enchriptedQueryString.getBytes()));
|
||||
|
||||
return filePublicUrl;
|
||||
}catch (Throwable e) {
|
||||
throw new BackendGenericError("error encrypting item id",e );
|
||||
}
|
||||
}
|
||||
|
||||
public static class VolatilePublicLink implements PublicLink {
|
||||
|
||||
private String storageKey;
|
||||
|
||||
private String storageName;
|
||||
|
||||
protected VolatilePublicLink(String storageKey, String storageName){
|
||||
this.storageKey = storageKey;
|
||||
this.storageName = storageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkType getType() {return LinkType.VOLATILE;}
|
||||
|
||||
@Override
|
||||
public String getId() { return storageKey; }
|
||||
|
||||
@Override
|
||||
public String getStorageName() { return storageName; }
|
||||
}
|
||||
|
||||
public static class ItemPublicLink implements PublicLink {
|
||||
|
||||
private String itemId;
|
||||
private String version;
|
||||
private LinkType type;
|
||||
|
||||
protected ItemPublicLink(String itemId){
|
||||
this.itemId = itemId;
|
||||
this.type = LinkType.STANDARD;
|
||||
}
|
||||
|
||||
protected ItemPublicLink(String itemId, String version){
|
||||
this.itemId = itemId;
|
||||
this.version = version;
|
||||
this.type = LinkType.VERSIONED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkType getType() {return type;}
|
||||
|
||||
@Override
|
||||
public String getId() { return itemId; }
|
||||
|
||||
@Override
|
||||
public String getVersion() { return version; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -9,8 +9,8 @@ import java.util.concurrent.ExecutorService;
|
|||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
@ -18,7 +18,7 @@ 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.security.AuthorizedTasks;
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.Paths;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
|
@ -30,7 +30,8 @@ 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.storages.StorageBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
|
@ -38,7 +39,7 @@ 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.handlers.plugins.StorageBackendHandler;
|
||||
import org.gcube.data.access.storagehub.types.ContentPair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -68,11 +69,9 @@ public class TrashHandler {
|
|||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject FolderPluginHandler managerHandler;
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderHandler;
|
||||
|
||||
StorageBackendHandler storageBackendHandler;
|
||||
|
||||
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
|
||||
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
||||
for (Item item: itemsToDelete) {
|
||||
|
@ -109,8 +108,13 @@ public class TrashHandler {
|
|||
}
|
||||
|
||||
try {
|
||||
FolderManager manager = folderHandler.getFolderManager(item);
|
||||
contentSet.add(new ContentPair(item.getContent(), manager.getStorageBackend()));
|
||||
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(item.getContent().getPayloadBackend());
|
||||
|
||||
StorageBackend sb = sbf.create(item.getContent().getPayloadBackend());
|
||||
|
||||
contentSet.add(new ContentPair(item.getContent(), sb));
|
||||
|
||||
List<Version> versions = versionHandler.getContentVersionHistory((Node)item.getRelatedNode());
|
||||
|
||||
|
@ -118,7 +122,7 @@ public class TrashHandler {
|
|||
try {
|
||||
Content content = node2Item.getContentFromVersion(version);
|
||||
if (content!= null && content.getStorageId()!=null)
|
||||
contentSet.add(new ContentPair(content, manager.getStorageBackend()));
|
||||
contentSet.add(new ContentPair(content, sb));
|
||||
else log.warn("invalid version {}",version.getName());
|
||||
}catch (Throwable t) {
|
||||
log.warn("error retrieving version content for {}",version.getName(),t);
|
||||
|
@ -159,7 +163,7 @@ public class TrashHandler {
|
|||
public void run() {
|
||||
for (ContentPair cp: contentToDelete ) {
|
||||
try {
|
||||
cp.getStorageBackend().onDelete(cp.getContent());
|
||||
cp.getStorageBackend().delete(cp.getContent().getStorageId());
|
||||
log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName());
|
||||
}catch(Throwable t) {
|
||||
log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t);
|
||||
|
@ -212,8 +216,7 @@ public class TrashHandler {
|
|||
|
||||
if (item instanceof FolderItem) {
|
||||
trashItem.setFolder(true);
|
||||
}else if (item instanceof AbstractFileItem ) {
|
||||
AbstractFileItem file = (AbstractFileItem) item;
|
||||
}else if (item instanceof AbstractFileItem file) {
|
||||
if (file.getContent()!=null) {
|
||||
trashItem.setMimeType(file.getContent().getMimeType());
|
||||
trashItem.setLenght(file.getContent().getSize());
|
||||
|
@ -229,10 +232,10 @@ public class TrashHandler {
|
|||
log.debug("calling jcr move");
|
||||
ses.getWorkspace().move(nodeToDelete.getPath(), Paths.append(Paths.getPath(newTrashItemNode.getPath()),nodeToDelete.getName()).toPath());
|
||||
String mimetype = null;
|
||||
if (item instanceof AbstractFileItem) {
|
||||
if (((AbstractFileItem)item).getContent()!=null)
|
||||
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
||||
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
|
||||
if (item instanceof AbstractFileItem file) {
|
||||
if (file.getContent()!=null)
|
||||
mimetype = file.getContent().getMimeType();
|
||||
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", file.getId());
|
||||
}
|
||||
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true);
|
||||
}catch(Throwable t) {
|
||||
|
|
|
@ -5,8 +5,8 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
@ -163,7 +163,7 @@ public class UnshareHandler {
|
|||
unsharedNodeIdentifier = unsharedNode.getIdentifier();
|
||||
log.info("[UNSHARE] unshared node id {}",unsharedNodeIdentifier);
|
||||
ses.save();
|
||||
}
|
||||
} //TODO: else shoud I removove all the fiel content ?
|
||||
|
||||
log.debug("all the users have been removed, the folder is totally unshared");
|
||||
|
||||
|
|
|
@ -4,8 +4,9 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.version.Version;
|
||||
import javax.jcr.version.VersionHistory;
|
||||
|
@ -52,7 +53,14 @@ public class VersionHandler {
|
|||
logger.warn("cannot checkoutNode content node",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Version getCurrentVersion(Node node) throws RepositoryException{
|
||||
Session session = node.getSession();
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
VersionManager versionManager = session.getWorkspace().getVersionManager();
|
||||
return versionManager.getBaseVersion(contentNode.getPath());
|
||||
}
|
||||
|
||||
public List<Version> getContentVersionHistory(Node node) {
|
||||
try {
|
||||
Session session = node.getSession();
|
||||
|
@ -68,10 +76,17 @@ public class VersionHandler {
|
|||
logger.debug("version name {} with nodeType {}",version.getName(),version.getPrimaryNodeType().getName());
|
||||
}
|
||||
return versions;
|
||||
}catch(Exception e ) {
|
||||
}catch(Throwable e ) {
|
||||
logger.warn("cannot get version history content node",e);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeContentVersion(Node node, String versionName) throws RepositoryException{
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
VersionHistory history = contentNode.getSession().getWorkspace().getVersionManager().getVersionHistory(contentNode.getPath());
|
||||
history.removeVersion(versionName);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,10 +7,18 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
|
|||
|
||||
public interface ContentHandler {
|
||||
|
||||
void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception;
|
||||
boolean requiresInputStream();
|
||||
|
||||
default void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
default void initiliseSpecificContent(String fileName, String mimeType) throws Exception {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
Content getContent();
|
||||
|
||||
|
||||
AbstractFileItem buildItem(String name, String description, String login);
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||
import org.reflections.Reflections;
|
||||
|
@ -42,9 +42,9 @@ public class ContentHandlerFactory {
|
|||
public ContentHandler create(String mimetype) throws Exception{
|
||||
Class<? extends ContentHandler> handlerClass = handlerMap.get(mimetype);
|
||||
if (handlerClass!=null)
|
||||
return handlerClass.newInstance();
|
||||
return handlerClass.getDeclaredConstructor().newInstance();
|
||||
else
|
||||
return defaultHandler.newInstance();
|
||||
return defaultHandler.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.gcube.data.access.storagehub.handlers.content;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.GenericFileItem;
|
||||
|
@ -11,12 +10,17 @@ public class GenericFileHandler implements ContentHandler{
|
|||
|
||||
Content content = new Content();
|
||||
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String filename, String mimeType) throws Exception {
|
||||
public boolean requiresInputStream() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(String filename, String mimeType) throws Exception {
|
||||
content.setMimeType(mimeType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Content getContent() {
|
||||
return content;
|
||||
|
|
|
@ -28,28 +28,38 @@ public class ImageHandler implements ContentHandler{
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ImageHandler.class);
|
||||
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
|
||||
Image image = javax.imageio.ImageIO.read(is);
|
||||
public boolean requiresInputStream() {
|
||||
return true;
|
||||
}
|
||||
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception {
|
||||
if (size<5242880) {
|
||||
Image image = javax.imageio.ImageIO.read(is);
|
||||
|
||||
content.setWidth(Long.valueOf(width));
|
||||
content.setHeight(Long.valueOf(height));
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
|
||||
try {
|
||||
int[] dimension = getThumbnailDimension(width, height);
|
||||
|
||||
byte[] buf = transform(image, fileName, dimension[0], dimension[1]).toByteArray();
|
||||
content.setWidth(Long.valueOf(width));
|
||||
content.setHeight(Long.valueOf(height));
|
||||
|
||||
|
||||
content.setThumbnailHeight(Long.valueOf(dimension[1]));
|
||||
content.setThumbnailWidth(Long.valueOf(dimension[0]));
|
||||
content.setThumbnailData(buf);
|
||||
}catch(Throwable t) {
|
||||
logger.warn("thumbnail for file {} cannot be created ", fileName,t);
|
||||
try {
|
||||
int[] dimension = getThumbnailDimension(width, height);
|
||||
|
||||
byte[] buf = transform(image, fileName, dimension[0], dimension[1]).toByteArray();
|
||||
|
||||
|
||||
content.setThumbnailHeight(Long.valueOf(dimension[1]));
|
||||
content.setThumbnailWidth(Long.valueOf(dimension[0]));
|
||||
content.setThumbnailData(buf);
|
||||
}catch(Throwable t) {
|
||||
logger.warn("thumbnail for file {} cannot be created ", fileName,t);
|
||||
}
|
||||
}
|
||||
|
||||
content.setMimeType(mimeType);
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,12 @@ public class OfficeAppHandler implements ContentHandler{
|
|||
Content content = new Content();
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String filename, String mimeType) throws Exception {
|
||||
public boolean requiresInputStream() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String filename, String mimeType, long size) throws Exception {
|
||||
//detecting the file type
|
||||
BodyContentHandler handler = new BodyContentHandler();
|
||||
Metadata metadata = new Metadata();
|
||||
|
|
|
@ -27,7 +27,12 @@ public class PdfHandler implements ContentHandler {
|
|||
private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class);
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
|
||||
public boolean requiresInputStream() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception {
|
||||
try {
|
||||
PdfReader reader = new PdfReader(is);
|
||||
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
||||
|
|
|
@ -10,13 +10,14 @@ import java.util.Map;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.ItemExistsException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Value;
|
||||
|
||||
import org.apache.jackrabbit.core.NodeImpl;
|
||||
import org.apache.jackrabbit.util.Text;
|
||||
import org.apache.jackrabbit.value.BinaryValue;
|
||||
import org.apache.jackrabbit.value.BooleanValue;
|
||||
|
@ -49,52 +50,62 @@ public class Item2NodeConverter {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
|
||||
|
||||
public <T extends RootItem> Node getNode(Node parentNode, T item){
|
||||
public <T extends RootItem> Node getNode(Node parentNode, T item, String uuid){
|
||||
try {
|
||||
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
|
||||
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
||||
//newNode.setPrimaryType(primaryType);
|
||||
for (Field field : retrieveAllFields(item.getClass())){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
if (attribute.isReadOnly()) continue;
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
//Class<?> returnType = field.getType();
|
||||
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());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value for attribute {}: {}",attribute.value(), e.getMessage());
|
||||
}
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||
if (nodeAttribute.isReadOnly()) continue;
|
||||
String nodeName = nodeAttribute.value();
|
||||
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.debug("error setting value",e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Node newNode = null;
|
||||
if (uuid==null)
|
||||
newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
||||
else ((NodeImpl)parentNode).addNodeWithUuid(item.getName(), primaryType, uuid);
|
||||
fillNode(newNode, item);
|
||||
return newNode;
|
||||
} catch (RepositoryException e) {
|
||||
logger.error("error writing repository",e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends RootItem> Node getNode(Node parentNode, T item){
|
||||
return getNode(parentNode, item, null);
|
||||
|
||||
}
|
||||
|
||||
private <T extends RootItem> void fillNode(Node newNode, T item) throws RepositoryException {
|
||||
for (Field field : retrieveAllFields(item.getClass())){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
if (attribute.isReadOnly()) continue;
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
//Class<?> returnType = field.getType();
|
||||
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());
|
||||
} catch (Exception e ) {
|
||||
logger.warn("error setting value for attribute {}: {}",attribute.value(), e.getMessage());
|
||||
}
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||
if (nodeAttribute.isReadOnly()) continue;
|
||||
String nodeName = nodeAttribute.value();
|
||||
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.debug("error setting value",e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{
|
||||
|
||||
|
||||
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
|
||||
|
||||
Node newNode;
|
||||
|
@ -115,6 +126,7 @@ public class Item2NodeConverter {
|
|||
@SuppressWarnings("rawtypes")
|
||||
Class returnType = field.getType();
|
||||
Values values = getObjectValue(returnType, field.get(object));
|
||||
if (values == null) continue;
|
||||
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||
else newNode.setProperty(attribute.value(), values.getValue());
|
||||
} catch (Exception e ) {
|
||||
|
@ -145,13 +157,28 @@ public class Item2NodeConverter {
|
|||
|
||||
iterateItemNodeAttributeFields(obj,newNode, field.getName()+(i++));
|
||||
}
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
|
||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||
if (nodeAttribute.isReadOnly()) continue;
|
||||
String subNodeName = nodeAttribute.value();
|
||||
logger.trace("retrieving field node "+field.getName());
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Object obj = field.get(object);
|
||||
if (obj!=null)
|
||||
iterateItemNodeAttributeFields(obj, newNode, subNodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public static Values getObjectValue(Class returnType, Object value) throws Exception{
|
||||
|
||||
if (value== null) return null;
|
||||
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
|
||||
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
|
||||
if (returnType.equals(Calendar.class)) return new Values(new DateValue((Calendar) value));
|
||||
|
@ -188,8 +215,9 @@ public class Item2NodeConverter {
|
|||
|
||||
public <F extends AbstractFileItem> void replaceContent(Node node, F item, ItemAction action){
|
||||
try {
|
||||
|
||||
node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value());
|
||||
|
||||
String primaryType = item.getClass().getAnnotation(RootNode.class).value()[0];
|
||||
node.setPrimaryType(primaryType);
|
||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||
contentNode.setPrimaryType(item.getContent().getClass().getAnnotation(AttributeRootNode.class).value());
|
||||
|
||||
|
@ -197,22 +225,9 @@ public class Item2NodeConverter {
|
|||
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), item.getLastModifiedBy());
|
||||
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||
|
||||
for (Field field : retrieveAllFields(item.getContent().getClass())){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
if (attribute.isReadOnly()) continue;
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
//Class<?> returnType = field.getType();
|
||||
Values values = getObjectValue(field.getType(), field.get(item.getContent()));
|
||||
if (values.isMulti()) contentNode.setProperty(attribute.value(), values.getValues() );
|
||||
else contentNode.setProperty(attribute.value(), values.getValue());
|
||||
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value for attribute "+attribute.value(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
replaceContentNodeInternal(contentNode, item.getContent().getClass(),item.getContent());
|
||||
|
||||
|
||||
} catch (RepositoryException e) {
|
||||
logger.error("error writing repository",e);
|
||||
|
@ -220,7 +235,41 @@ public class Item2NodeConverter {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
//VALID ONLY FOR CONTENT
|
||||
public void replaceContentNodeInternal(Node node, Class<?> clazz, Object instance) {
|
||||
for (Field field : retrieveAllFields(clazz)){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
if (attribute.isReadOnly()) continue;
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
//Class<?> returnType = field.getType();
|
||||
Values values = getObjectValue(field.getType(), field.get(instance));
|
||||
if (values.isMulti()) node.setProperty(attribute.value(), values.getValues() );
|
||||
else node.setProperty(attribute.value(), values.getValue());
|
||||
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value for attribute "+attribute.value(),e);
|
||||
}
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||
if (nodeAttribute.isReadOnly()) continue;
|
||||
String subNodeName = nodeAttribute.value();
|
||||
logger.trace("retrieving field node "+field.getName());
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Object obj = field.get(instance);
|
||||
if (obj!=null)
|
||||
iterateItemNodeAttributeFields(obj, node, subNodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateHidden(Node node, Boolean hidden,String login) throws RepositoryException {
|
||||
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
||||
node.setProperty(NodeProperty.HIDDEN.toString(), hidden);
|
||||
|
@ -231,6 +280,7 @@ public class Item2NodeConverter {
|
|||
node.setProperty(NodeProperty.DESCRIPTION.toString(), description);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
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;
|
||||
|
|
|
@ -7,17 +7,14 @@ 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 jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
import javax.jcr.version.Version;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||
|
@ -26,7 +23,6 @@ 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;
|
||||
|
@ -38,12 +34,11 @@ 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.storages.StorageBackendFactory;
|
||||
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;
|
||||
|
@ -55,15 +50,15 @@ import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationPara
|
|||
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.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class ItemHandler {
|
||||
|
||||
|
||||
@Inject
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
||||
@Inject
|
||||
|
@ -76,54 +71,47 @@ public class ItemHandler {
|
|||
VersionHandler versionHandler;
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler pluginHandler;
|
||||
StorageBackendHandler storageBackendHandler;
|
||||
|
||||
private static ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||
// private static ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
@Inject Item2NodeConverter item2Node;
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
@Inject
|
||||
Item2NodeConverter item2Node;
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(ItemHandler.class);
|
||||
|
||||
|
||||
public <T extends CreateParameters> String create(T parameters) throws Exception{
|
||||
// TODO: accounting
|
||||
// provider URI host
|
||||
// resourceOwner user
|
||||
// consumer write
|
||||
// in caso di versione - update con -delta
|
||||
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) {
|
||||
} catch (RepositoryException inf) {
|
||||
throw new IdNotFoundException(parameters.getParentId());
|
||||
}
|
||||
|
||||
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||
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());
|
||||
Node newNode = switch (parameters.getMangedType()) {
|
||||
case FILE -> create((FileCreationParameters) parameters, destination);
|
||||
case FOLDER -> create((FolderCreationParameters) parameters, destination);
|
||||
case ARCHIVE -> create((ArchiveStructureCreationParameter) parameters, destination);
|
||||
case URL -> create((URLCreationParameters) parameters, destination);
|
||||
case GCUBEITEM -> create((GCubeItemCreationParameters) parameters, destination);
|
||||
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()))
|
||||
|
@ -132,267 +120,295 @@ public class ItemHandler {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private Node create(FolderCreationParameters params, Node destination) throws Exception{
|
||||
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);
|
||||
Node newNode = Utils.createFolderInternally(params, accountingHandler, false);
|
||||
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);
|
||||
private Node create(FileCreationParameters params, Node destination) throws Exception {
|
||||
Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(),
|
||||
params.getDescription(), params.getFileDetails(), params.getUser(), true);
|
||||
params.getSession().save();
|
||||
versionHandler.checkinContentNode(newNode);
|
||||
log.info("file with id {} correctly created",newNode.getIdentifier());
|
||||
return newNode;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
private Node create(URLCreationParameters params, Node destination) throws Exception{
|
||||
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);
|
||||
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{
|
||||
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);
|
||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder()
|
||||
.name(params.getParentFolderName()).author(params.getUser()).on(destination.getIdentifier())
|
||||
.with(params.getSession()).build();
|
||||
Node parentDirectoryNode = Utils.createFolderInternally(folderParameters, accountingHandler, false);
|
||||
params.getSession().save();
|
||||
try {
|
||||
if (params.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
|
||||
params.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
|
||||
} catch (Throwable t){
|
||||
} catch (Throwable t) {
|
||||
log.warn("error unlocking {}", destination.getPath(), t);
|
||||
}
|
||||
|
||||
Set<Node> fileNodes = new HashSet<>();
|
||||
|
||||
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
||||
|
||||
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
||||
ArchiveInputStream input = new ArchiveStreamFactory()
|
||||
.createArchiveInputStream(new BufferedInputStream(params.getStream()));
|
||||
|
||||
try (ArchiveInputStream input = new ArchiveStreamFactory()
|
||||
.createArchiveInputStream(new BufferedInputStream(params.getStream(), 1024*64))){
|
||||
ArchiveEntry entry;
|
||||
while ((entry = input.getNextEntry()) != null) {
|
||||
String entirePath = entry.getName();
|
||||
ArchiveEntry entry;
|
||||
while ((entry = input.getNextEntry()) != null) {
|
||||
String entirePath = entry.getName();
|
||||
log.debug("reading new entry ------> {} ", entirePath);
|
||||
if (entry.isDirectory()) {
|
||||
log.debug("creating directory with entire path {} ", entirePath);
|
||||
createPath(entirePath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
|
||||
} 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;
|
||||
long fileSize = entry.getSize();
|
||||
FormDataContentDisposition fileDetail = FormDataContentDisposition.name(name).size(fileSize)
|
||||
.build();
|
||||
//this code has been added for a bug on s3 client(v1) that closes the stream
|
||||
InputStream notClosableIS = new BufferedInputStream(input) {
|
||||
@Override
|
||||
public void close() throws IOException { }
|
||||
};
|
||||
|
||||
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);
|
||||
if (parentPath.isEmpty()) {
|
||||
fileNode = createFileItemInternally(params.getSession(), parentDirectoryNode, notClosableIS, name, "",
|
||||
fileDetail, 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, notClosableIS, name, "",
|
||||
fileDetail, params.getUser(), false);
|
||||
}
|
||||
fileNodes.add(fileNode);
|
||||
} catch (Throwable e) {
|
||||
log.warn("error getting file {}", entry.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.info("archive {} uploading finished ", params.getParentFolderName());
|
||||
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{
|
||||
|
||||
|
||||
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];
|
||||
String name = parentPathSplit[parentPathSplit.length - 1];
|
||||
StringBuilder relParentPath = new StringBuilder();
|
||||
for (int i = 0 ; i<=parentPathSplit.length-2; i++)
|
||||
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);
|
||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user)
|
||||
.on(rootNode.getIdentifier()).with(ses).build();
|
||||
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler, false);
|
||||
directoryNodeMap.put(name + "/", createdNode);
|
||||
return createdNode;
|
||||
}else {
|
||||
} else {
|
||||
Node relParentNode = directoryNodeMap.get(relParentPath.toString());
|
||||
if (relParentNode==null) {
|
||||
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);
|
||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user)
|
||||
.on(relParentNode.getIdentifier()).with(ses).build();
|
||||
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler, false);
|
||||
directoryNodeMap.put(relParentPath.append(name).append("/").toString(), createdNode);
|
||||
return createdNode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Node create(GCubeItemCreationParameters params, Node destination) throws Exception{
|
||||
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);
|
||||
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{
|
||||
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name,
|
||||
String description, FormDataContentDisposition fileDetails, String login, boolean withLock)
|
||||
throws RepositoryException, StorageHubException {
|
||||
|
||||
log.trace("UPLOAD: starting preparing file");
|
||||
|
||||
Node newNode;
|
||||
FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL);
|
||||
FolderManager folderManager = pluginHandler.getFolderManager(destinationItem);
|
||||
StorageBackend storageBackend = folderManager.getStorageBackend();
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(destinationItem.getBackend());
|
||||
|
||||
StorageBackend sb = sbf.create(destinationItem.getBackend());
|
||||
|
||||
String relativePath = destinationNode.getPath();
|
||||
|
||||
if (destinationItem.isExternalManaged())
|
||||
relativePath = relativePath.replace(folderManager.getRootFolder().getPath(), "");
|
||||
|
||||
|
||||
|
||||
String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath();
|
||||
log.info("new node path is {}", newNodePath);
|
||||
|
||||
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);
|
||||
|
||||
AbstractFileItem item = fillItemWithContent(stream, sb, name, description, fileDetails, relativePath,
|
||||
login);
|
||||
|
||||
if (withLock) {
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
|
||||
}catch (LockException le) {
|
||||
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);
|
||||
log.trace("replacing content of class {}", item.getContent().getClass());
|
||||
item2Node.replaceContent(newNode, item, ItemAction.UPDATED);
|
||||
String versionName = null;
|
||||
try {
|
||||
Version version = versionHandler.getCurrentVersion(newNode);
|
||||
versionName = version.getName();
|
||||
} catch (RepositoryException e) {
|
||||
log.warn("current version of {} cannot be retreived", item.getId());
|
||||
}
|
||||
accountingHandler.createFileUpdated(item.getTitle(), versionName, ses, newNode, login, false);
|
||||
ses.save();
|
||||
}finally {
|
||||
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
|
||||
} catch (Throwable t) {
|
||||
log.error("error saving item", t);
|
||||
} finally {
|
||||
if (withLock) {
|
||||
if (ses != null && ses.hasPendingChanges())
|
||||
ses.save();
|
||||
ses.getWorkspace().getLockManager().unlock(newNode.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true);
|
||||
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath, login);
|
||||
AbstractFileItem item = fillItemWithContent(stream, sb, name, description, fileDetails, relativePath,
|
||||
login);
|
||||
if (withLock) {
|
||||
try {
|
||||
log.debug("trying to acquire lock");
|
||||
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
|
||||
}catch (LockException le) {
|
||||
} catch (LockException le) {
|
||||
throw new ItemLockedException(le);
|
||||
}
|
||||
}
|
||||
try {
|
||||
newNode = item2Node.getNode(destinationNode, item);
|
||||
newNode = item2Node.getNode(destinationNode, item);
|
||||
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode, login, false);
|
||||
ses.save();
|
||||
}finally {
|
||||
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
|
||||
} catch (Throwable t) {
|
||||
log.error("error saving item", t);
|
||||
throw new BackendGenericError(t);
|
||||
} 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);
|
||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(),
|
||||
ses, login, destinationNode, false);
|
||||
}
|
||||
|
||||
// TODO: Utils.updateParentSize()
|
||||
|
||||
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 AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name,
|
||||
String description, FormDataContentDisposition fileDetails, String relPath, String login)
|
||||
throws BackendGenericError {
|
||||
log.trace("UPLOAD: filling content");
|
||||
ContentHandler handler = getContentHandler(stream, storageBackend, name, fileDetails, relPath, login);
|
||||
return handler.buildItem(name, description, login);
|
||||
}
|
||||
|
||||
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError {
|
||||
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name,
|
||||
FormDataContentDisposition fileDetails, 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));
|
||||
log.trace("UPLOAD: handling content");
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
log.debug("TIMING: writing the stream - start");
|
||||
log.trace("UPLOAD: 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();
|
||||
MetaInfo info = null;
|
||||
try {
|
||||
log.debug("UPLOAD: upload on {} - start", storageBackend.getClass());
|
||||
if (fileDetails != null && fileDetails.getSize() > 0) {
|
||||
log.debug("UPLOAD: file size set is {} Byte", fileDetails.getSize());
|
||||
info = storageBackend.upload(stream, relPath, name, fileDetails.getSize(), login);
|
||||
} else
|
||||
info = storageBackend.upload(stream, relPath, name, login);
|
||||
log.debug("UPLOAD: upload on storage - stop");
|
||||
} catch (Throwable e) {
|
||||
log.error("error writing content", e);
|
||||
throw e;
|
||||
}
|
||||
ContentHandler handler = null;
|
||||
String mimeType;
|
||||
log.debug("UPLOAD: reading the mimetype - start");
|
||||
try (InputStream is1 = new BufferedInputStream(storageBackend.download(info.getStorageId()))) {
|
||||
org.apache.tika.mime.MediaType mediaType = null;
|
||||
TikaConfig config = TikaConfig.getDefaultConfig();
|
||||
Detector detector = config.getDetector();
|
||||
TikaInputStream tikastream = TikaInputStream.get(is1);
|
||||
Metadata metadata = new Metadata();
|
||||
mediaType = detector.detect(tikastream, metadata);
|
||||
mimeType = mediaType.getBaseType().toString();
|
||||
handler = contenthandlerFactory.create(mimeType);
|
||||
|
||||
log.debug("UPLOAD: reading the mimetype {} - finished in {}", mimeType,
|
||||
System.currentTimeMillis() - start);
|
||||
} catch (Throwable e) {
|
||||
log.error("error retrieving mimeType", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (handler.requiresInputStream())
|
||||
try (InputStream is1 = new BufferedInputStream(storageBackend.download(info.getStorageId()))) {
|
||||
log.debug("UPLOAD: the file type requires input stream");
|
||||
handler.initiliseSpecificContent(is1, name, mimeType, info.getSize());
|
||||
}
|
||||
else {
|
||||
log.debug("UPLOAD: the file type doesn't requires input stream");
|
||||
handler.initiliseSpecificContent(name, mimeType);
|
||||
}
|
||||
log.debug("UPLOAD: writing the stream - finished in {}", System.currentTimeMillis() - start);
|
||||
|
||||
handler.getContent().setData(NodeConstants.CONTENT_NAME);
|
||||
handler.getContent().setStorageId(info.getStorageId());
|
||||
handler.getContent().setSize(info.getSize());
|
||||
handler.getContent().setRemotePath(info.getRemotePath());
|
||||
handler.getContent().setRemotePath(info.getRemotePath());
|
||||
|
||||
handler.getContent().setPayloadBackend(info.getPayloadBackend());
|
||||
log.debug("UPLOAD: content payload set as {} ", handler.getContent().getPayloadBackend());
|
||||
|
||||
return handler;
|
||||
}catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
log.error("error writing file", e);
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
|
@ -42,12 +41,15 @@ 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.gcube.data.access.storagehub.predicates.ItemTypePredicate;
|
||||
import org.reflections.Configuration;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class Node2ItemConverter {
|
||||
|
@ -57,11 +59,11 @@ public class Node2ItemConverter {
|
|||
|
||||
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{
|
||||
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, ItemTypePredicate itemTypePredicate) 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;
|
||||
if (itemTypePredicate != null && !itemTypePredicate.test(classToHandle)) return null;
|
||||
else return retrieveItem(node, excludes, classToHandle);
|
||||
}
|
||||
|
||||
|
@ -83,7 +85,7 @@ public class Node2ItemConverter {
|
|||
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")))
|
||||
|
@ -95,7 +97,7 @@ public class Node2ItemConverter {
|
|||
}catch (Throwable e) {
|
||||
msg.setWithAttachments(false);
|
||||
}
|
||||
|
||||
|
||||
setRootItemCommonFields(node, Collections.emptyList(), Message.class, msg);
|
||||
return msg;
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ public class Node2ItemConverter {
|
|||
private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{
|
||||
T item;
|
||||
try {
|
||||
item = classToHandle.newInstance();
|
||||
item = classToHandle.getDeclaredConstructor().newInstance();
|
||||
}catch (Exception e) {
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
|
@ -129,7 +131,7 @@ public class Node2ItemConverter {
|
|||
item.setExternalManaged(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
item.setLocked(node.isLocked());
|
||||
|
||||
setRootItemCommonFields(node, excludes, classToHandle, item);
|
||||
|
@ -137,7 +139,7 @@ public class Node2ItemConverter {
|
|||
return item;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
|
||||
if(node==null) return false;
|
||||
|
@ -146,16 +148,16 @@ public class Node2ItemConverter {
|
|||
|
||||
|
||||
private <T extends RootItem> void setRootItemCommonFields(Node node, List<String> excludes, Class<T> classToHandle, T instance) throws RepositoryException{
|
||||
|
||||
|
||||
try{
|
||||
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()));
|
||||
|
||||
|
@ -166,21 +168,11 @@ public class Node2ItemConverter {
|
|||
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(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.debug("error setting value for property {} ",attribute.value());
|
||||
}
|
||||
setAttributeFieldCheckingDefault(field, instance, node);
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
|
||||
//for now it excludes only first level node
|
||||
|
@ -195,7 +187,7 @@ public class Node2ItemConverter {
|
|||
}catch(PathNotFoundException e){
|
||||
logger.trace("the current node dosn't contain {} node",fieldNodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value",e);
|
||||
logger.trace("error setting value",e);
|
||||
}
|
||||
|
||||
|
||||
|
@ -204,100 +196,145 @@ public class Node2ItemConverter {
|
|||
}
|
||||
|
||||
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
||||
T obj = clazz.newInstance();
|
||||
T obj = clazz.getDeclaredConstructor().newInstance();
|
||||
for (Field field : retrieveAllFields(clazz)){
|
||||
if (field.isAnnotationPresent(Attribute.class)){
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
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.debug("error setting value {}",e.getMessage());
|
||||
}
|
||||
setAttributeFieldCheckingDefault(field, obj, node);
|
||||
} 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());
|
||||
field.setAccessible(true);
|
||||
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
|
||||
Map<String, Object> mapToset = new HashMap<String, Object>();
|
||||
PropertyIterator iterator = node.getProperties();
|
||||
if (iterator!=null) {
|
||||
while (iterator.hasNext()){
|
||||
Property prop = iterator.nextProperty();
|
||||
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
|
||||
try{
|
||||
logger.trace("adding {} in the map",prop.getName());
|
||||
|
||||
mapToset.put(prop.getName(), getPropertyValue(prop));
|
||||
}catch(PathNotFoundException e){
|
||||
logger.warn("the property {} is not mapped",prop.getName());
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value {}",e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
field.set(obj, mapToset);
|
||||
setMapAttribute(field, obj, node);
|
||||
} else if (field.isAnnotationPresent(ListNodes.class)){
|
||||
logger.trace("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), clazz.getName(), node.getName());
|
||||
setListNode(field, obj, node);
|
||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||
logger.trace("found field {} of type annotated as NodeAttribute in class {} on node {}", field.getName(), clazz.getName(), node.getName());
|
||||
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 {} on field {}", fieldNodeName, field.getName());
|
||||
field.setAccessible(true);
|
||||
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
|
||||
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
|
||||
|
||||
Class listType = field.getAnnotation(ListNodes.class).listClass();
|
||||
|
||||
Map<String, Class> subTypesMap = Collections.emptyMap();
|
||||
|
||||
if (!typeToSubtypeMap.containsKey(listType)) {
|
||||
|
||||
|
||||
Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName());
|
||||
Reflections reflections = new Reflections(config);
|
||||
Set<Class> subTypes = reflections.getSubTypesOf(listType);
|
||||
|
||||
|
||||
if (subTypes.size()>0) {
|
||||
subTypesMap = new HashMap<>();
|
||||
for (Class subtype: subTypes)
|
||||
if (subtype.isAnnotationPresent(AttributeRootNode.class)) {
|
||||
AttributeRootNode attributeRootNode = (AttributeRootNode)subtype.getAnnotation(AttributeRootNode.class);
|
||||
subTypesMap.put(attributeRootNode.value(), subtype);
|
||||
}
|
||||
} else logger.trace("no subtypes found for {}",listType.getName());
|
||||
|
||||
typeToSubtypeMap.put(listType, subTypesMap);
|
||||
|
||||
} else {
|
||||
logger.info("subtypes already found in cache");
|
||||
subTypesMap = typeToSubtypeMap.get(listType);
|
||||
try{
|
||||
Node fieldNode = node.getNode(fieldNodeName);
|
||||
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
|
||||
field.set(obj, iterateNodeAttributeFields(field.getType(), fieldNode));
|
||||
}catch(PathNotFoundException e){
|
||||
logger.trace("the current node dosn't contain {} node",fieldNodeName);
|
||||
} catch (Exception e ) {
|
||||
logger.trace("error setting value",e);
|
||||
}
|
||||
|
||||
List<Object> toSetList = new ArrayList<>();
|
||||
|
||||
NodeIterator iterator = node.getNodes();
|
||||
|
||||
while (iterator.hasNext()){
|
||||
Node currentNode = iterator.nextNode();
|
||||
|
||||
String primaryType = currentNode.getPrimaryNodeType().getName();
|
||||
|
||||
logger.trace("the current node {} has a list",currentNode.getName());
|
||||
|
||||
if (!include.isEmpty() && !primaryType.startsWith(include))
|
||||
continue;
|
||||
if (!exclude.isEmpty() && primaryType.startsWith(exclude))
|
||||
continue;
|
||||
if (subTypesMap.containsKey(primaryType))
|
||||
toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode));
|
||||
else toSetList.add(iterateNodeAttributeFields(listType, currentNode));
|
||||
}
|
||||
if (toSetList.size()!=0) field.set(obj, toSetList);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private <T> void setMapAttribute(Field field, T instance, Node node) throws Exception{
|
||||
field.setAccessible(true);
|
||||
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
|
||||
Map<String, Object> mapToset = new HashMap<String, Object>();
|
||||
PropertyIterator iterator = node.getProperties();
|
||||
if (iterator!=null) {
|
||||
while (iterator.hasNext()){
|
||||
Property prop = iterator.nextProperty();
|
||||
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
|
||||
try{
|
||||
logger.trace("adding {} in the map",prop.getName());
|
||||
|
||||
mapToset.put(prop.getName(), getPropertyValue(prop));
|
||||
}catch(PathNotFoundException e){
|
||||
logger.trace("the property {} is not mapped",prop.getName());
|
||||
} catch (Exception e ) {
|
||||
logger.trace("error setting value {}",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
field.set(instance, mapToset);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void setListNode(Field field, T instance, Node node) throws Exception{
|
||||
field.setAccessible(true);
|
||||
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
|
||||
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
|
||||
|
||||
Class listType = field.getAnnotation(ListNodes.class).listClass();
|
||||
|
||||
Map<String, Class> subTypesMap = Collections.emptyMap();
|
||||
|
||||
if (!typeToSubtypeMap.containsKey(listType)) {
|
||||
|
||||
Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName());
|
||||
Reflections reflections = new Reflections(config);
|
||||
Set<Class> subTypes = reflections.getSubTypesOf(listType);
|
||||
|
||||
|
||||
if (subTypes.size()>0) {
|
||||
subTypesMap = new HashMap<>();
|
||||
for (Class subtype: subTypes)
|
||||
if (subtype.isAnnotationPresent(AttributeRootNode.class)) {
|
||||
AttributeRootNode attributeRootNode = (AttributeRootNode)subtype.getAnnotation(AttributeRootNode.class);
|
||||
subTypesMap.put(attributeRootNode.value(), subtype);
|
||||
}
|
||||
} else logger.trace("no subtypes found for {}",listType.getName());
|
||||
|
||||
typeToSubtypeMap.put(listType, subTypesMap);
|
||||
|
||||
} else {
|
||||
logger.debug("subtypes already found in cache");
|
||||
subTypesMap = typeToSubtypeMap.get(listType);
|
||||
}
|
||||
|
||||
List<Object> toSetList = new ArrayList<>();
|
||||
|
||||
NodeIterator iterator = node.getNodes();
|
||||
|
||||
while (iterator.hasNext()){
|
||||
Node currentNode = iterator.nextNode();
|
||||
|
||||
String primaryType = currentNode.getPrimaryNodeType().getName();
|
||||
|
||||
logger.trace("the current node {} has a list",currentNode.getName());
|
||||
|
||||
if (!include.isEmpty() && !primaryType.startsWith(include))
|
||||
continue;
|
||||
if (!exclude.isEmpty() && primaryType.startsWith(exclude))
|
||||
continue;
|
||||
if (subTypesMap.containsKey(primaryType))
|
||||
toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode));
|
||||
else toSetList.add(iterateNodeAttributeFields(listType, currentNode));
|
||||
}
|
||||
if (toSetList.size()!=0) field.set(instance, toSetList);
|
||||
}
|
||||
|
||||
|
||||
private <T> void setAttributeFieldCheckingDefault(Field field, T instance, Node node) {
|
||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||
field.setAccessible(true);
|
||||
try{
|
||||
Object propValue;
|
||||
Class<?> returnType = field.getType();
|
||||
if (node.hasProperty(attribute.value())) {
|
||||
propValue = getPropertyValue(returnType, node.getProperty(attribute.value()));
|
||||
if (!attribute.defaultValue().isEmpty() && propValue==null )
|
||||
propValue = returnType.cast(attribute.defaultValue());
|
||||
field.set(instance, propValue);
|
||||
logger.trace("retrieve item - added field {}",field.getName());
|
||||
} else if (!attribute.defaultValue().isEmpty()){
|
||||
propValue = returnType.cast(attribute.defaultValue());
|
||||
field.set(instance, propValue);
|
||||
logger.trace("retrieve item - setting default for field {}",field.getName());
|
||||
} else
|
||||
logger.trace("property not found for field {}",field.getName());
|
||||
|
||||
} catch (Exception e ) {
|
||||
logger.debug("error setting value for property {} ",attribute.value());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
||||
if (returnType.equals(String.class)) return prop.getString();
|
||||
|
|
|
@ -28,7 +28,7 @@ public class ArchiveStructureCreationParameter extends CreateParameters {
|
|||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream) && Objects.nonNull(fileDetails);
|
||||
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.gcube.common.storagehub.model.Metadata;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
|
||||
import org.gcube.common.storagehub.model.plugins.PluginParameters;
|
||||
|
||||
public class FolderCreationParameters extends CreateParameters {
|
||||
|
@ -9,8 +12,8 @@ public class FolderCreationParameters extends CreateParameters {
|
|||
private String name;
|
||||
private String description="";
|
||||
private boolean hidden = false;
|
||||
private String externalPluginName = null;
|
||||
private PluginParameters externalPluginParameters = null;
|
||||
private PayloadBackend backend;
|
||||
|
||||
|
||||
protected FolderCreationParameters() {}
|
||||
|
||||
|
@ -26,16 +29,8 @@ public class FolderCreationParameters extends CreateParameters {
|
|||
return hidden;
|
||||
}
|
||||
|
||||
public boolean isExternal() {
|
||||
return externalPluginName!=null;
|
||||
}
|
||||
|
||||
public String getPluginName(String name) {
|
||||
return this.externalPluginName;
|
||||
}
|
||||
|
||||
public PluginParameters getPluginParameters() {
|
||||
return externalPluginParameters;
|
||||
public PayloadBackend getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,8 +65,8 @@ public class FolderCreationParameters extends CreateParameters {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ExternalFolderCreationBuilder onRepository(String pluginName) {
|
||||
return new ExternalFolderCreationBuilder(pluginName, this);
|
||||
public BackendCreationBuilder onRepository(String pluginName) {
|
||||
return new BackendCreationBuilder(pluginName, this);
|
||||
}
|
||||
|
||||
public FolderCreationBuilder hidden(boolean hidden) {
|
||||
|
@ -81,19 +76,26 @@ public class FolderCreationParameters extends CreateParameters {
|
|||
|
||||
}
|
||||
|
||||
public static class ExternalFolderCreationBuilder {
|
||||
public static class BackendCreationBuilder {
|
||||
|
||||
FolderCreationBuilder cb;
|
||||
|
||||
protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
|
||||
this.cb.parameters.externalPluginName = pluginName;
|
||||
String plugin;
|
||||
|
||||
protected BackendCreationBuilder(String pluginName, FolderCreationBuilder cb) {
|
||||
this.cb = cb;
|
||||
this.plugin = pluginName;
|
||||
}
|
||||
|
||||
public FolderCreationBuilder withParameters(PluginParameters params){
|
||||
this.cb.parameters.externalPluginParameters = params;
|
||||
public FolderCreationBuilder withParameters(Map<String, Object> params){
|
||||
this.cb.parameters.backend = new PayloadBackend(plugin, new Metadata(params));
|
||||
return this.cb;
|
||||
}
|
||||
|
||||
public FolderCreationBuilder withoutParameters(){
|
||||
this.cb.parameters.backend = new PayloadBackend(plugin, null);
|
||||
return this.cb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.inject.Default;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
||||
import org.gcube.common.storagehub.model.items.ExternalFolder;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeFolderManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class FolderPluginHandler {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(FolderPluginHandler.class);
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
private GcubeFolderManager defaultManager = new GcubeFolderManager();
|
||||
|
||||
public FolderManager getDefault() {
|
||||
return defaultManager;
|
||||
}
|
||||
|
||||
@Inject
|
||||
Instance<FolderManagerConnector> connectors;
|
||||
|
||||
private Map<String, FolderManagerConnector> connectorsMap;
|
||||
|
||||
FolderPluginHandler(){
|
||||
if (connectors !=null)
|
||||
connectorsMap = connectors.stream().collect(Collectors.toMap(FolderManagerConnector::getName, e -> e ));
|
||||
else {
|
||||
log.info("connectors are null");
|
||||
connectorsMap = Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
public FolderManagerConnector getConnector(String name) throws PluginNotFoundException {
|
||||
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
|
||||
return connectorsMap.get(name);
|
||||
}
|
||||
|
||||
public FolderManager getFolderManager(Item item) throws PluginInitializationException, PluginNotFoundException, RepositoryException, BackendGenericError{
|
||||
if (!item.isExternalManaged())
|
||||
return defaultManager;
|
||||
Session session = ((Node)item.getRelatedNode()).getSession();
|
||||
Item parent = null;
|
||||
do {
|
||||
String parentId = item.getParentId();
|
||||
Node node = session.getNodeByIdentifier(parentId);
|
||||
parent = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
if (parent !=null && parent instanceof ExternalFolder) {
|
||||
ExternalFolder extParent = (ExternalFolder) parent;
|
||||
String plugin = extParent.getManagedBy();
|
||||
Map<String, Object> parameters = extParent.getConnectionParameters().getMap();
|
||||
return getConnector(plugin).connect(extParent, parameters);
|
||||
}
|
||||
} while (parent!=null);
|
||||
throw new BackendGenericError("selected external managed item doesn't have a parent external folder");
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class OperationMediator {
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderHandler;
|
||||
|
||||
/*
|
||||
boolean onMove(Item source, Item destination, Session session) throws PluginInitializationException, PluginNotFoundException, BackendGenericError, RepositoryException{
|
||||
FolderManager sourceFolderManager = folderHandler.getFolderManager(source);
|
||||
FolderManager destinationFolderManager = folderHandler.getFolderManager(destination);
|
||||
|
||||
if (source instanceof FolderItem) {
|
||||
destinationFolderManager.onCreatedFolder((FolderItem) source);
|
||||
|
||||
|
||||
session.move(source.getPath(), destination.getPath());
|
||||
sourceFolderManager.onDeletingFolder((FolderItem) source);
|
||||
} else if (source instanceof AbstractFileItem){
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
import org.gcube.common.storagehub.model.storages.StorageNames;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class StorageBackendHandler {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(StorageBackendHandler.class);
|
||||
|
||||
public static PayloadBackend getDefaultPayloadForFolder() {
|
||||
return new PayloadBackend(StorageNames.DEFAULT_S3_STORAGE, null);
|
||||
}
|
||||
|
||||
@Inject
|
||||
Instance<StorageBackendFactory> factories;
|
||||
|
||||
Map<String, StorageBackendFactory> storagebackendMap = new HashMap<String, StorageBackendFactory>();
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
if (factories != null)
|
||||
for (StorageBackendFactory connector : factories) {
|
||||
if (storagebackendMap.containsKey(connector.getName())) {
|
||||
log.error("multiple storage backend with the same name");
|
||||
throw new RuntimeException("multiple storage backend with the same name");
|
||||
}
|
||||
storagebackendMap.put(connector.getName(), connector);
|
||||
}
|
||||
else
|
||||
throw new RuntimeException("storage backend implementation not found");
|
||||
}
|
||||
|
||||
public StorageBackendFactory get(PayloadBackend payload) throws PluginNotFoundException {
|
||||
if (payload == null || !storagebackendMap.containsKey(payload.getStorageName()))
|
||||
throw new PluginNotFoundException(
|
||||
String.format("implementation for storage %s not found", payload.getStorageName()));
|
||||
return storagebackendMap.get(payload.getStorageName());
|
||||
}
|
||||
|
||||
public StorageBackendFactory get(String storageName) throws PluginNotFoundException {
|
||||
return storagebackendMap.get(storageName);
|
||||
}
|
||||
|
||||
public Collection<StorageBackendFactory> getAllImplementations() {
|
||||
return storagebackendMap.values();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
|
||||
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class StorageOperationMediator {
|
||||
|
||||
Logger log = LoggerFactory.getLogger(StorageOperationMediator.class);
|
||||
|
||||
@Inject
|
||||
StorageBackendHandler storageBackendHandler;
|
||||
|
||||
public MetaInfo copy(Content source, PayloadBackend destination, String newName, String newParentPath, String login) throws StorageHubException{
|
||||
|
||||
log.info("creating Storages for source {} and destination {}", source.getPayloadBackend(), destination.getStorageName());
|
||||
|
||||
StorageBackendFactory sourceSBF = storageBackendHandler.get(source.getPayloadBackend());
|
||||
//TODO: add metadata taken from content node
|
||||
StorageBackend sourceSB = sourceSBF.create(source.getPayloadBackend());
|
||||
|
||||
StorageBackendFactory destSBF = storageBackendHandler.get(destination);
|
||||
StorageBackend destSB = destSBF.create(destination);
|
||||
|
||||
log.info("source factory is {} and destination factory is {}", sourceSBF.getName(), destSBF.getName());
|
||||
|
||||
if (sourceSB.equals(destSB)) {
|
||||
log.info("source and destination are the same storage");
|
||||
return sourceSB.onCopy(source, newParentPath, newName);
|
||||
}else {
|
||||
log.info("source and destination are different storage");
|
||||
InputStream stream = sourceSB.download(source);
|
||||
return destSB.upload(stream, newParentPath, newName, source.getSize(), login);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean move(){
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -6,32 +6,26 @@ 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.security.ContextBean;
|
||||
import org.gcube.common.security.ContextBean.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.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class VREManager {
|
||||
|
||||
|
@ -39,8 +33,7 @@ public class VREManager {
|
|||
|
||||
private Map<String, VRE> vreMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
@ -49,19 +42,12 @@ public class VREManager {
|
|||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
GroupHandler groupHandler;
|
||||
GroupManagerDelegate 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) {
|
||||
|
||||
private synchronized VRE getVRE(String completeName) {
|
||||
logger.trace("requesting VRE {}",completeName);
|
||||
if (vreMap.containsKey(completeName))
|
||||
return vreMap.get(completeName);
|
||||
|
@ -74,36 +60,26 @@ public class VREManager {
|
|||
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);
|
||||
VRE toReturn = new VRE(vreFolder, repository.getRepository(), Constants.JCR_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());
|
||||
public String retrieveGroupNameFromContext(String context) throws StorageHubException{
|
||||
ContextBean bean = new ContextBean(context);
|
||||
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);
|
||||
return entireScopeName;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
public synchronized VRE getVreFolderItemByGroupName(JackrabbitSession ses, String groupName, List<String> excludes ) throws RepositoryException, StorageHubException{
|
||||
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,41 @@
|
|||
package org.gcube.data.access.storagehub.health;
|
||||
|
||||
import org.gcube.common.health.api.HealthCheck;
|
||||
import org.gcube.common.health.api.ReadinessChecker;
|
||||
import org.gcube.common.health.api.response.HealthCheckResponse;
|
||||
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
|
||||
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeDefaultS3StorageBackendFactory;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.S3Backend;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ReadinessChecker
|
||||
public class DefaultStorageCheck implements HealthCheck{
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(DefaultStorageCheck.class);
|
||||
|
||||
PayloadBackend defaultPayload = StorageBackendHandler.getDefaultPayloadForFolder();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("default storage (%s)",defaultPayload.getStorageName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthCheckResponse check() {
|
||||
try {
|
||||
GcubeDefaultS3StorageBackendFactory storageFactory =new GcubeDefaultS3StorageBackendFactory();
|
||||
storageFactory.init();
|
||||
if (((S3Backend)storageFactory.create(defaultPayload)).isAlive())
|
||||
return HealthCheckResponse.builder(getName()).up().build();
|
||||
else
|
||||
return HealthCheckResponse.builder(getName()).down().error("error contacting storage").build();
|
||||
} catch (Exception e) {
|
||||
log.error("error checking defaultStorage",e);
|
||||
return HealthCheckResponse.builder(getName()).down().error(e.getMessage()).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.gcube.data.access.storagehub.health;
|
||||
|
||||
import javax.jcr.LoginException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.health.api.HealthCheck;
|
||||
import org.gcube.common.health.api.ReadinessChecker;
|
||||
import org.gcube.common.health.api.response.HealthCheckResponse;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
|
||||
@ReadinessChecker
|
||||
public class JCRRepositoryCheck implements HealthCheck{
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Jackrabbit repository";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HealthCheckResponse check() {
|
||||
try {
|
||||
Session session = StoragehubRepository.repository.getRepository().login();
|
||||
if (session != null) session.logout();
|
||||
return HealthCheckResponse.builder(getName()).up().build();
|
||||
}catch (LoginException e) { }
|
||||
catch(Throwable ex) {
|
||||
return HealthCheckResponse.builder(getName()).down().error(ex.getMessage()).build();
|
||||
}
|
||||
return HealthCheckResponse.builder(getName()).up().build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.gcube.data.access.storagehub.predicates;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.RootItem;
|
||||
|
||||
public class ExcludeTypePredicate implements ItemTypePredicate {
|
||||
|
||||
List<Class<? extends RootItem>> classes;
|
||||
|
||||
public ExcludeTypePredicate(List<Class<? extends RootItem>> classes) {
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
public ExcludeTypePredicate(Class<? extends RootItem> clazz) {
|
||||
this.classes = Collections.singletonList(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Class<? extends RootItem> t) {
|
||||
for (Class<? extends RootItem> _class : classes)
|
||||
if (_class.isAssignableFrom(t)) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package org.gcube.data.access.storagehub.predicates;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.RootItem;
|
||||
|
||||
public class IncludeTypePredicate implements ItemTypePredicate {
|
||||
|
||||
List<Class<? extends RootItem>> classes;
|
||||
|
||||
public IncludeTypePredicate(List<Class<? extends RootItem>> classes) {
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
public IncludeTypePredicate(Class<? extends RootItem> clazz) {
|
||||
this.classes = Collections.singletonList(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Class<? extends RootItem> t) {
|
||||
for (Class<? extends RootItem> _class : classes)
|
||||
if (_class.isAssignableFrom(t)) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package org.gcube.data.access.storagehub.predicates;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.RootItem;
|
||||
|
||||
public interface ItemTypePredicate extends Predicate<Class<? extends RootItem>> {
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package org.gcube.data.access.storagehub.query.sql2.evaluators;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package org.gcube.data.access.storagehub.query.sql2.evaluators;
|
||||
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.enterprise.inject.Instance;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
|
||||
|
@ -19,6 +19,7 @@ public class Evaluators {
|
|||
@Inject
|
||||
Instance<Evaluator<?>> evaluators;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public String evaluate(Expression<?> expression) {
|
||||
for (Evaluator eval: evaluators) {
|
||||
if (eval.getType().equals(expression.getClass()))
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.date.Before;
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.logical.And;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.gcube.data.access.storagehub.query.sql2.evaluators.logical;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.logical.Or;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.gcube.data.access.storagehub.query.sql2.evaluators.text;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||
import org.gcube.common.storagehub.model.expressions.text.Contains;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
package org.gcube.data.access.storagehub.repository;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import javax.jcr.Repository;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.nodetype.NodeType;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitRepository;
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.apache.jackrabbit.api.JackrabbitWorkspace;
|
||||
import org.apache.jackrabbit.api.security.authorization.PrivilegeManager;
|
||||
import org.apache.jackrabbit.commons.cnd.CndImporter;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class JackrabbitRepositoryImpl implements StoragehubRepository {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(JackrabbitRepositoryImpl.class);
|
||||
|
||||
private Repository repository;
|
||||
|
||||
public JackrabbitRepositoryImpl(){
|
||||
try {
|
||||
InitialContext context = new InitialContext();
|
||||
Context environment = (Context) context.lookup("java:comp/env");
|
||||
repository = (Repository) environment.lookup("jcr/repository");
|
||||
}catch (Throwable e) {
|
||||
log.error("error initializing repository", e);
|
||||
throw new RuntimeException("error initializing repository",e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Repository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
private boolean jackrabbitInitialized = false;
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void initContainerAtFirstStart() {
|
||||
try {
|
||||
JackrabbitSession ses = (JackrabbitSession) this.repository.login(Constants.JCR_CREDENTIALS);
|
||||
try {
|
||||
boolean notAlreadyDone = !jackrabbitInitialized && !ses.getRootNode().hasNode("Home");
|
||||
if (notAlreadyDone)
|
||||
this.init(ses);
|
||||
else log.info("jackrabbit is already initialized");
|
||||
}finally {
|
||||
ses.logout();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("error initialising Jackrabbit",e);
|
||||
}
|
||||
jackrabbitInitialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
((JackrabbitRepository)repository).shutdown();
|
||||
}
|
||||
|
||||
public void init(JackrabbitSession ses) throws Exception{
|
||||
log.info("init started");
|
||||
try {
|
||||
initNodeTypes(ses);
|
||||
ses.getRootNode().addNode("Home");
|
||||
ses.getRootNode().addNode("Share");
|
||||
PrivilegeManager pm = ((JackrabbitWorkspace) ses.getWorkspace()).getPrivilegeManager();
|
||||
pm.registerPrivilege("hl:writeAll", false, new String[0]);
|
||||
ses.save();
|
||||
}catch (Exception e) {
|
||||
log.error("init error", e);
|
||||
throw e;
|
||||
}
|
||||
log.info("init finished");
|
||||
}
|
||||
|
||||
void initNodeTypes(Session ses) throws Exception{
|
||||
InputStream stream = this.getClass().getResourceAsStream("/init/NodeType.cnd");
|
||||
|
||||
if (stream == null)
|
||||
throw new Exception("NodeType.cnd inputStream is null");
|
||||
|
||||
InputStreamReader inputstream = new InputStreamReader(stream, Charset.forName("UTF-8"));
|
||||
// Register the custom node types defined in the CND file, using JCR Commons CndImporter
|
||||
|
||||
log.info("start to register the custom node types defined in the CND file...");
|
||||
|
||||
|
||||
NodeType[] nodeTypes = CndImporter.registerNodeTypes(inputstream, ses, true);
|
||||
|
||||
for (NodeType nt : nodeTypes)
|
||||
log.info("Registered: {} ", nt.getName());
|
||||
|
||||
|
||||
log.info("custom node types registered");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.gcube.data.access.storagehub.repository;
|
||||
|
||||
import javax.jcr.Repository;
|
||||
|
||||
public interface StoragehubRepository {
|
||||
|
||||
static final StoragehubRepository repository = new JackrabbitRepositoryImpl();
|
||||
|
||||
Repository getRepository();
|
||||
|
||||
void shutdown();
|
||||
|
||||
void initContainerAtFirstStart();
|
||||
}
|
|
@ -2,24 +2,10 @@ package org.gcube.data.access.storagehub.services;
|
|||
|
||||
import java.util.Collections;
|
||||
|
||||
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.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
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.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
|
@ -35,11 +21,13 @@ 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.Constants;
|
||||
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.StorageHubApplicationManager;
|
||||
import org.gcube.data.access.storagehub.handlers.ACLHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
||||
import org.gcube.smartgears.annotations.ManagedBy;
|
||||
import org.gcube.smartgears.utils.InnerMethodName;
|
||||
|
@ -47,33 +35,59 @@ 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;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("items")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@ManagedBy(StorageHubApplicationManager.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);
|
||||
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
ACLHandler aclHandler;
|
||||
|
||||
|
||||
|
||||
@RequestScoped
|
||||
@PathParam("id")
|
||||
String id;
|
||||
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
|
||||
|
||||
@Inject UnshareHandler unshareHandler;
|
||||
|
||||
|
||||
@Inject ACLManagerInterface aclManagerDelegate;
|
||||
|
||||
|
||||
/**
|
||||
* returns the AccessType for all the users in a shared folder
|
||||
*
|
||||
|
@ -84,13 +98,13 @@ public class ACLManager extends Impersonable {
|
|||
@Path("{id}/acls")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ACLList getACL() {
|
||||
InnerMethodName.instance.set("getACLById");
|
||||
InnerMethodName.set("getACLById");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
return new ACLList(aclManagerDelegate.get(item, ses));
|
||||
return new ACLList(aclManagerDelegate.getByItem(item, ses));
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr error getting acl", re);
|
||||
throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re));
|
||||
|
@ -121,13 +135,13 @@ public class ACLManager extends Impersonable {
|
|||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Path("{id}/acls")
|
||||
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
|
||||
InnerMethodName.instance.set("setACLById");
|
||||
InnerMethodName.set("setACLById");
|
||||
Session ses = null;
|
||||
try {
|
||||
|
||||
|
||||
if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified");
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
@ -139,28 +153,25 @@ public class ACLManager extends Impersonable {
|
|||
throw new UserNotAuthorizedException("owner acl cannot be changed");
|
||||
|
||||
SharedFolder folder = (SharedFolder) item;
|
||||
|
||||
|
||||
authChecker.checkAdministratorControl(ses, currentUser, folder);
|
||||
|
||||
if (folder.isVreFolder()) {
|
||||
if (accessType==AccessType.ADMINISTRATOR) throw new InvalidCallParameters("a VRE admin cannot be changed with this method");
|
||||
|
||||
if (!user.equals(folder.getTitle())) throw new InvalidCallParameters("the groupId in the argument is different to the one of the VREFolder");
|
||||
if (item instanceof VreFolder || folder.isVreFolder())
|
||||
throw new InvalidCallParameters("acls in vreFolder cannot be updated with this method");
|
||||
|
||||
} else {
|
||||
NodeIterator sharedSet = node.getSharedSet();
|
||||
boolean found = false;
|
||||
while (sharedSet.hasNext() && !found) {
|
||||
Node current = sharedSet.nextNode();
|
||||
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
|
||||
NodeIterator sharedSet = node.getSharedSet();
|
||||
boolean found = false;
|
||||
while (sharedSet.hasNext() && !found) {
|
||||
Node current = sharedSet.nextNode();
|
||||
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
|
||||
found = true;
|
||||
}
|
||||
|
||||
aclManagerDelegate.update(user, folder, accessType, ses);
|
||||
|
||||
if (!found)
|
||||
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
|
||||
|
||||
|
||||
aclManagerDelegate.update(user, node, accessType, ses);
|
||||
|
||||
}catch(RepositoryException re){
|
||||
log.error("jcr error extracting archive", re);
|
||||
throw new WebApplicationException(new BackendGenericError("jcr error setting acl", re));
|
||||
|
@ -191,21 +202,21 @@ public class ACLManager extends Impersonable {
|
|||
@Consumes(MediaType.TEXT_PLAIN)
|
||||
@Path("{id}/acls/{user}")
|
||||
public void removeACL(@PathParam("user") String user) {
|
||||
InnerMethodName.instance.set("removeACLById");
|
||||
InnerMethodName.set("removeACLById");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
|
||||
if (!(item instanceof SharedFolder))
|
||||
throw new InvalidItemException("the item is not a shared folder");
|
||||
|
||||
|
||||
if (item instanceof VreFolder || ((SharedFolder) item).isVreFolder())
|
||||
throw new InvalidCallParameters("acls in vreFolder cannot be removed with this method");
|
||||
|
||||
|
||||
authChecker.checkAdministratorControl(ses, currentUser, (SharedFolder) item);
|
||||
|
||||
unshareHandler.unshare(ses, Collections.singleton(user), node, currentUser);
|
||||
|
@ -225,11 +236,11 @@ public class ACLManager extends Impersonable {
|
|||
@GET
|
||||
@Path("{id}/acls/write")
|
||||
public Boolean canWriteInto() {
|
||||
InnerMethodName.instance.set("canWriteIntoFolder");
|
||||
InnerMethodName.set("canWriteIntoFolder");
|
||||
Session ses = null;
|
||||
Boolean canWrite = false;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
if (!(item instanceof FolderItem))
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.WebApplicationException;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Path("api-docs")
|
||||
public class DocsGenerator {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(DocsGenerator.class);
|
||||
|
||||
@GET
|
||||
@Path("/{any: .*}")
|
||||
public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException {
|
||||
logger.info(DocsGenerator.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) {
|
||||
logger.error("error getting the docs", e);
|
||||
throw new WebApplicationException(e,Status.SERVICE_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,132 +3,80 @@ 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.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
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;
|
||||
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.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.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.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.security.providers.SecretManagerProvider;
|
||||
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.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.data.access.storagehub.StorageHubApplicationManager;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
|
||||
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;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.DefaultValue;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
@Path("groups")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@Singleton
|
||||
@ManagedBy(StorageHubApplicationManager.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
|
||||
VREManager vreManager;
|
||||
|
||||
@Inject
|
||||
GroupHandler groupHandler;
|
||||
private final StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
@Inject
|
||||
GroupManagerDelegate groupHandler;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<String> getGroups(){
|
||||
|
||||
InnerMethodName.instance.set("getGroups");
|
||||
|
||||
InnerMethodName.set("getGroups");
|
||||
JackrabbitSession session = null;
|
||||
List<String> groups= new ArrayList<>();
|
||||
try {
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
|
||||
|
||||
@Override
|
||||
public <T> void build(QueryBuilder<T> builder) {
|
||||
builder.setSelector(Group.class);
|
||||
}
|
||||
});
|
||||
|
||||
while (result.hasNext()) {
|
||||
Authorizable group = result.next();
|
||||
log.info("group {} found",group.getPrincipal().getName());
|
||||
groups.add(group.getPrincipal().getName());
|
||||
}
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
groups = groupHandler.getGroups(session);
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||
|
@ -142,32 +90,14 @@ public class GroupManager {
|
|||
@POST
|
||||
@Path("")
|
||||
@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");
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
|
||||
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner, @FormDataParam("useDefaultStorage") @DefaultValue("true") boolean useDefaultStorage){
|
||||
|
||||
InnerMethodName.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();
|
||||
|
||||
Group createdGroup = usrManager.createGroup(group);
|
||||
groupId = createdGroup.getID();
|
||||
|
||||
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 = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
groupHandler.createGroup(session, group, accessType, folderOwner, useDefaultStorage);
|
||||
session.save();
|
||||
}catch(StorageHubException se) {
|
||||
log.error("error creating group {}", group, se);
|
||||
|
@ -179,37 +109,19 @@ public class GroupManager {
|
|||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
||||
return groupId;
|
||||
return group;
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{group}")
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
|
||||
public String deleteGroup(@PathParam("group") String group){
|
||||
|
||||
InnerMethodName.instance.set("deleteGroup");
|
||||
|
||||
InnerMethodName.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 {
|
||||
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);
|
||||
}
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
groupHandler.deleteGroup(session, group);
|
||||
session.save();
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error creating item", re);
|
||||
|
@ -222,51 +134,32 @@ public class GroupManager {
|
|||
}
|
||||
|
||||
|
||||
public boolean isInfraManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); }
|
||||
public boolean isInfraManager() { return SecretManagerProvider.get().getOwner().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); }
|
||||
|
||||
public boolean isVREManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(VREMANAGER_ROLE); }
|
||||
public boolean isVREManager() { return SecretManagerProvider.get().getOwner().getRoles().contains(VREMANAGER_ROLE); }
|
||||
|
||||
@PUT
|
||||
@Path("{id}/admins")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
||||
|
||||
InnerMethodName.instance.set("addAdmin");
|
||||
InnerMethodName.set("addAdmin");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
try {
|
||||
Objects.nonNull(groupId);
|
||||
Objects.nonNull(userId);
|
||||
Objects.nonNull(userId);
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
|
||||
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
|
||||
String currentUser = SecretManagerProvider.get().getOwner().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 (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)) &&
|
||||
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser))
|
||||
throw new UserNotAuthorizedException();
|
||||
|
||||
if (!group.isMember(authUser))
|
||||
throw new InvalidCallParameters("user "+userId+" is not in the group "+groupId);
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
groupHandler.addAdministratorToGroup(session, groupId, userId);
|
||||
|
||||
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);
|
||||
|
@ -278,6 +171,8 @@ public class GroupManager {
|
|||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@DELETE
|
||||
|
@ -285,35 +180,23 @@ public class GroupManager {
|
|||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){
|
||||
|
||||
InnerMethodName.instance.set("removeAdmin");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
InnerMethodName.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();
|
||||
String currentUser = SecretManagerProvider.get().getOwner().getId();
|
||||
|
||||
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
|
||||
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
|
||||
|
||||
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)) &&
|
||||
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser))
|
||||
throw new UserNotAuthorizedException();
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
groupHandler.removeAdministratorFromGroup(session, groupId, userId);
|
||||
|
||||
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);
|
||||
|
@ -321,7 +204,7 @@ public class GroupManager {
|
|||
}catch(Throwable re ){
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re));
|
||||
}finally {
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -332,37 +215,19 @@ public class GroupManager {
|
|||
@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;
|
||||
InnerMethodName.set("getAdmins");
|
||||
List<String> users = new ArrayList<>();
|
||||
JackrabbitSession session = null;
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
users = groupHandler.getGroupAdministators(session, groupId);
|
||||
}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 {
|
||||
}catch(Throwable re ){
|
||||
log.error("jcr error getting admins", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting admins", re));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -374,41 +239,29 @@ public class GroupManager {
|
|||
@PUT
|
||||
@Path("{id}/users")
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE})
|
||||
public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){
|
||||
|
||||
InnerMethodName.instance.set("addUserToGroup");
|
||||
|
||||
InnerMethodName.set("addUserToGroup");
|
||||
JackrabbitSession session = null;
|
||||
boolean success = false;
|
||||
try {
|
||||
|
||||
if (!isInfraManager() && !isValidGroupForContext(groupId))
|
||||
if (!isInfraManager() && !(isVREManager() && 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();
|
||||
|
||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||
User user = (User)usrManager.getAuthorizable(userId);
|
||||
|
||||
if (user==null)
|
||||
throw new InvalidCallParameters("user "+userId+" not exists");
|
||||
|
||||
if (group.isMember(user))
|
||||
throw new InvalidCallParameters("user "+userId+" is already member of group "+groupId);
|
||||
|
||||
this.internalAddUserToGroup(session, group, user);
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
groupHandler.addUserToGroup(session, userId, groupId);
|
||||
|
||||
success = true;
|
||||
session.save();
|
||||
}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 {
|
||||
log.error("jcr error adding user to group", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error adding user to group", re));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -416,43 +269,25 @@ 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(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE})
|
||||
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
|
||||
|
||||
InnerMethodName.instance.set("removeUserFromGroup");
|
||||
InnerMethodName.set("removeUserFromGroup");
|
||||
|
||||
JackrabbitSession session = null;
|
||||
boolean success = false;
|
||||
try {
|
||||
|
||||
if (!isValidGroupForContext(groupId) && !isInfraManager())
|
||||
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)))
|
||||
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
success = groupHandler.removeUserFromGroup(groupId, userId, session);
|
||||
success = groupHandler.removeUserFromGroup(session, groupId, userId);
|
||||
|
||||
session.save();
|
||||
}catch(StorageHubException she ){
|
||||
|
@ -472,39 +307,25 @@ public class GroupManager {
|
|||
@GET
|
||||
@Path("{groupId}/users")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE})
|
||||
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
|
||||
|
||||
InnerMethodName.instance.set("getUsersOfGroup");
|
||||
|
||||
InnerMethodName.set("getUsersOfGroup");
|
||||
JackrabbitSession session = null;
|
||||
List<String> users = new ArrayList<>();
|
||||
try {
|
||||
|
||||
if (!isValidGroupForContext(groupId) && !isInfraManager())
|
||||
|
||||
if (!isInfraManager() && !(isVREManager() && 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();
|
||||
|
||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||
|
||||
Iterator<Authorizable> it = group.getMembers();
|
||||
|
||||
while (it.hasNext()) {
|
||||
Authorizable user = it.next();
|
||||
users.add(user.getPrincipal().getName());
|
||||
}
|
||||
|
||||
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
|
||||
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
users = groupHandler.getUsersBelongingToGroup(session, groupId);
|
||||
}catch (StorageHubException e) {
|
||||
log.error("error getting users", e);
|
||||
GXOutboundErrorResponse.throwException(e);
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error creating item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||
}finally {
|
||||
log.error("jcr error getting users", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting users", re));
|
||||
} finally {
|
||||
if (session!=null)
|
||||
session.logout();
|
||||
}
|
||||
|
@ -512,51 +333,11 @@ public class GroupManager {
|
|||
return users;
|
||||
}
|
||||
|
||||
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 currentScope = ScopeProvider.instance.get();
|
||||
ScopeBean bean = new ScopeBean(currentScope);
|
||||
while (!bean.is(Type.INFRASTRUCTURE)) {
|
||||
bean = bean.enclosingScope();
|
||||
}
|
||||
String root = bean.toString().replaceAll("/", "");
|
||||
|
||||
String displayName = groupId.replaceAll(root+"-[^\\-]*\\-(.*)", "$1");
|
||||
|
||||
log.info("creating vreFolder with name {} and title {} and owner {}", name, displayName, owner);
|
||||
|
||||
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).description( "VREFolder for "+groupId).author(owner).on(sharedRootNode.getIdentifier()).with(session).build();
|
||||
|
||||
Node folder= Utils.createFolderInternally(folderParameters, null);
|
||||
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
||||
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
|
||||
folder.setProperty(NodeProperty.TITLE.toString(), name);
|
||||
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()) };
|
||||
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 boolean isValidGroupForContext(String group){
|
||||
String currentContext = ScopeProvider.instance.get();
|
||||
String currentContext = SecretManagerProvider.get().getContext();
|
||||
String expectedGroupId= currentContext.replace("/", "-").substring(1);
|
||||
return group.equals(expectedGroupId);
|
||||
}
|
||||
|
|
|
@ -3,36 +3,33 @@ 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.gcube.common.security.Owner;
|
||||
import org.gcube.common.security.providers.SecretManagerProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
|
||||
@Path("")
|
||||
public abstract class Impersonable {
|
||||
|
||||
Logger log = LoggerFactory.getLogger(Impersonable.class);
|
||||
|
||||
String currentUser;
|
||||
|
||||
String currentUser = null;
|
||||
|
||||
@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)) {
|
||||
Owner owner = SecretManagerProvider.get().getOwner();
|
||||
if(impersonate!=null && owner.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
|
||||
this.currentUser = impersonate;
|
||||
} else
|
||||
this.currentUser = info.getId();
|
||||
this.currentUser = owner.getId();
|
||||
|
||||
log.info("called with login {} and impersonate {}",info.getId(), impersonate);
|
||||
log.info("called with login {} and impersonate {}",owner.getId(), impersonate);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,24 +4,12 @@ import java.util.HashMap;
|
|||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
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.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;
|
||||
|
@ -43,26 +31,44 @@ 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.UnshareHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
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;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
|
||||
|
||||
@Path("items")
|
||||
@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);
|
||||
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
private final StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
@ -73,10 +79,10 @@ public class ItemSharing extends Impersonable{
|
|||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
|
@ -86,15 +92,15 @@ public class ItemSharing extends Impersonable{
|
|||
@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");
|
||||
InnerMethodName.set("shareFolder");
|
||||
HashMap<String,String> mapUserPermission;
|
||||
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
|
@ -105,17 +111,17 @@ public class ItemSharing extends Impersonable{
|
|||
}
|
||||
AccessType defaultAccessType;
|
||||
try {
|
||||
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
|
||||
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
|
||||
}catch (IllegalArgumentException e) {
|
||||
throw new InvalidCallParameters("invalid default accessType");
|
||||
}
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
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");
|
||||
|
||||
|
@ -194,13 +200,12 @@ public class ItemSharing extends Impersonable{
|
|||
@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");
|
||||
InnerMethodName.set("shareFolder");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||
|
@ -211,6 +216,8 @@ public class ItemSharing extends Impersonable{
|
|||
if (users==null || users.isEmpty())
|
||||
throw new InvalidCallParameters("users is empty");
|
||||
|
||||
log.info("shared method called with users {} and default access type {} ", users, accessType.getValue());
|
||||
|
||||
Node nodeToShare = ses.getNodeByIdentifier(id);
|
||||
|
||||
boolean alreadyShared = false;
|
||||
|
@ -244,8 +251,9 @@ public class ItemSharing extends Impersonable{
|
|||
for (String user : users)
|
||||
try {
|
||||
addUserToSharing(sharedFolderNode, ses, user, null, userPrivileges, acls);
|
||||
log.info("added user {} to the shared node",user);
|
||||
}catch(Exception e){
|
||||
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName());
|
||||
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName(),e);
|
||||
}
|
||||
|
||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||
|
@ -267,6 +275,9 @@ public class ItemSharing extends Impersonable{
|
|||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}catch(Exception e){
|
||||
log.error("jcr sharing", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error sharing folder", e));
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
|
@ -278,7 +289,7 @@ public class ItemSharing extends Impersonable{
|
|||
|
||||
|
||||
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
|
||||
|
||||
|
||||
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");
|
||||
|
||||
|
@ -296,30 +307,35 @@ public class ItemSharing extends Impersonable{
|
|||
}
|
||||
|
||||
private void addUserToSharing(Node sharedFolderNode, Session ses, String user, Item itemToShare, Privilege[] userPrivileges, JackrabbitAccessControlList acls) throws RepositoryException{
|
||||
String userRootWSId;
|
||||
String userPath;
|
||||
if (itemToShare==null) {
|
||||
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
|
||||
userRootWSId = ses.getNode(userRootWS).getIdentifier();
|
||||
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
|
||||
try {
|
||||
String userRootWSId;
|
||||
String userPath;
|
||||
if (itemToShare==null) {
|
||||
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
|
||||
userRootWSId = ses.getNode(userRootWS).getIdentifier();
|
||||
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
|
||||
}
|
||||
else {
|
||||
userPath = itemToShare.getPath();
|
||||
userRootWSId = itemToShare.getParentId();
|
||||
}
|
||||
|
||||
|
||||
log.info("cloning directory to {} ",userPath);
|
||||
|
||||
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), userPath , false);
|
||||
|
||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
|
||||
Node usersNode =null;
|
||||
if (sharedFolderNode.hasNode(NodeConstants.USERS_NAME))
|
||||
usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
|
||||
else
|
||||
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
|
||||
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString()));
|
||||
}catch (Exception e) {
|
||||
log.error("error sharing node with user {}",user,e);
|
||||
throw new RepositoryException(e);
|
||||
}
|
||||
else {
|
||||
userPath = itemToShare.getPath();
|
||||
userRootWSId = itemToShare.getParentId();
|
||||
}
|
||||
|
||||
|
||||
log.info("cloning directory to {} ",userPath);
|
||||
|
||||
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), userPath , false);
|
||||
|
||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
|
||||
Node usersNode =null;
|
||||
if (sharedFolderNode.hasNode(NodeConstants.USERS_NAME))
|
||||
usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
|
||||
else
|
||||
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
|
||||
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -327,12 +343,12 @@ public class ItemSharing extends Impersonable{
|
|||
@Path("{id}/unshare")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public String unshare(@FormDataParam("users") Set<String> users){
|
||||
InnerMethodName.instance.set("unshareFolder");
|
||||
InnerMethodName.set("unshareFolder");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try {
|
||||
log.debug("unsharing folder with id {} with users {}", id, users);
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node sharedNode = ses.getNodeByIdentifier(id);
|
||||
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
|
||||
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveException;
|
||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||
import org.gcube.common.storagehub.model.plugins.PluginParameters;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
|
||||
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;
|
||||
|
@ -31,6 +31,7 @@ import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationPa
|
|||
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.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.smartgears.annotations.ManagedBy;
|
||||
import org.gcube.smartgears.utils.InnerMethodName;
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
|
@ -38,32 +39,50 @@ 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;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
|
||||
@Path("items")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@ManagedBy(StorageHubApplicationManager.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);
|
||||
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
private final StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
ItemHandler itemHandler;
|
||||
|
||||
|
||||
@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) {
|
||||
InnerMethodName.instance.set("createItem(FOLDER)");
|
||||
InnerMethodName.set("createItem(FOLDER)");
|
||||
log.info("create folder item called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
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 ){
|
||||
|
@ -84,21 +103,31 @@ public class ItemsCreator extends Impersonable{
|
|||
}
|
||||
|
||||
@POST
|
||||
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
|
||||
@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)");
|
||||
@Context HttpServletRequest request) {
|
||||
InnerMethodName.set("createItem(EXTERNALFOLDER)");
|
||||
log.info("create folder item called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
//TODO
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
Iterator<String> paramIt = request.getParameterNames().asIterator();
|
||||
Iterable<String> iterable = () -> paramIt;
|
||||
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);
|
||||
|
||||
PluginParameters pluginParams = new PluginParameters();
|
||||
|
||||
targetStream.filter(v -> v.startsWith("plugin."))
|
||||
.forEach(v -> pluginParams.add(v.replace("plugin.", ""), request.getParameter(v)));
|
||||
|
||||
log.debug("parameters for external folder with plugin {} are {}",pluginName, pluginParams.toString());
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
|
||||
.description(description).onRepository(pluginName).withParameters(null).hidden(hidden).on(id).with(ses).author(currentUser);
|
||||
.description(description).onRepository(pluginName).withParameters(pluginParams.getParameters()).hidden(hidden).on(id).with(ses).author(currentUser);
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
|
@ -116,18 +145,18 @@ public class ItemsCreator extends Impersonable{
|
|||
}
|
||||
return Response.ok(toReturn).build();
|
||||
}
|
||||
|
||||
|
||||
@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) {
|
||||
InnerMethodName.instance.set("createItem(URL)");
|
||||
InnerMethodName.set("createItem(URL)");
|
||||
log.info("create url called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name).description(description).url(value).on(id).with(ses).author(currentUser);
|
||||
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
|
@ -147,21 +176,21 @@ public class ItemsCreator extends Impersonable{
|
|||
}
|
||||
return Response.ok(toReturn).build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/create/GCUBEITEM")
|
||||
public String createGcubeItem(@PathParam("id") String id, GCubeItem item) {
|
||||
InnerMethodName.instance.set("createItem(GCUBEITEM)");
|
||||
InnerMethodName.set("createItem(GCUBEITEM)");
|
||||
log.info("create Gcube item called");
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder().item(item).on(id).with(ses).author(currentUser);
|
||||
|
||||
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
|
@ -181,24 +210,31 @@ public class ItemsCreator extends Impersonable{
|
|||
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@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){
|
||||
InnerMethodName.instance.set("createItem(FILE)");
|
||||
public String createFileItemFromUrl(@PathParam("id") String id, @FormParam("name") String name,
|
||||
@FormParam("description") String description,
|
||||
@FormParam("url") String url){
|
||||
InnerMethodName.set("createItem(FILEFromUrl)");
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
|
||||
log.debug("UPLOAD: call started");
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description(description).stream(stream).fileDetails(fileDetail)
|
||||
.on(id).with(ses).author(currentUser);
|
||||
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
|
||||
URLConnection connectionURL = new URI(url).toURL().openConnection();
|
||||
|
||||
long fileLength = connectionURL.getContentLengthLong();
|
||||
|
||||
try(InputStream stream = connectionURL.getInputStream()){
|
||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).fileDetails(FormDataContentDisposition.name(name).size(fileLength).build())
|
||||
.description(description).stream(stream)
|
||||
.on(id).with(ses).author(currentUser);
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
}
|
||||
log.debug("UPLOAD: call finished");
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error creating file item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
|
||||
|
@ -218,10 +254,83 @@ public class ItemsCreator extends Impersonable{
|
|||
|
||||
}
|
||||
|
||||
|
||||
@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 file,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||
InnerMethodName.set("createItem(FILE)");
|
||||
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try(InputStream is = new BufferedInputStream(file)){
|
||||
|
||||
long size = fileDetail.getSize();
|
||||
|
||||
log.info("UPLOAD: call started with file size {}",size);
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description(description).stream(file).fileDetails(fileDetail)
|
||||
.on(id).with(ses).author(currentUser);
|
||||
log.debug("UPLOAD: item prepared");
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
log.debug("UPLOAD: call finished");
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error creating file item", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}catch(Throwable e ){
|
||||
log.error("unexpected error", e);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
||||
}finally{
|
||||
if (ses!=null && ses.isLive()) {
|
||||
log.info("session closed");
|
||||
ses.logout();
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
@Path("/{id}/create/ARCHIVE")
|
||||
public String uploadArchiveFromURL(@PathParam("id") String id, @FormParam("parentFolderName") String parentFolderName,
|
||||
@FormParam("url") String url){
|
||||
InnerMethodName.set("createItem(ARCHIVEFromURL)");
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
try(InputStream stream = new URI(url).toURL().openStream()){
|
||||
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(stream)
|
||||
.on(id).with(ses).author(currentUser);
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
}
|
||||
|
||||
}catch(RepositoryException | ArchiveException | IOException re){
|
||||
log.error("jcr error extracting archive", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
||||
}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)
|
||||
|
@ -229,16 +338,16 @@ public class ItemsCreator extends Impersonable{
|
|||
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
|
||||
@FormDataParam("file") InputStream stream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||
InnerMethodName.instance.set("createItem(ARCHIVE)");
|
||||
InnerMethodName.set("createItem(ARCHIVE)");
|
||||
|
||||
Session ses = null;
|
||||
String toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
try(InputStream is = new BufferedInputStream(stream)){
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail)
|
||||
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(is).fileDetails(fileDetail)
|
||||
.on(id).with(ses).author(currentUser);
|
||||
|
||||
|
||||
toReturn = itemHandler.create(builder.build());
|
||||
|
||||
}catch(RepositoryException | ArchiveException | IOException re){
|
||||
|
@ -259,6 +368,6 @@ public class ItemsCreator extends Impersonable{
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,24 +1,13 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import static org.gcube.common.storagehub.model.Constants.enchriptedPrefix;
|
||||
import static org.gcube.common.storagehub.model.Constants.versionPrefix;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
|
@ -26,39 +15,16 @@ import javax.jcr.RepositoryException;
|
|||
import javax.jcr.Session;
|
||||
import javax.jcr.lock.LockException;
|
||||
import javax.jcr.version.Version;
|
||||
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.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 javax.ws.rs.core.StreamingOutput;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
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;
|
||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||
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.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;
|
||||
|
@ -66,47 +32,71 @@ 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;
|
||||
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||
import org.gcube.common.storagehub.model.types.FolderInfoType;
|
||||
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.StorageHubApplicationManager;
|
||||
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.DownloadHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.PublicLinkHandler;
|
||||
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.data.access.storagehub.handlers.plugins.StorageOperationMediator;
|
||||
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
|
||||
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
import org.gcube.data.access.storagehub.types.PublicLink;
|
||||
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;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
|
||||
@Path("items")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@ManagedBy(StorageHubApplicationManager.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);
|
||||
|
||||
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
private final StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
||||
@RequestScoped
|
||||
@PathParam("id")
|
||||
String id;
|
||||
|
||||
|
@ -115,35 +105,40 @@ public class ItemsManager extends Impersonable{
|
|||
|
||||
@Inject
|
||||
AuthorizationChecker authChecker;
|
||||
|
||||
|
||||
@Inject
|
||||
VersionHandler versionHandler;
|
||||
|
||||
@Inject
|
||||
DownloadHandler downloadHandler;
|
||||
|
||||
@Inject
|
||||
TrashHandler trashHandler;
|
||||
|
||||
@Inject PathUtil pathUtil;
|
||||
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
@Inject Item2NodeConverter item2Node;
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderPluginHandler;
|
||||
|
||||
StorageOperationMediator opMediator;
|
||||
|
||||
|
||||
@Inject
|
||||
CompressHandler compressHandler;
|
||||
|
||||
|
||||
PublicLinkHandler publicLinkHandler;
|
||||
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemWrapper<Item> getById(@QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("getById");
|
||||
InnerMethodName.set("getById");
|
||||
Session ses = null;
|
||||
Item toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = node2Item.getItem(node, excludes);
|
||||
|
@ -168,11 +163,11 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/path")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("getByPath");
|
||||
InnerMethodName.set("getByPath");
|
||||
Session ses = null;
|
||||
Item toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
String relativePath = path.startsWith("/")? path.substring(1) : path;
|
||||
|
@ -230,7 +225,7 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/items/{name}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
|
||||
InnerMethodName.instance.set("findChildrenByNamePattern");
|
||||
InnerMethodName.set("findChildrenByNamePattern");
|
||||
return _findChildrenByNamePattern(excludes, name);
|
||||
}
|
||||
|
||||
|
@ -238,15 +233,15 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/items")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
|
||||
InnerMethodName.instance.set("findChildrenByNamePattern");
|
||||
InnerMethodName.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));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
//NOT using the internal pattern matching of jcr because of title for shared folder
|
||||
|
@ -278,23 +273,24 @@ public class ItemsManager extends Impersonable{
|
|||
if (ses!=null)
|
||||
ses.logout();
|
||||
}
|
||||
|
||||
|
||||
return new ItemList(toReturn);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/children/count")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||
InnerMethodName.instance.set("countById");
|
||||
InnerMethodName.set("countById");
|
||||
Session ses = null;
|
||||
Long toReturn = null;
|
||||
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
toReturn = Utils.getItemCount(node, showHidden==null?false:showHidden, itemPredicate );
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||
|
@ -315,13 +311,15 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/children")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||
InnerMethodName.instance.set("listById");
|
||||
InnerMethodName.set("listById");
|
||||
Session ses = null;
|
||||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
toReturn = Utils.getItemList(node, excludes, null, showHidden==null?false:showHidden, itemPredicate);
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||
|
@ -343,14 +341,16 @@ public class ItemsManager extends Impersonable{
|
|||
@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");
|
||||
InnerMethodName.set("search");
|
||||
Session ses = null;
|
||||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
log.debug("search for node {}",name);
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
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);
|
||||
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
toReturn = Utils.searchByNameOnFolder(ses, currentUser, authChecker, node, excludes, null, showHidden==null?false:showHidden, excludeTrashed==true?false:excludeTrashed, itemPredicate, name);
|
||||
log.debug("search retrieved {} elements",toReturn.size());
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
|
@ -373,13 +373,15 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/children/paged")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList listByIdPaged(@QueryParam("showHidden") Boolean showHidden, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||
InnerMethodName.instance.set("listByIdPaged");
|
||||
InnerMethodName.set("listByIdPaged");
|
||||
Session ses = null;
|
||||
List<? extends Item> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
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);
|
||||
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
toReturn = Utils.getItemList(node, excludes, new Range(start, limit),showHidden==null?false:showHidden, itemPredicate);
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||
|
@ -399,62 +401,26 @@ public class ItemsManager extends Impersonable{
|
|||
|
||||
@GET
|
||||
@Path("publiclink/{id}")
|
||||
@AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
|
||||
@AuthorizationControl(allowedUsers={"URIResolver"})
|
||||
public Response resolvePublicLink() {
|
||||
InnerMethodName.instance.set("resolvePubliclink");
|
||||
InnerMethodName.set("resolvePubliclink");
|
||||
|
||||
log.warn("arrived id is {}",id);
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
String complexId = id;
|
||||
|
||||
if (id.startsWith(enchriptedPrefix)) {
|
||||
String currentScope = ScopeProvider.instance.get();
|
||||
try {
|
||||
ScopeBean bean= new ScopeBean(currentScope);
|
||||
while (!bean.is(Type.INFRASTRUCTURE)) {
|
||||
bean = bean.enclosingScope();
|
||||
}
|
||||
|
||||
ScopeProvider.instance.set(bean.toString());
|
||||
complexId = StringEncrypter.getEncrypter().decrypt(new String(Base64.getUrlDecoder().decode(id.replace(enchriptedPrefix, ""))));
|
||||
}catch(Exception e){
|
||||
throw new BackendGenericError("invalid public url",e);
|
||||
}finally {
|
||||
ScopeProvider.instance.set(currentScope);
|
||||
}
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
PublicLink publicLink = publicLinkHandler.resolveEnchriptedId(id);
|
||||
switch (publicLink.getType()) {
|
||||
case VOLATILE:
|
||||
return downloadHandler.downloadFileFromStorageBackend(publicLink.getId(), publicLink.getStorageName());
|
||||
case VERSIONED:
|
||||
Item versionedItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT);
|
||||
return downloadHandler.downloadVersionedItem(ses, currentUser, (AbstractFileItem) versionedItem, publicLink.getVersion(), true);
|
||||
default:
|
||||
Item currentItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT);
|
||||
return downloadHandler.downloadFileItem(ses,(AbstractFileItem) currentItem, currentUser, true);
|
||||
}
|
||||
|
||||
String itemId = complexId;
|
||||
String versionName = null;
|
||||
|
||||
if (complexId.contains(versionPrefix)) {
|
||||
String[] split = complexId.split(versionPrefix);
|
||||
itemId = split[0];
|
||||
versionName = split[1];
|
||||
}
|
||||
|
||||
log.warn("item id to retrieve is {}",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, currentUser, itemId, versionName, false);
|
||||
else
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
||||
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error getting public link", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||
|
@ -472,11 +438,11 @@ public class ItemsManager extends Impersonable{
|
|||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{id}/publiclink")
|
||||
public URL getPublicLink(@QueryParam("version") String version) {
|
||||
InnerMethodName.instance.set("getPubliclink");
|
||||
InnerMethodName.set("getPubliclink");
|
||||
Session ses = null;
|
||||
URL toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
Node selectedNode = ses.getNodeByIdentifier(id);
|
||||
|
@ -505,28 +471,10 @@ public class ItemsManager extends Impersonable{
|
|||
ses.getWorkspace().getLockManager().unlock(selectedNode.getPath());
|
||||
}*/
|
||||
|
||||
String url = null;
|
||||
String currentScope = ScopeProvider.instance.get();
|
||||
try {
|
||||
ScopeBean bean= new ScopeBean(currentScope);
|
||||
while (!bean.is(Type.INFRASTRUCTURE)) {
|
||||
bean = bean.enclosingScope();
|
||||
}
|
||||
|
||||
ScopeProvider.instance.set(bean.toString());
|
||||
String url = version!=null ? publicLinkHandler.getForVersionedItem(id, version, context):
|
||||
publicLinkHandler.getForItem(id, context);
|
||||
|
||||
String toEnchript;
|
||||
if(version!=null) toEnchript = String.format("%s%s%s",id, versionPrefix, version);
|
||||
else toEnchript = id;
|
||||
|
||||
String enchriptedQueryString = StringEncrypter.getEncrypter().encrypt(toEnchript);
|
||||
|
||||
url = createPublicLink(new String(Base64.getUrlEncoder().encode(enchriptedQueryString.getBytes())));
|
||||
}catch(Exception e){
|
||||
throw new BackendGenericError(e);
|
||||
}finally {
|
||||
ScopeProvider.instance.set(currentScope);
|
||||
}
|
||||
|
||||
toReturn = new URL(url);
|
||||
|
||||
|
@ -545,21 +493,19 @@ public class ItemsManager extends Impersonable{
|
|||
}
|
||||
|
||||
|
||||
private String createPublicLink(String enchriptedString) {
|
||||
String basepath = context.getInitParameter("resolver-basepath");
|
||||
String filePublicUrl = String.format("%s/%s%s",basepath, enchriptedPrefix, enchriptedString);
|
||||
return filePublicUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@PUT
|
||||
@Path("{id}/publish")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String makeFolderPublic(@FormParam("publish") boolean publish){
|
||||
InnerMethodName.instance.set("makeFolderPublic("+publish+")");
|
||||
InnerMethodName.set("makeFolderPublic("+publish+")");
|
||||
Session ses = null;
|
||||
Item folder= null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
Node currentNode =ses.getNodeByIdentifier(id);
|
||||
log.trace("current node is {}",currentNode.getPath());
|
||||
|
@ -574,7 +520,7 @@ public class ItemsManager extends Impersonable{
|
|||
ses.save();
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error getting rootSharedFolder", re);
|
||||
log.error("jcr error publishing folder", re);
|
||||
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||
}catch(StorageHubException she ){
|
||||
log.error(she.getErrorMessage(), she);
|
||||
|
@ -591,11 +537,11 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/rootSharedFolder")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("getRootSharedFolder");
|
||||
InnerMethodName.set("getRootSharedFolder");
|
||||
Session ses = null;
|
||||
Item sharedParent= null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
Node currentNode =ses.getNodeByIdentifier(id);
|
||||
log.trace("current node is {}",currentNode.getPath());
|
||||
|
@ -634,11 +580,11 @@ public class ItemsManager extends Impersonable{
|
|||
@Path("{id}/versions")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public VersionList getVersions(){
|
||||
InnerMethodName.instance.set("getVersions");
|
||||
InnerMethodName.set("getVersions");
|
||||
Session ses = null;
|
||||
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
|
@ -670,13 +616,17 @@ public class ItemsManager extends Impersonable{
|
|||
@GET
|
||||
@Path("{id}/versions/{version}/download")
|
||||
public Response downloadVersion(@PathParam("version") String versionName){
|
||||
InnerMethodName.instance.set("downloadSpecificVersion");
|
||||
InnerMethodName.set("downloadSpecificVersion");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
Item currentItem = node2Item.getItem(node, Excludes.ALL);
|
||||
if (!(currentItem instanceof AbstractFileItem))
|
||||
throw new InvalidItemException("this item is not a file");
|
||||
|
||||
return downloadVersionInternal(ses, currentUser, id, versionName, true);
|
||||
return downloadHandler.downloadVersionedItem(ses, currentUser, (AbstractFileItem) currentItem, versionName, true);
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error downloading version", re);
|
||||
|
@ -691,56 +641,60 @@ public class ItemsManager extends Impersonable{
|
|||
return Response.serverError().build();
|
||||
}
|
||||
|
||||
private Response downloadVersionInternal(Session ses, String login, String id, String versionName, boolean withAccounting) throws RepositoryException, StorageHubException{
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
Item currentItem = node2Item.getItem(node, Excludes.ALL);
|
||||
if (!(currentItem instanceof AbstractFileItem))
|
||||
throw new InvalidItemException("this item is not a file");
|
||||
|
||||
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)) {
|
||||
Content content = node2Item.getContentFromVersion(version);
|
||||
|
||||
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());
|
||||
|
||||
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
||||
|
||||
if (withAccounting)
|
||||
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", content.getSize())
|
||||
.header("Content-Type", content.getMimeType())
|
||||
.build();
|
||||
}
|
||||
@DELETE
|
||||
@Path("{id}/versions/{version}")
|
||||
public void deleteVersion(@PathParam("version") String versionName){
|
||||
InnerMethodName.set("deleteVersion");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
Item currentItem = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT);
|
||||
if (!(currentItem instanceof AbstractFileItem))
|
||||
throw new InvalidItemException("this item is not a file");
|
||||
|
||||
List<Version> versions = versionHandler.getContentVersionHistory(node);
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for(Version version : versions)
|
||||
if (version.getName().equals(versionName)) {
|
||||
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
|
||||
if (currentVersion)
|
||||
throw new InvalidCallParameters("current version cannot be removed");
|
||||
versionHandler.removeContentVersion(node, versionName);
|
||||
accountingHandler.createVersionDeleted(currentItem.getTitle(), versionName, ses, node, currentUser, false);
|
||||
ses.save();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) throw new InvalidItemException("the version "+versionName+" is not valid or is current version for item "+currentItem.getTitle());
|
||||
}catch(RepositoryException re ){
|
||||
log.error("jcr error removing version", 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();
|
||||
}
|
||||
throw new InvalidItemException("the version is not valid");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GET
|
||||
@Path("{id}/anchestors")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("getAnchestors");
|
||||
InnerMethodName.set("getAnchestors");
|
||||
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
|
||||
Session ses = null;
|
||||
List<Item> toReturn = new LinkedList<>();
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
Node currentNode = ses.getNodeByIdentifier(id);
|
||||
Item currentItem = node2Item.getItem(currentNode, excludes);
|
||||
|
@ -790,50 +744,17 @@ public class ItemsManager extends Impersonable{
|
|||
@GET
|
||||
@Path("{id}/download")
|
||||
public Response download(@QueryParam("exclude") List<String> excludes){
|
||||
InnerMethodName.instance.set("downloadById");
|
||||
InnerMethodName.set("downloadById");
|
||||
Session ses = null;
|
||||
Response response = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
final Node node = ses.getNodeByIdentifier(id);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
final Item item = node2Item.getItem(node, null);
|
||||
if (item instanceof AbstractFileItem){
|
||||
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
|
||||
return downloadHandler.downloadFileItem(ses, (AbstractFileItem) item, currentUser, true);
|
||||
} else if (item instanceof FolderItem){
|
||||
|
||||
try {
|
||||
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() {
|
||||
|
||||
@Override
|
||||
public void write(OutputStream os) {
|
||||
|
||||
try(ZipOutputStream zos = new ZipOutputStream(os)){
|
||||
long start = System.currentTimeMillis();
|
||||
zos.setLevel(Deflater.BEST_COMPRESSION);
|
||||
log.debug("writing StreamOutput");
|
||||
compressHandler.zipNode(zos, allNodes, currentUser, originalPath);
|
||||
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
|
||||
} catch (Exception e) {
|
||||
log.error("error writing stream",e);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
response = Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+item.getTitle()+".zip")
|
||||
.header("Content-Type", "application/zip")
|
||||
.header("Content-Length", -1l)
|
||||
.build();
|
||||
|
||||
accountingHandler.createReadObj(item.getTitle(), ses, (Node) item.getRelatedNode(), currentUser, false);
|
||||
}finally {
|
||||
if (ses!=null) ses.save();
|
||||
}
|
||||
return downloadHandler.downloadFolderItem(ses, currentUser, (FolderItem)item, true);
|
||||
} else throw new InvalidItemException("item type not supported for download: "+item.getClass());
|
||||
|
||||
}catch(RepositoryException re ){
|
||||
|
@ -845,40 +766,19 @@ public class ItemsManager extends Impersonable{
|
|||
} finally{
|
||||
if (ses!=null) ses.logout();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, BackendGenericError {
|
||||
|
||||
FolderManager folderManager = folderPluginHandler.getFolderManager(fileItem);
|
||||
|
||||
final InputStream streamToWrite = folderManager.getStorageBackend().download(fileItem.getContent());
|
||||
|
||||
if (withAccounting)
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), ses, (Node) fileItem.getRelatedNode(), login, true);
|
||||
|
||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||
|
||||
return Response
|
||||
.ok(so)
|
||||
.header("content-disposition","attachment; filename = "+fileItem.getName())
|
||||
.header("Content-Length", fileItem.getContent().getSize())
|
||||
.header("Content-Type", fileItem.getContent().getMimeType())
|
||||
.build();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@PUT
|
||||
@Path("{id}/move")
|
||||
public String move(@FormParam("destinationId") String destinationId){
|
||||
InnerMethodName.instance.set("move");
|
||||
InnerMethodName.set("move");
|
||||
|
||||
Session ses = null;
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
||||
|
@ -922,11 +822,12 @@ public class ItemsManager extends Impersonable{
|
|||
|
||||
if (movingSharedItemOutside)
|
||||
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
|
||||
|
||||
//folderHandler.onMove(source, destination);
|
||||
|
||||
|
||||
//add onMove (if it changes the remotePath) and in case of different backend
|
||||
|
||||
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());
|
||||
|
@ -950,20 +851,20 @@ public class ItemsManager extends Impersonable{
|
|||
@PUT
|
||||
@Path("{id}/copy")
|
||||
public String copy(@FormParam("destinationId") String destinationId, @FormParam("fileName") String newFileName){
|
||||
InnerMethodName.instance.set("copy");
|
||||
InnerMethodName.set("copy");
|
||||
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root or if the item is thrashed
|
||||
Session ses = null;
|
||||
String newFileIdentifier = null;
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
|
||||
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
|
||||
|
||||
final Node nodeToCopy = ses.getNodeByIdentifier(id);
|
||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||
//Item destinationItem = node2Item.getItem(destination,null);
|
||||
FolderItem destinationItem = (FolderItem)node2Item.getItem(destination,null);
|
||||
|
||||
final Item item = node2Item.getItem(nodeToCopy, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
||||
|
||||
|
@ -976,6 +877,7 @@ public class ItemsManager extends Impersonable{
|
|||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destination, newFileName);
|
||||
String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
|
||||
|
@ -983,22 +885,20 @@ public class ItemsManager extends Impersonable{
|
|||
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 = manager.getStorageBackend().onCopy((AbstractFileItem) item);
|
||||
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
|
||||
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
||||
}
|
||||
Content contentToCopy = ((AbstractFileItem) item).getContent();
|
||||
|
||||
MetaInfo contentInfo = opMediator.copy(contentToCopy, destinationItem.getBackend(), destination.getPath(), uniqueName, currentUser);
|
||||
|
||||
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
||||
//replaces content copied with new information
|
||||
Utils.setContentFromMetaInfo((AbstractFileItem) item, contentInfo);
|
||||
|
||||
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;
|
||||
String mimeTypeForAccounting = ((AbstractFileItem) item).getContent().getMimeType();
|
||||
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
|
||||
|
||||
|
||||
|
@ -1026,26 +926,25 @@ public class ItemsManager extends Impersonable{
|
|||
@PUT
|
||||
@Path("{id}/rename")
|
||||
public Response rename(@FormParam("newName") String newName){
|
||||
InnerMethodName.instance.set("rename");
|
||||
InnerMethodName.set("rename");
|
||||
Session ses = null;
|
||||
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
|
||||
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||
|
||||
final Item item = node2Item.getItem(nodeToMove, null);
|
||||
|
||||
if (item instanceof SharedFolder)
|
||||
throw new InvalidItemException("shared folder");
|
||||
|
||||
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()))
|
||||
throw new InvalidItemException("protected folder cannot be renamed");
|
||||
|
||||
if (item instanceof SharedFolder)
|
||||
if (getSharedParentNode(nodeToMove).getIdentifier() == item.getId())
|
||||
throw new InvalidItemException("root shared folder name cannot be modfied");
|
||||
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
|
||||
|
||||
try {
|
||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
|
||||
|
@ -1053,10 +952,7 @@ public class ItemsManager extends Impersonable{
|
|||
}catch (LockException e) {
|
||||
throw new ItemLockedException(e);
|
||||
}
|
||||
|
||||
try {
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
|
||||
|
||||
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
|
||||
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
||||
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
|
||||
|
@ -1088,13 +984,13 @@ public class ItemsManager extends Impersonable{
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/hidden")
|
||||
public Response setItemAsHidden(Boolean hidden){
|
||||
InnerMethodName.instance.set("setHidden");
|
||||
InnerMethodName.set("setHidden");
|
||||
|
||||
Session ses = null;
|
||||
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
|
@ -1133,13 +1029,13 @@ public class ItemsManager extends Impersonable{
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/description")
|
||||
public Response setDescription(String description){
|
||||
InnerMethodName.instance.set("setDescription");
|
||||
InnerMethodName.set("setDescription");
|
||||
|
||||
Session ses = null;
|
||||
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
|
@ -1177,13 +1073,13 @@ public class ItemsManager extends Impersonable{
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/{id}/metadata")
|
||||
public Response setMetadata(org.gcube.common.storagehub.model.Metadata metadata){
|
||||
InnerMethodName.instance.set("updateMetadata");
|
||||
InnerMethodName.set("updateMetadata");
|
||||
|
||||
Session ses = null;
|
||||
|
||||
try{
|
||||
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
|
||||
|
@ -1222,15 +1118,15 @@ public class ItemsManager extends Impersonable{
|
|||
@DELETE
|
||||
@Path("{id}")
|
||||
public Response deleteItem(@QueryParam("force") boolean force){
|
||||
InnerMethodName.instance.set("deleteItem("+force+")");
|
||||
|
||||
InnerMethodName.set("deleteItem("+force+")");
|
||||
|
||||
Session ses = null;
|
||||
try{
|
||||
|
||||
log.info("removing node with id {}", id);
|
||||
|
||||
//TODO check if it is possible to change all the ACL on a workspace
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
|
||||
authChecker.checkMoveOpsForProtectedFolders(ses, id);
|
||||
|
@ -1243,7 +1139,7 @@ public class ItemsManager extends Impersonable{
|
|||
|
||||
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) {
|
||||
|
@ -1267,5 +1163,30 @@ public class ItemsManager extends Impersonable{
|
|||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@Path("{id}/info")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public FolderInfoType getFolderInfo() {
|
||||
InnerMethodName.set("getFolderInfo");
|
||||
Session ses = null;
|
||||
try {
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node node = ses.getNodeByIdentifier(id);
|
||||
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||
if (!(item instanceof FolderItem))
|
||||
throw new InvalidCallParameters("the item is not a folder");
|
||||
return Utils.getFolderInfo(node);
|
||||
} catch (RepositoryException re) {
|
||||
log.error("error getting workspace total size", 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 FolderInfoType(0, 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,28 +5,11 @@ 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;
|
||||
|
@ -40,37 +23,65 @@ 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.Content;
|
||||
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.storages.MetaInfo;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
|
||||
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.StorageHubApplicationManager;
|
||||
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.handlers.plugins.StorageBackendHandler;
|
||||
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
|
||||
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
|
||||
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
|
||||
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;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
@Path("messages")
|
||||
@ManagedBy(StorageHubAppllicationManager.class)
|
||||
@ManagedBy(StorageHubApplicationManager.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;
|
||||
|
||||
private final StoragehubRepository repository = StoragehubRepository.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
||||
|
@ -78,25 +89,25 @@ public class MessageManager extends Impersonable{
|
|||
@PathParam("id")
|
||||
String id;
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
@Inject PathUtil pathUtil;
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
@Inject Item2NodeConverter item2Node;
|
||||
|
||||
@Inject TrashHandler trashHandler;
|
||||
|
||||
|
||||
@Inject
|
||||
StorageBackendHandler storageBackendHandler;
|
||||
|
||||
@GET
|
||||
@Path("{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Message getById(){
|
||||
InnerMethodName.instance.set("getMessageById");
|
||||
InnerMethodName.set("getMessageById");
|
||||
Session ses = null;
|
||||
Message toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node messageNode = ses.getNodeByIdentifier(id);
|
||||
toReturn = node2Item.getMessageItem(messageNode);
|
||||
checkRights(currentUser, toReturn);
|
||||
|
@ -120,25 +131,28 @@ public class MessageManager extends Impersonable{
|
|||
@DELETE
|
||||
@Path("{id}")
|
||||
public void deleteById(){
|
||||
InnerMethodName.instance.set("deleteMessageById");
|
||||
InnerMethodName.set("deleteMessageById");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node messageNode = ses.getNodeByIdentifier(id);
|
||||
Message message = node2Item.getMessageItem(messageNode);
|
||||
Node personalNode = checkRights(currentUser, message);
|
||||
|
||||
if (countSharedSet(messageNode)>1)
|
||||
personalNode.removeShare();
|
||||
else {
|
||||
if (countSharedSet(messageNode)>1) {
|
||||
log.debug("removing node message "+personalNode.getPath());
|
||||
personalNode.remove();
|
||||
}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);
|
||||
ItemTypePredicate itemPredicate = new IncludeTypePredicate(AbstractFileItem.class);
|
||||
List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, itemPredicate);
|
||||
trashHandler.removeOnlyNodesContent(ses, attachments);
|
||||
}
|
||||
messageNode.removeSharedSet();
|
||||
}
|
||||
ses.save();
|
||||
log.debug("removing node message saved");
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||
|
@ -158,16 +172,17 @@ public class MessageManager extends Impersonable{
|
|||
@Path("{id}/attachments")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ItemList getAttachments(){
|
||||
InnerMethodName.instance.set("getAttachmentsByMessageId");
|
||||
InnerMethodName.set("getAttachmentsByMessageId");
|
||||
Session ses = null;
|
||||
List<Item> attachments = new ArrayList<>();
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
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);
|
||||
ItemTypePredicate itemPredicate = new IncludeTypePredicate(AbstractFileItem.class);
|
||||
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, itemPredicate);
|
||||
}catch (ItemNotFoundException e) {
|
||||
log.error("id {} not found",id,e);
|
||||
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
|
||||
|
@ -189,11 +204,11 @@ public class MessageManager extends Impersonable{
|
|||
@Path("inbox")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){
|
||||
InnerMethodName.instance.set("getReceivedMessages");
|
||||
InnerMethodName.set("getReceivedMessages");
|
||||
Session ses = null;
|
||||
List<Message> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath());
|
||||
|
||||
|
@ -214,11 +229,11 @@ public class MessageManager extends Impersonable{
|
|||
@Path("sent")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){
|
||||
InnerMethodName.instance.set("getSentMessages");
|
||||
InnerMethodName.set("getSentMessages");
|
||||
Session ses = null;
|
||||
List<Message> toReturn = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
|
||||
|
||||
|
@ -238,10 +253,10 @@ public class MessageManager extends Impersonable{
|
|||
@Path("{id}/{prop}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void setProperty(@PathParam("prop") String property,Object value){
|
||||
InnerMethodName.instance.set("setPropertyOnMessage("+property+")");
|
||||
InnerMethodName.set("setPropertyOnMessage("+property+")");
|
||||
Session ses = null;
|
||||
try{
|
||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
Node messageNode = ses.getNodeByIdentifier(id);
|
||||
Message messageItem = node2Item.getMessageItem(messageNode);
|
||||
checkRights(currentUser, messageItem);
|
||||
|
@ -271,7 +286,7 @@ public class MessageManager extends Impersonable{
|
|||
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");
|
||||
InnerMethodName.set("sendMessage");
|
||||
JackrabbitSession ses = null;
|
||||
String messageId = null;
|
||||
try{
|
||||
|
@ -280,7 +295,7 @@ public class MessageManager extends Impersonable{
|
|||
|
||||
log.debug("attachments send are {}",attachments);
|
||||
|
||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
ses = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
|
||||
|
||||
Message message = new MessageSharable();
|
||||
message.setAddresses(addresses.toArray(new String[0]));
|
||||
|
@ -288,6 +303,9 @@ public class MessageManager extends Impersonable{
|
|||
message.setBody(body);
|
||||
message.setName(UUID.randomUUID().toString());
|
||||
User user = ses.getUserManager().getAuthorizable(currentUser, User.class);
|
||||
|
||||
if (user ==null)
|
||||
throw new InvalidCallParameters("invalid storagehub user: "+currentUser);
|
||||
Owner owner = new Owner();
|
||||
owner.setUserId(user.getID());
|
||||
owner.setUserName(user.getPrincipal().getName());
|
||||
|
@ -325,7 +343,7 @@ public class MessageManager extends Impersonable{
|
|||
|
||||
|
||||
|
||||
private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, BackendGenericError{
|
||||
private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, StorageHubException{
|
||||
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
|
||||
|
||||
for (String itemId: attachments) {
|
||||
|
@ -345,7 +363,7 @@ public class MessageManager extends Impersonable{
|
|||
NodeIterator nodeIt = node.getNodes();
|
||||
while(nodeIt.hasNext()) {
|
||||
Node child = nodeIt.nextNode();
|
||||
log.info("message type "+child.getPrimaryNodeType().getName());
|
||||
log.trace("message type "+child.getPrimaryNodeType().getName());
|
||||
Message message = node2Item.getMessageItem(child);
|
||||
if (message == null) {
|
||||
log.info("message discarded");
|
||||
|
@ -375,13 +393,13 @@ public class MessageManager extends Impersonable{
|
|||
private Node checkRights(String user, Message messageItem) throws RepositoryException, StorageHubException{
|
||||
Node personalNode = null;
|
||||
Node messageNode = (Node) messageItem.getRelatedNode();
|
||||
if (messageNode.getPath().startsWith(pathUtil.getWorkspacePath(currentUser).toPath()))
|
||||
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.getWorkspacePath(currentUser).toPath()))
|
||||
if (node.getPath().startsWith(pathUtil.getInboxPath(user).toPath()))
|
||||
personalNode = node;
|
||||
}
|
||||
if (personalNode == null &&
|
||||
|
@ -390,10 +408,8 @@ public class MessageManager extends Impersonable{
|
|||
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{
|
||||
|
||||
private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, StorageHubException{
|
||||
//it needs to be locked ??
|
||||
Node nodeToCopy = ((Node)itemToCopy.getRelatedNode());
|
||||
String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() );
|
||||
|
@ -403,9 +419,15 @@ public class MessageManager extends Impersonable{
|
|||
|
||||
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);
|
||||
|
||||
Content contentToCopy = newNodeItem.getContent();
|
||||
|
||||
StorageBackendFactory sbf = storageBackendHandler.get(contentToCopy.getPayloadBackend());
|
||||
StorageBackend sb = sbf.create(contentToCopy.getPayloadBackend());
|
||||
|
||||
MetaInfo contentInfo = sb.onCopy(contentToCopy, destination.getPath(), uniqueName);
|
||||
|
||||
Utils.setContentFromMetaInfo(newNodeItem, contentInfo);
|
||||
item2Node.replaceContent(newNode, newNodeItem, ItemAction.CLONED);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
package org.gcube.data.access.storagehub.services;
|
||||
|
||||
import javax.jcr.Repository;
|
||||
|
||||
public interface RepositoryInitializer {
|
||||
|
||||
Repository getRepository();
|
||||
|
||||
void shutdown();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue