Compare commits

..

20 Commits

Author SHA1 Message Date
lucio 65a26149f4 updated 2024-10-21 17:11:49 +02:00
Massimiliano Assante fc37ffec6f Update 'enunciate.xml' 2023-05-30 12:41:55 +02:00
lucio e0a50f2a72 added header for swagger 2023-05-29 12:17:59 +02:00
lucio b4c9cfeee6 updated 2023-05-25 15:01:40 +02:00
lucio 7920345286 theme modified 2023-05-25 15:00:10 +02:00
lucio 80704b9df2 basepath changed for swagger 2023-05-25 14:53:27 +02:00
lucio a42919ffcf enunciate updated 2023-05-24 17:13:46 +02:00
lucio 6b54bf4554 enunciate files updated 2023-05-24 17:11:14 +02:00
lucio 122cba00e4 added DocManager to jersey initialiser 2023-05-24 15:00:19 +02:00
Lucio Lelii 60d9bf570c Update 'CHANGELOG.md' 2023-05-23 14:37:19 +02:00
Lucio Lelii f9870a0190 Update 'CHANGELOG.md' 2023-05-23 14:36:56 +02:00
lucio d9a229929b enunciate documentation added 2023-05-22 11:23:32 +02:00
Lucio Lelii 0b907277cd Update 'pom.xml' 2022-11-15 11:06:55 +01:00
Lucio Lelii 500aaa3fc9 Update 'pom.xml' 2022-11-15 10:52:33 +01:00
Lucio Lelii e167aa24d9 smartgears bom updated 2022-11-15 10:23:01 +01:00
Lucio Lelii 39d73b97c4 aspectj updated for java11 2022-11-15 10:16:29 +01:00
Lucio Lelii 4dc547afd2 Update 'CHANGELOG.md' 2022-11-14 12:06:28 +01:00
Lucio Lelii 122b326203 update for release 2022-11-14 12:05:16 +01:00
Lucio Lelii 1bbd1d200f added library to manage particular jpeg 2022-11-14 12:04:29 +01:00
Lucio Lelii 647dbb651a Update 'src/main/java/org/gcube/data/access/storagehub/services/MessageManager.java'
solved Incident #22230
2021-10-15 17:06:32 +02:00
143 changed files with 3767 additions and 6139 deletions

View File

@ -1,11 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"> <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/> <attribute name="optional" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"> <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes> <attributes>
<attribute name="test" value="true"/> <attribute name="test" value="true"/>
@ -18,23 +31,11 @@
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" output="target/classes" path="src/main/java"> <classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
<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"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

6
.gitignore vendored
View File

@ -1,8 +1,2 @@
target target
/Storagehub-TODO
/postgres-data/
.classpath
.settings/org.eclipse.jdt.core.prefs
/.project
/.externalToolBuilders/ /.externalToolBuilders/
/.settings/

View File

@ -6,13 +6,8 @@
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand> <buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> <name>org.eclipse.wst.common.project.facet.core.builder</name>
<triggers>full,incremental,</triggers>
<arguments> <arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.common.project.facet.core.builder.launch</value>
</dictionary>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>
@ -21,13 +16,8 @@
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> <name>org.eclipse.wst.validation.validationbuilder</name>
<triggers>full,incremental,</triggers>
<arguments> <arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.wst.validation.validationbuilder.launch</value>
</dictionary>
</arguments> </arguments>
</buildCommand> </buildCommand>
<buildCommand> <buildCommand>

View File

@ -1,16 +1,8 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.compliance=1.8
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.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=17 org.eclipse.jdt.core.compiler.source=1.8

View File

@ -18,22 +18,6 @@
@ -59,22 +43,6 @@
@ -100,22 +68,6 @@
@ -126,57 +78,27 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/> <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/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="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>
@ -196,6 +118,15 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
@ -237,22 +168,6 @@
@ -278,22 +193,6 @@
@ -319,22 +218,6 @@

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<faceted-project> <faceted-project>
<fixed facet="wst.jsdt.web"/> <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="jst.jaxrs" version="2.0"/>
<installed facet="wst.jsdt.web" version="1.0"/> <installed facet="wst.jsdt.web" version="1.0"/>
<installed facet="jst.web" version="4.0"/>
<installed facet="java" version="17"/>
</faceted-project> </faceted-project>

View File

@ -1,22 +1,23 @@
# Changelog for "storagehub" # Changelog
All notable changes to this project will be documented in this file. 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). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.0.0] ## [v1.4.2] - [2023-05-22]
- ceph as default storage - added enunciate libraries for documentation
- vre folders can define specific bucket as backend
- enunciate docs
- dockerization of the service
## [v1.4.0] 2021-10-07 ## [v1.4.1] - [2022-11-14]
- added libraries to manage different image format
## [v1.4.0] - [2021-10-07]
- slow query removed from VRE retrieving and recents - slow query removed from VRE retrieving and recents
- incident solved [#22184] - incident #22184 solved
## [v1.3.2] - [2021-09-28] ## [v1.3.2] - [2021-09-28]
- fix 22087 - fix 22087
## [v1.3.1] - [2021-09-08] ## [v1.3.1] - [2021-09-08]
@ -24,7 +25,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
## [v1.3.0] - [2021-03-31] ## [v1.3.0] - [2021-03-31]
possibility to impersonate people added - possibility to impersonate people added
## [v1.2.5] - [2021-03-11] ## [v1.2.5] - [2021-03-11]
@ -48,6 +49,8 @@ method for description update added
bug on Archive uploader solved bug on Archive uploader solved
## [v1.2.0] - [2020-04-15] ## [v1.2.0] - [2020-04-15]
trash items changes owner on restore trash items changes owner on restore
@ -56,14 +59,20 @@ restore with new destination folder added
move between shared and private or different shared folder enabled move between shared and private or different shared folder enabled
## [v1.0.8] - [2019-09-20] ## [v1.0.8] - [2019-09-20]
Bug on ushare owner fixed Bug on ushare owner fixed
## [v1.0.5] - [2019-04-04] ## [v1.0.5] - [2019-04-04]
Active wait for lock in case of item creation added Active wait for lock in case of item creation added
## [v1.0.0] - [2015-07-01] ## [v1.0.0] - [2015-07-01]
First commit First commit

View File

@ -1,22 +0,0 @@
# 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
```

View File

@ -1,3 +0,0 @@
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/

View File

@ -1,13 +0,0 @@
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/

View File

@ -1,8 +0,0 @@
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/

View File

@ -1,155 +0,0 @@
// 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

View File

@ -1,3 +0,0 @@
nodeType to remove on new import from a backup:
externalUrl

View File

@ -1,15 +0,0 @@
#!/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
distro/LICENSE Normal file
View File

@ -0,0 +1 @@
${gcube.license}

66
distro/README Normal file
View File

@ -0,0 +1,66 @@
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.

8
distro/gcube-app.xml Normal file
View File

@ -0,0 +1,8 @@
<application mode='online'>
<name>StorageHub</name>
<group>DataAccess</group>
<version>1.4.2</version>
<description>Storage Hub webapp</description>
<local-persistence location='target' />
<exclude>/workspace/api-docs/*</exclude>
</application>

View File

@ -1,50 +0,0 @@
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: {}

View File

@ -1,47 +0,0 @@
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: {}

View File

@ -1,10 +0,0 @@
version: '3.7'
services:
storagehub:
image: d4science/storagehub:latest
ports:
- '${APP_PORT}:8080'
volumes:
- ${JACKRABBIT_FOLDER}:/app/jackrabbit
- ${SMARTGEARS_CONFIG_FOLDER}:/etc

View File

@ -1,23 +0,0 @@
[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

View File

@ -1,18 +0,0 @@
# 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

View File

@ -1,21 +0,0 @@
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)

View File

@ -1,11 +0,0 @@
#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

View File

@ -1,111 +0,0 @@
<?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>

View File

@ -1,23 +0,0 @@
[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

View File

@ -1,10 +0,0 @@
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

View File

@ -1,25 +0,0 @@
<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>

View File

@ -1,6 +0,0 @@
${{adminId}}=workspace
${{adminPwd}}=gcube
${{db-host}}=postgres
${{ws-db}}=workspace-db
${{dbUser}}=ws-db-user
${{dbPwd}}=dbPwd

View File

@ -1,10 +0,0 @@
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

View File

@ -1,10 +0,0 @@
<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>

View File

@ -1,6 +0,0 @@
name: StorageHub
group: DataAccess
version: ${version}
description: ${description}
excludes:
- path: /workspace/api-docs/*

View File

@ -1,18 +0,0 @@
<?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>

440
pom.xml
View File

@ -4,50 +4,50 @@
<parent> <parent>
<artifactId>maven-parent</artifactId> <artifactId>maven-parent</artifactId>
<groupId>org.gcube.tools</groupId> <groupId>org.gcube.tools</groupId>
<version>1.2.0</version> <version>1.1.0</version>
<relativePath /> <relativePath />
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.gcube.data.access</groupId> <groupId>org.gcube.data.access</groupId>
<artifactId>storagehub</artifactId> <artifactId>storagehub</artifactId>
<version>2.0.0</version> <version>1.4.2</version>
<name>storagehub</name> <name>storagehub</name>
<scm> <scm>
<connection> <connection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection>
scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection> <developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
<developerConnection>
scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/storagehub</url> <url>https://code-repo.d4science.org/gCubeSystem/storagehub</url>
</scm> </scm>
<packaging>war</packaging> <packaging>war</packaging>
<properties> <properties>
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory> <webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
<jackrabbit.version>2.22.0</jackrabbit.version> <jackrabbit.version>2.20.2</jackrabbit.version>
<jackson.version>2.15.3</jackson.version> <jackson.version>2.8.11</jackson.version>
<slf4j.version>2.0.12</slf4j.version> <slf4j.version>1.7.4</slf4j.version>
<tika.version>2.6.0</tika.version> <tomcat.version>7.0.40</tomcat.version>
<aspectj-plugin.version>1.14.0</aspectj-plugin.version> <jetty.version>6.1.26</jetty.version>
<tika.version>1.21</tika.version>
<distroDirectory>${project.basedir}/distro</distroDirectory> <distroDirectory>${project.basedir}/distro</distroDirectory>
<description>REST web service for Jackrabbit</description> <description>REST web service for Jackrabbit</description>
<warname>storagehub</warname> <warname>storagehub</warname>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<enunciate.version>2.17.1</enunciate.version> <enunciate.version>2.14.0</enunciate.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<java_version>17</java_version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.gcube.distribution</groupId> <groupId>org.gcube.distribution</groupId>
<artifactId>gcube-smartgears-bom</artifactId> <artifactId>gcube-smartgears-bom</artifactId>
<version>4.0.0</version> <version>2.1.1</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version>
</dependency>
</dependencies> </dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
</dependencyManagement> </dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
@ -65,6 +65,7 @@
<dependency> <dependency>
<groupId>org.gcube.common</groupId> <groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId> <artifactId>authorization-control-library</artifactId>
<version>[1.0.0,2.0.0-SNAPSHOT)</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.gcube.common</groupId> <groupId>org.gcube.common</groupId>
@ -89,79 +90,13 @@
<dependency> <dependency>
<groupId>org.gcube.data.access</groupId> <groupId>org.gcube.data.access</groupId>
<artifactId>storagehub-script-utils</artifactId> <artifactId>storagehub-script-utils</artifactId>
<version>[2.0.0-SNAPSHOT,3.0.0)</version> <version>[1.0.0, 2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.itextpdf</groupId> <groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId> <artifactId>itextpdf</artifactId>
<version>5.5.13.2</version> <version>5.5.13.2</version>
</dependency> </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>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>2.19.3</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<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>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-core -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers-standard-package</artifactId>
<version>${tika.version}</version>
</dependency>
<!-- needed to manage strange image types --> <!-- needed to manage strange image types -->
<dependency> <dependency>
<groupId>com.twelvemonkeys.imageio</groupId> <groupId>com.twelvemonkeys.imageio</groupId>
@ -178,26 +113,101 @@
<artifactId>imageio-core</artifactId> <artifactId>imageio-core</artifactId>
<version>3.3.2</version> <version>3.3.2</version>
</dependency> </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>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>2.19.3</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<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>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.bull.javamelody/javamelody-core -->
<dependency>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.82.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
<!-- jersey & weld --> <!-- jersey & weld -->
<dependency> <dependency>
<groupId>jakarta.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency> </dependency>
<!-- <!-- https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
<dependency> <dependency>
<groupId>jakarta.interceptor</groupId> <groupId>javax.interceptor</groupId>
<artifactId>jakarta.interceptor-api</artifactId> <artifactId>javax.interceptor-api</artifactId>
<version>2.0.1</version> <version>1.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jakarta.enterprise</groupId> <groupId>javax.ws.rs</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId> <artifactId>javax.ws.rs-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.glassfish.jersey.containers</groupId> <groupId>org.glassfish.jersey.containers</groupId>
@ -207,11 +217,11 @@
<groupId>org.glassfish.jersey.containers</groupId> <groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId> <artifactId>jersey-container-servlet-core</artifactId>
</dependency> </dependency>
<!-- <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
<dependency> <dependency>
<groupId>org.glassfish.jersey.inject</groupId> <groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId> <artifactId>jersey-hk2</artifactId>
<version>2.30.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.glassfish.jersey.core</groupId> <groupId>org.glassfish.jersey.core</groupId>
@ -225,16 +235,18 @@
<groupId>org.glassfish.jersey.ext.cdi</groupId> <groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-servlet</artifactId> <artifactId>jersey-cdi1x-servlet</artifactId>
</dependency> </dependency>
<!--
https://mvnrepository.com/artifact/org.jboss.weld.servlet/weld-servlet-core -->
<dependency> <dependency>
<groupId>org.jboss.weld.servlet</groupId> <groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet-core</artifactId> <artifactId>weld-servlet-core</artifactId>
<version>5.1.2.Final</version> <version>3.1.0.Final</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
<!-- <dependency>
https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common --> <groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>2.2.2.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
<dependency> <dependency>
<groupId>org.glassfish.jersey.core</groupId> <groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId> <artifactId>jersey-common</artifactId>
@ -247,15 +259,27 @@
<groupId>org.glassfish.jersey.media</groupId> <groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId> <artifactId>jersey-media-multipart</artifactId>
</dependency> </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> <dependency>
<groupId>org.reflections</groupId> <groupId>org.reflections</groupId>
<artifactId>reflections</artifactId> <artifactId>reflections</artifactId>
</dependency> <version>0.9.10</version>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
@ -265,7 +289,7 @@
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId> <artifactId>commons-compress</artifactId>
<version>1.22</version> <version>1.17</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.tukaani</groupId> <groupId>org.tukaani</groupId>
@ -289,30 +313,28 @@
<version>10.8.2.2</version> <version>10.8.2.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </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 --> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.7</version> <version>2.7</version>
</dependency> </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>com.vlkan.rfos</groupId> <groupId>com.vlkan.rfos</groupId>
<artifactId>rotating-fos</artifactId> <artifactId>rotating-fos</artifactId>
<version>0.9.2</version> <version>0.9.2</version>
</dependency> </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.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>2.0.7</version>
</dependency>
<!-- enunciate deps --> <!-- enunciate deps -->
<dependency> <dependency>
<groupId>com.webcohesion.enunciate</groupId> <groupId>com.webcohesion.enunciate</groupId>
@ -326,66 +348,78 @@
<version>${enunciate.version}</version> <version>${enunciate.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- Storage dependencies --> <!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency> <dependency>
<groupId>org.gcube.contentmanagement</groupId> <groupId>org.mockito</groupId>
<artifactId>storage-manager-core</artifactId> <artifactId>mockito-all</artifactId>
<version>[4.0.0-SNAPSHOT,5.0.0-SNAPSHOT)</version> <version>1.9.5</version>
</dependency> <scope>test</scope>
<dependency> </dependency>
<groupId>org.gcube.contentmanagement</groupId> <dependency>
<artifactId>storage-manager-wrapper</artifactId> <groupId>org.slf4j</groupId>
<version>[4.0.0-SNAPSHOT,5.0.0-SNAPSHOT)</version> <artifactId>jul-to-slf4j</artifactId>
</dependency> <version>${slf4j.version}</version>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3 --> </dependency>
<dependency> <dependency>
<groupId>com.amazonaws</groupId> <groupId>org.jboss.weld.se</groupId>
<artifactId>aws-java-sdk-s3</artifactId> <artifactId>weld-se</artifactId>
<version>1.12.763</version> <version>2.2.10.Final</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> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13.2</version> <version>4.11</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>logback-classic</artifactId> <artifactId>jersey-test-framework-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName> <finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<plugin> <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> <groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId> <artifactId>aspectj-maven-plugin</artifactId>
<version>${aspectj-plugin.version}</version> <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.14.0</version>
<configuration> <configuration>
<complianceLevel>17</complianceLevel> <complianceLevel>1.8</complianceLevel>
<source>17</source> <source>1.8</source>
<target>17</target> <target>1.8</target>
<aspectLibraries> <aspectLibraries>
<aspectLibrary> <aspectLibrary>
<groupId>org.gcube.common</groupId> <groupId>org.gcube.common</groupId>
@ -393,18 +427,10 @@
</aspectLibrary> </aspectLibrary>
</aspectLibraries> </aspectLibraries>
</configuration> </configuration>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.21.1</version>
</dependency>
</dependencies>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>compile</goal> <!-- use this goal to weave <goal>compile</goal>
all your main classes -->
</goals> </goals>
</execution> </execution>
</executions> </executions>
@ -423,6 +449,29 @@
<failOnMissingWebXml>false</failOnMissingWebXml> <failOnMissingWebXml>false</failOnMissingWebXml>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-profile</id>
<goals>
<goal>copy-resources</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<outputDirectory>${webappDirectory}</outputDirectory>
<resources>
<resource>
<directory>${distroDirectory}</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Enunciate Maven plugin --> <!-- Enunciate Maven plugin -->
<plugin> <plugin>
<groupId>com.webcohesion.enunciate</groupId> <groupId>com.webcohesion.enunciate</groupId>
@ -438,11 +487,11 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Copy Enunciate Documentation from your-application/docs to <!-- Copy Enunciate Documentation from your-application/docs to your-application.war -->
your-application.war -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId> <artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions> <executions>
<execution> <execution>
<id>copy-enunciate-docs</id> <id>copy-enunciate-docs</id>
@ -454,10 +503,8 @@
<outputDirectory>target</outputDirectory> <outputDirectory>target</outputDirectory>
<resources> <resources>
<resource> <resource>
<targetPath> <targetPath>${project.build.directory}/${project.artifactId}/api-docs</targetPath>
${project.build.directory}/${project.artifactId}/api-docs</targetPath> <directory>${project.build.directory}/api-docs</directory>
<directory>
${project.build.directory}/api-docs</directory>
<filtering>true</filtering> <filtering>true</filtering>
</resource> </resource>
</resources> </resources>
@ -467,35 +514,4 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </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> </project>

View File

@ -2,8 +2,8 @@ package org.gcube.data.access.storagehub;
import java.util.List; import java.util.List;
import jakarta.inject.Inject; import javax.inject.Inject;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
@ -74,20 +74,20 @@ public class AuthorizationChecker {
//SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING); //SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
//if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return; //if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return;
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER //CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
List<ACL> acls = aclManager.getByItem(item, session); List<ACL> acls = aclManager.get(item, session);
UserManager userManager = ((JackrabbitSession) session).getUserManager(); UserManager userManager = ((JackrabbitSession) session).getUserManager();
Authorizable userAuthorizable = userManager.getAuthorizable(userToCheck); Authorizable userAuthorizable = userManager.getAuthorizable(userToCheck);
for (ACL entry: acls) { for (ACL entry: acls) {
log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPrincipal()); log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPricipal());
Authorizable authorizable = userManager.getAuthorizable(entry.getPrincipal()); Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
if (authorizable==null) { if (authorizable==null) {
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPrincipal()); log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPricipal());
continue; continue;
} }
try { try {
if (!authorizable.isGroup() && entry.getPrincipal().equals(userToCheck)) return; if (!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) return;
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return; if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
}catch (Throwable e) { }catch (Throwable e) {
log.warn("someting went wrong checking authorizations",e); log.warn("someting went wrong checking authorizations",e);
@ -103,13 +103,13 @@ public class AuthorizationChecker {
private boolean hasParentPublicFolder(Session session, Item item) { private boolean hasParentPublicFolder(Session session, Item item) {
if(item==null || item.getParentPath()==null) return false; 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.getParentPath().replaceAll("/Home/[^/]*/"+Constants.WORKSPACE_ROOT_FOLDER_NAME,"").isEmpty() || item.getParentPath().replaceAll(Constants.SHARED_FOLDER_PATH, "").isEmpty()) {
if (item instanceof FolderItem folder) if (item instanceof FolderItem)
return folder.isPublicItem(); return ((FolderItem) item).isPublicItem();
else return false; else return false;
} else { } else {
if (item instanceof FolderItem folder) if (item instanceof FolderItem)
try { try {
return (folder.isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(folder.getParentId(), session, Excludes.ALL))); return ((FolderItem) item).isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
}catch (Throwable e) { }catch (Throwable e) {
log.warn("error checking public parents",e); log.warn("error checking public parents",e);
return false; return false;
@ -136,13 +136,13 @@ public class AuthorizationChecker {
if (item.isShared()) { if (item.isShared()) {
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER //CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
List<ACL> acls = aclManager.getByItem(item, session); List<ACL> acls = aclManager.get(item, session);
UserManager userManager = ((JackrabbitSession) session).getUserManager(); UserManager userManager = ((JackrabbitSession) session).getUserManager();
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck); Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
//put it in a different method //put it in a different method
for (ACL entry: acls) { for (ACL entry: acls) {
Authorizable authorizable = userManager.getAuthorizable(entry.getPrincipal()); Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
if ((!authorizable.isGroup() && entry.getPrincipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){ if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
for (AccessType privilege : entry.getAccessTypes()){ for (AccessType privilege : entry.getAccessTypes()){
if (isNewItem && privilege!=AccessType.READ_ONLY) if (isNewItem && privilege!=AccessType.READ_ONLY)
return; 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==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+": it's not a valid StorageHub node");
if (item.isShared()) { if (item.isShared()) {
List<ACL> acls = aclManager.getByItem(item, session); List<ACL> acls = aclManager.get(item, session);
for (ACL entry: acls) { for (ACL entry: acls) {
if (entry.getPrincipal().equals(userToCheck)) { if (entry.getPricipal().equals(userToCheck)) {
for (AccessType privilege : entry.getAccessTypes()){ for (AccessType privilege : entry.getAccessTypes()){
if (privilege==AccessType.ADMINISTRATOR) if (privilege==AccessType.ADMINISTRATOR)
return; return;

View File

@ -3,8 +3,6 @@ package org.gcube.data.access.storagehub;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.jcr.SimpleCredentials;
public class Constants { public class Constants {
public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders"; public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
@ -19,8 +17,6 @@ public class Constants {
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe"; 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 SHARED_FOLDER_PATH = "/Share";
public static final String WORKSPACE_ROOT_FOLDER_NAME ="Workspace"; public static final String WORKSPACE_ROOT_FOLDER_NAME ="Workspace";
@ -29,6 +25,10 @@ public class Constants {
public static final String QUERY_LANGUAGE ="JCR-SQL2"; 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 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); public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
@ -36,9 +36,4 @@ 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> 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 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());
} }

View File

@ -0,0 +1,141 @@
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;
}
}
}

View File

@ -1,6 +1,10 @@
package org.gcube.data.access.storagehub; package org.gcube.data.access.storagehub;
import org.gcube.data.access.storagehub.repository.StoragehubRepository; import javax.inject.Inject;
import javax.ws.rs.ext.Provider;
import org.apache.jackrabbit.api.JackrabbitRepository;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.glassfish.jersey.server.monitoring.ApplicationEvent; import org.glassfish.jersey.server.monitoring.ApplicationEvent;
import org.glassfish.jersey.server.monitoring.ApplicationEventListener; import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
import org.glassfish.jersey.server.monitoring.RequestEvent; import org.glassfish.jersey.server.monitoring.RequestEvent;
@ -8,21 +12,21 @@ import org.glassfish.jersey.server.monitoring.RequestEventListener;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.ws.rs.ext.Provider;
@Provider @Provider
public class MyApplicationListener implements ApplicationEventListener { public class MyApplicationListener implements ApplicationEventListener {
private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class); private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
StoragehubRepository repository = StoragehubRepository.repository; @Inject
RepositoryInitializer repository;
@Override @Override
public void onEvent(ApplicationEvent event) { public void onEvent(ApplicationEvent event) {
log.info("StorageHub - event called");
switch (event.getType()) { switch (event.getType()) {
case DESTROY_FINISHED: case DESTROY_FINISHED:
log.info("Destroying application storageHub"); log.info("Destroying application storageHub");
repository.shutdown(); ((JackrabbitRepository) repository.getRepository()).shutdown();
log.info("Jackrabbit repository stopped"); log.info("Jackrabbit repository stopped");
default: default:
break; break;

View File

@ -1,6 +1,6 @@
package org.gcube.data.access.storagehub; package org.gcube.data.access.storagehub;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
@ -46,14 +46,9 @@ public class PathUtil {
} }
public Path getSharedWithMePath(String login){ public Path getSharedWithMePath(String login){
return Paths.append(getHome(login),Constants.SHARED_WITH_ME_PARENT_NAME); return Paths.append(getWorkspacePath(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 { public Path getVREsPath(String login, Session session) throws RepositoryException {
Path home = getHome(login); Path home = getHome(login);
Node node = session.getNode(home.toPath()); Node node = session.getNode(home.toPath());

View File

@ -0,0 +1,35 @@
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();
}
}

View File

@ -4,8 +4,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import jakarta.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View File

@ -0,0 +1,36 @@
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);
}
}

View File

@ -3,19 +3,18 @@ package org.gcube.data.access.storagehub;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import jakarta.ws.rs.Path; import javax.ws.rs.Path;
import jakarta.ws.rs.core.Application; import javax.ws.rs.core.Application;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter; import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
import org.gcube.data.access.storagehub.services.ACLManager; import org.gcube.data.access.storagehub.services.ACLManager;
import org.gcube.data.access.storagehub.services.DocsGenerator; import org.gcube.data.access.storagehub.services.DocManager;
import org.gcube.data.access.storagehub.services.GroupManager; import org.gcube.data.access.storagehub.services.GroupManager;
import org.gcube.data.access.storagehub.services.Impersonable; import org.gcube.data.access.storagehub.services.Impersonable;
import org.gcube.data.access.storagehub.services.ItemSharing; import org.gcube.data.access.storagehub.services.ItemSharing;
import org.gcube.data.access.storagehub.services.ItemsCreator; import org.gcube.data.access.storagehub.services.ItemsCreator;
import org.gcube.data.access.storagehub.services.ItemsManager; import org.gcube.data.access.storagehub.services.ItemsManager;
import org.gcube.data.access.storagehub.services.MessageManager; import org.gcube.data.access.storagehub.services.MessageManager;
import org.gcube.data.access.storagehub.services.StorageManager;
import org.gcube.data.access.storagehub.services.UserManager; import org.gcube.data.access.storagehub.services.UserManager;
import org.gcube.data.access.storagehub.services.WorkspaceManager; import org.gcube.data.access.storagehub.services.WorkspaceManager;
import org.gcube.data.access.storagehub.services.admin.ScriptManager; import org.gcube.data.access.storagehub.services.admin.ScriptManager;
@ -38,11 +37,10 @@ public class StorageHub extends Application {
classes.add(GroupManager.class); classes.add(GroupManager.class);
classes.add(ScriptManager.class); classes.add(ScriptManager.class);
classes.add(MessageManager.class); classes.add(MessageManager.class);
classes.add(StorageManager.class);
classes.add(DocsGenerator.class);
classes.add(MultiPartFeature.class); classes.add(MultiPartFeature.class);
classes.add(SerializableErrorEntityTextWriter.class); classes.add(SerializableErrorEntityTextWriter.class);
classes.add(MyApplicationListener.class); classes.add(MyApplicationListener.class);
classes.add(DocManager.class);
return classes; return classes;
} }

View File

@ -1,97 +0,0 @@
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);
}
}
}

View File

@ -0,0 +1,41 @@
package org.gcube.data.access.storagehub;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.gcube.smartgears.ApplicationManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StorageHubAppllicationManager implements ApplicationManager {
private static Logger logger = LoggerFactory.getLogger(StorageHubAppllicationManager.class);
private boolean alreadyShutDown = false;
public static RepositoryInitializer repository;
@Override
public synchronized void onInit() {
logger.info("jackrabbit initialization started");
try {
repository = new RepositoryInitializerImpl();
} catch (Exception e) {
logger.error("ERROR INITIALIZING REPOSITORY",e);
}
repository.getRepository();
}
@Override
public synchronized void onShutdown() {
if (!alreadyShutDown)
try {
logger.info("jackrabbit is shutting down");
repository.shutdown();
alreadyShutDown= true;
} catch (Exception e) {
logger.warn("the database was not shutdown properly",e);
}
}
}

View File

@ -6,7 +6,6 @@ import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -31,24 +30,18 @@ import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException; import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; 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.ExternalLink;
import org.gcube.common.storagehub.model.items.FolderItem; import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem; import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.items.GenericFileItem;
import org.gcube.common.storagehub.model.items.Item; import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder; import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.types.ItemAction; import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty; import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.types.FolderInfoType;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter; import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; 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.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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -79,22 +72,8 @@ public class Utils {
return digest; return digest;
} }
public static long getItemCount(Node parent, boolean showHidden, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{ public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, itemTypePredicate).size(); return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).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;
} }
@ -122,7 +101,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, ItemTypePredicate itemTypePredicate, 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, Class<? extends RootItem> nodeTypeToInclude, String nameParam) throws RepositoryException, BackendGenericError{
String xpath = String.format("/jcr:root%s//element(*,nthl:workspaceItem)[jcr:like(fn:lower-case(@jcr:title), '%s')]",ISO9075.encodePath(parent.getPath()), nameParam.toLowerCase()); String 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()); //String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
@ -146,26 +125,26 @@ public class Utils {
}; };
return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, itemTypePredicate); return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, nodeTypeToInclude);
} }
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
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, nodeTypeToInclude);
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, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{ public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
logger.trace("getting children of node {}", parent.getIdentifier()); logger.trace("getting children of node {}", parent.getIdentifier());
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent); NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent);
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start)); logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, itemTypePredicate); return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, nodeTypeToInclude);
} }
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, ItemTypePredicate itemTypePredicate) 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, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
List<T> returnList = new ArrayList<T>(); List<T> returnList = new ArrayList<T>();
logger.trace("nodeType is {}",nodeTypeToInclude);
int count =0; int count =0;
logger.trace("selected range is {}", range); logger.trace("selected range is {}", range);
Node2ItemConverter node2Item= new Node2ItemConverter(); Node2ItemConverter node2Item= new Node2ItemConverter();
@ -192,7 +171,7 @@ public class Utils {
logger.trace("[SEARCH] current node not excluded {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName()); logger.trace("[SEARCH] current node not excluded {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) { if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
T item = node2Item.getFilteredItem(current, excludes, itemTypePredicate); T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
if (item==null || (item.isTrashed() && excludeTrashed)) continue; if (item==null || (item.isTrashed() && excludeTrashed)) continue;
returnList.add(item); returnList.add(item);
} }
@ -234,18 +213,17 @@ public class Utils {
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{ public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
String escapedName = Text.escapeIllegalJcrChars(name);
try { try {
destination.getNode(escapedName); destination.getNode(name);
}catch(PathNotFoundException pnf) { }catch(PathNotFoundException pnf) {
return escapedName; return Text.escapeIllegalJcrChars(name);
} catch (Exception e) { } catch (Exception e) {
throw new BackendGenericError(e); throw new BackendGenericError(e);
} }
try { try {
String filename = FilenameUtils.getBaseName(escapedName); String filename = FilenameUtils.getBaseName(name);
String ext = FilenameUtils.getExtension(escapedName); String ext = FilenameUtils.getExtension(name);
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext); String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
@ -262,23 +240,20 @@ public class Utils {
String newName = ext.isEmpty()? String.format("%s(%d)", filename,maxval+1) : String.format("%s(%d).%s", filename,maxval+1, ext) ; String newName = ext.isEmpty()? String.format("%s(%d)", filename,maxval+1) : String.format("%s(%d).%s", filename,maxval+1, ext) ;
return newName; return Text.escapeIllegalJcrChars(newName);
} catch (Exception e) { } catch (Exception e) {
throw new BackendGenericError(e); throw new BackendGenericError(e);
} }
} }
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler, boolean isInternalWSFolder) throws StorageHubException { public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler) throws StorageHubException {
logger.debug("creating folder {} in {}", params.getName(), params.getParentId()); logger.debug("creating folder {} in {}", params.getName(), params.getParentId());
Node destinationNode; Node destinationNode;
FolderItem destinationItem;
try { try {
destinationNode = params.getSession().getNodeByIdentifier(params.getParentId()); destinationNode = params.getSession().getNodeByIdentifier(params.getParentId());
destinationItem = (FolderItem) new Node2ItemConverter().getItem(destinationNode, Excludes.ALL);
}catch (RepositoryException e) { }catch (RepositoryException e) {
logger.error("id not found",e);
throw new IdNotFoundException(params.getParentId()); throw new IdNotFoundException(params.getParentId());
} }
String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName()); String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName());
@ -288,20 +263,6 @@ public class Utils {
item.setName(uniqueName); item.setName(uniqueName);
item.setTitle(uniqueName); item.setTitle(uniqueName);
item.setDescription(params.getDescription()); 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(); //TODO: item.setExternalStorage();
//item.setCreationTime(now); //item.setCreationTime(now);
@ -351,7 +312,6 @@ public class Utils {
Node newNode = new Item2NodeConverter().getNode(destinationNode, item); Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
if (accountingHandler!=null) { if (accountingHandler!=null) {
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false); accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false); accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
@ -386,11 +346,5 @@ public class Utils {
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name()); 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());
}
} }

View File

@ -4,17 +4,21 @@ import java.util.Calendar;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.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.items.nodes.accounting.AccountingEntryType;
import org.gcube.common.storagehub.model.types.NodeProperty; import org.gcube.common.storagehub.model.types.NodeProperty;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.inject.Singleton;
@Singleton @Singleton
public class AccountingHandler { public class AccountingHandler {
@ -28,12 +32,11 @@ public class AccountingHandler {
private static final String OLD_ITEM_NAME = "hl:oldItemName"; private static final String OLD_ITEM_NAME = "hl:oldItemName";
private static final String NEW_ITEM_NAME = "hl:newItemName"; 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); private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
public void createReadObj(String title, String version, Session ses, Node node, String login, boolean saveHistory ) { public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
try { try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){ if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -46,8 +49,20 @@ public class AccountingHandler {
accountingNode.setProperty(USER, login); accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance()); accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title); accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, version!=null?version:BASE_VERSION);
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);
}
if (saveHistory) ses.save(); if (saveHistory) ses.save();
} catch (RepositoryException e) { } catch (RepositoryException e) {
logger.warn("error trying to retrieve accountign node",e); logger.warn("error trying to retrieve accountign node",e);
@ -66,8 +81,6 @@ public class AccountingHandler {
accountingNode.setProperty(USER, login); accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance()); accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title); accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, BASE_VERSION);
if (saveHistory) ses.save(); if (saveHistory) ses.save();
} catch (RepositoryException e) { } catch (RepositoryException e) {
@ -75,7 +88,7 @@ public class AccountingHandler {
} }
} }
public void createFileUpdated(String title, String version, Session ses, Node node, String login, boolean saveHistory ) { public void createFileUpdated(String title, Session ses, Node node, String login, boolean saveHistory ) {
try { try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){ if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -88,30 +101,21 @@ public class AccountingHandler {
accountingNode.setProperty(USER, login); accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance()); accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title); 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 { try {
VersionManager vManager = ses.getWorkspace().getVersionManager();
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){ VersionHistory history = vManager.getVersionHistory(node.getNode("jcr:content").getPath());
node.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString()); VersionIterator versions = history.getAllVersions();
Version version= null;
while (versions.hasNext()) {
version = versions.nextVersion();
} }
if (version!=null)
accountingNode.setProperty(VERSION_ACCOUNTING, version.getName());
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString()); }catch(UnsupportedRepositoryOperationException uropex) {
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.DELETE.getNodeTypeDefinition()); logger.warn("version cannot be retrieved", uropex);
}
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, version);
if (saveHistory) ses.save(); if (saveHistory) ses.save();

View File

@ -0,0 +1,16 @@
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);
}
}

View File

@ -1,5 +0,0 @@
package org.gcube.data.access.storagehub.handlers;
public class ACLHandler {
}

View File

@ -40,12 +40,11 @@ public class ClassHandler {
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class); Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
for (Class<?> clazz: classesAnnotated ){ for (Class<?> clazz: classesAnnotated ){
if (RootItem.class.isAssignableFrom(clazz) && clazz.isAnnotationPresent(RootNode.class)) { if (RootItem.class.isAssignableFrom(clazz)) {
String[] values = clazz.getAnnotation(RootNode.class).value(); String value = clazz.getAnnotation(RootNode.class).value();
log.debug("loading class {} with values {} ", clazz, values ); log.debug("loading class {} with value {} ", clazz, value );
for (String value: values)
classMap.put(value, (Class<? extends RootItem>) clazz); classMap.put(value, (Class<? extends RootItem>) clazz);
typeMap.put((Class<? extends RootItem>) clazz, values[0]); typeMap.put((Class<? extends RootItem>) clazz, value);
} }
} }
} }

View File

@ -8,24 +8,21 @@ import java.util.List;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
import jakarta.inject.Inject; import javax.inject.Inject;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.version.Version;
import org.gcube.common.storagehub.model.Excludes; 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.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem; import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem; import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item; import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.storages.StorageBackend; import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler; import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -34,12 +31,9 @@ public class CompressHandler {
private Logger logger = LoggerFactory.getLogger(CompressHandler.class); private Logger logger = LoggerFactory.getLogger(CompressHandler.class);
@Inject @Inject
StorageBackendHandler storageBackendHandler; FolderPluginHandler pluginHandler;
@Inject public Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
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>(); Deque<Item> queue = new LinkedList<Item>();
Node currentNode = session.getNodeByIdentifier(directory.getId()); Node currentNode = session.getNodeByIdentifier(directory.getId());
queue.push(directory); queue.push(directory);
@ -48,17 +42,11 @@ public class CompressHandler {
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){ for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
if (excludes.contains(item.getId())) continue; if (excludes.contains(item.getId())) continue;
if (item instanceof FolderItem) if (item instanceof FolderItem)
tempQueue.addAll(getAllNodesForZip((FolderItem) item, login, session, accountingHandler, excludes)); tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, login, accountingHandler, excludes));
else if (item instanceof AbstractFileItem fileItem){ else if (item instanceof AbstractFileItem){
logger.trace("adding file {}",item.getPath()); logger.trace("adding file {}",item.getPath());
String versionName = null; AbstractFileItem fileItem = (AbstractFileItem) item;
try { accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
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); queue.addLast(item);
} }
} }
@ -67,9 +55,9 @@ public class CompressHandler {
} }
public void zipNode(ZipOutputStream zos, Deque<Item> queue, Path originalPath) throws Exception{ public void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath) throws Exception{
logger.trace("originalPath is {}",originalPath.toPath()); logger.trace("originalPath is {}",originalPath.toPath());
Path actualPath = Paths.getPath(""); org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
Item item = queue.pop(); Item item = queue.pop();
if (item instanceof FolderItem) { if (item instanceof FolderItem) {
@ -83,14 +71,11 @@ public class CompressHandler {
}finally { }finally {
zos.closeEntry(); zos.closeEntry();
} }
} else if (item instanceof AbstractFileItem fileItem){ } else if (item instanceof AbstractFileItem){
try { try {
AbstractFileItem fileItem = (AbstractFileItem)item;
StorageBackendFactory sbf = storageBackendHandler.get(fileItem.getContent().getPayloadBackend()); FolderManager manager = pluginHandler.getFolderManager(fileItem);
InputStream streamToWrite = manager.getStorageBackend().download(fileItem.getContent());
StorageBackend sb = sbf.create(fileItem.getContent().getPayloadBackend());
InputStream streamToWrite = sb.download(fileItem.getContent());
if (streamToWrite == null){ if (streamToWrite == null){
logger.warn("discarding item {} ",item.getName()); logger.warn("discarding item {} ",item.getName());
continue; continue;

View File

@ -0,0 +1,18 @@
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;
}
}

View File

@ -1,150 +0,0 @@
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);
}
});
}
}

View File

@ -1,212 +0,0 @@
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();
}
}

View File

@ -0,0 +1,82 @@
package org.gcube.data.access.storagehub.handlers;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.services.GroupManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class GroupHandler {
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
@Inject
PathUtil pathUtil;
public boolean removeUserFromGroup(String groupId, String userId, JackrabbitSession session) throws StorageHubException, RepositoryException {
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User user = (User)usrManager.getAuthorizable(userId);
if (!group.isMember(user))
throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId);
//delete folder on user
String folderName = group.getPrincipal().getName();
Node folder = getFolderNodeRelatedToGroup(session, folderName);
NodeIterator ni = folder.getSharedSet();
while (ni.hasNext()) {
Node node = ni.nextNode();
if (node.getPath().startsWith(pathUtil.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
node.removeShare();
break;
}
}
return group.removeMember(user);
}
public Node getFolderNodeRelatedToGroup(JackrabbitSession session, String name) throws ItemNotFoundException, RepositoryException {
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
Node vreFolder = null;
try {
vreFolder = sharedRootNode.getNode(name);
}catch (PathNotFoundException e) {
log.debug("is an old HL VRE");
}
if (vreFolder==null) {
NodeIterator nodes = sharedRootNode.getNodes();
while (nodes.hasNext()) {
Node node = nodes.nextNode();
if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
vreFolder= node;
break;
}
}
}
if (vreFolder==null) throw new ItemNotFoundException("vre folder not found for group "+name);
return vreFolder;
}
}

View File

@ -1,143 +0,0 @@
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; }
}
}

View File

@ -9,8 +9,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.inject.Inject; import javax.inject.Inject;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.ItemNotFoundException; import javax.jcr.ItemNotFoundException;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
@ -18,7 +18,7 @@ import javax.jcr.Session;
import javax.jcr.lock.LockException; import javax.jcr.lock.LockException;
import javax.jcr.version.Version; import javax.jcr.version.Version;
import org.gcube.common.security.AuthorizedTasks; import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.storagehub.model.Excludes; import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths; import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
@ -30,8 +30,7 @@ import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item; import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.TrashItem; import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.items.nodes.Content; import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.storages.StorageBackend; import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
import org.gcube.common.storagehub.model.types.ItemAction; import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
@ -39,7 +38,7 @@ import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter; import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler; import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.types.ContentPair; import org.gcube.data.access.storagehub.types.ContentPair;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -69,8 +68,10 @@ public class TrashHandler {
@Inject @Inject
PathUtil pathUtil; PathUtil pathUtil;
@Inject FolderPluginHandler managerHandler;
@Inject @Inject
StorageBackendHandler storageBackendHandler; FolderPluginHandler folderHandler;
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{ public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
log.debug("defnitively removing nodes with ids {}",itemsToDelete); log.debug("defnitively removing nodes with ids {}",itemsToDelete);
@ -108,13 +109,8 @@ public class TrashHandler {
} }
try { 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()); List<Version> versions = versionHandler.getContentVersionHistory((Node)item.getRelatedNode());
@ -122,7 +118,7 @@ public class TrashHandler {
try { try {
Content content = node2Item.getContentFromVersion(version); Content content = node2Item.getContentFromVersion(version);
if (content!= null && content.getStorageId()!=null) if (content!= null && content.getStorageId()!=null)
contentSet.add(new ContentPair(content, sb)); contentSet.add(new ContentPair(content, manager.getStorageBackend()));
else log.warn("invalid version {}",version.getName()); else log.warn("invalid version {}",version.getName());
}catch (Throwable t) { }catch (Throwable t) {
log.warn("error retrieving version content for {}",version.getName(),t); log.warn("error retrieving version content for {}",version.getName(),t);
@ -163,7 +159,7 @@ public class TrashHandler {
public void run() { public void run() {
for (ContentPair cp: contentToDelete ) { for (ContentPair cp: contentToDelete ) {
try { try {
cp.getStorageBackend().delete(cp.getContent().getStorageId()); cp.getStorageBackend().onDelete(cp.getContent());
log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName()); log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName());
}catch(Throwable t) { }catch(Throwable t) {
log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t); log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t);
@ -216,7 +212,8 @@ public class TrashHandler {
if (item instanceof FolderItem) { if (item instanceof FolderItem) {
trashItem.setFolder(true); trashItem.setFolder(true);
}else if (item instanceof AbstractFileItem file) { }else if (item instanceof AbstractFileItem ) {
AbstractFileItem file = (AbstractFileItem) item;
if (file.getContent()!=null) { if (file.getContent()!=null) {
trashItem.setMimeType(file.getContent().getMimeType()); trashItem.setMimeType(file.getContent().getMimeType());
trashItem.setLenght(file.getContent().getSize()); trashItem.setLenght(file.getContent().getSize());
@ -232,10 +229,10 @@ public class TrashHandler {
log.debug("calling jcr move"); log.debug("calling jcr move");
ses.getWorkspace().move(nodeToDelete.getPath(), Paths.append(Paths.getPath(newTrashItemNode.getPath()),nodeToDelete.getName()).toPath()); ses.getWorkspace().move(nodeToDelete.getPath(), Paths.append(Paths.getPath(newTrashItemNode.getPath()),nodeToDelete.getName()).toPath());
String mimetype = null; String mimetype = null;
if (item instanceof AbstractFileItem file) { if (item instanceof AbstractFileItem) {
if (file.getContent()!=null) if (((AbstractFileItem)item).getContent()!=null)
mimetype = file.getContent().getMimeType(); mimetype = ((AbstractFileItem) item).getContent().getMimeType();
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", file.getId()); else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
} }
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true); accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true);
}catch(Throwable t) { }catch(Throwable t) {

View File

@ -5,8 +5,8 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import jakarta.inject.Inject; import javax.inject.Inject;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.NodeIterator; import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
@ -163,7 +163,7 @@ public class UnshareHandler {
unsharedNodeIdentifier = unsharedNode.getIdentifier(); unsharedNodeIdentifier = unsharedNode.getIdentifier();
log.info("[UNSHARE] unshared node id {}",unsharedNodeIdentifier); log.info("[UNSHARE] unshared node id {}",unsharedNodeIdentifier);
ses.save(); ses.save();
} //TODO: else shoud I removove all the fiel content ? }
log.debug("all the users have been removed, the folder is totally unshared"); log.debug("all the users have been removed, the folder is totally unshared");

View File

@ -4,9 +4,8 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.version.Version; import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory; import javax.jcr.version.VersionHistory;
@ -54,13 +53,6 @@ public class VersionHandler {
} }
} }
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) { public List<Version> getContentVersionHistory(Node node) {
try { try {
Session session = node.getSession(); Session session = node.getSession();
@ -76,17 +68,10 @@ public class VersionHandler {
logger.debug("version name {} with nodeType {}",version.getName(),version.getPrimaryNodeType().getName()); logger.debug("version name {} with nodeType {}",version.getName(),version.getPrimaryNodeType().getName());
} }
return versions; return versions;
}catch(Throwable e ) { }catch(Exception e ) {
logger.warn("cannot get version history content node",e); logger.warn("cannot get version history content node",e);
return Collections.emptyList(); 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);
}
} }

View File

@ -7,15 +7,7 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
public interface ContentHandler { public interface ContentHandler {
boolean requiresInputStream(); void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception;
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(); Content getContent();

View File

@ -4,7 +4,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Set; import java.util.Set;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler; import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
import org.reflections.Reflections; import org.reflections.Reflections;
@ -42,9 +42,9 @@ public class ContentHandlerFactory {
public ContentHandler create(String mimetype) throws Exception{ public ContentHandler create(String mimetype) throws Exception{
Class<? extends ContentHandler> handlerClass = handlerMap.get(mimetype); Class<? extends ContentHandler> handlerClass = handlerMap.get(mimetype);
if (handlerClass!=null) if (handlerClass!=null)
return handlerClass.getDeclaredConstructor().newInstance(); return handlerClass.newInstance();
else else
return defaultHandler.getDeclaredConstructor().newInstance(); return defaultHandler.newInstance();
} }
} }

View File

@ -1,5 +1,6 @@
package org.gcube.data.access.storagehub.handlers.content; package org.gcube.data.access.storagehub.handlers.content;
import java.io.InputStream;
import java.util.Calendar; import java.util.Calendar;
import org.gcube.common.storagehub.model.items.GenericFileItem; import org.gcube.common.storagehub.model.items.GenericFileItem;
@ -10,17 +11,12 @@ public class GenericFileHandler implements ContentHandler{
Content content = new Content(); Content content = new Content();
@Override
public boolean requiresInputStream() {
return false;
}
@Override @Override
public void initiliseSpecificContent(String filename, String mimeType) throws Exception { public void initiliseSpecificContent(InputStream is, String filename, String mimeType) throws Exception {
content.setMimeType(mimeType); content.setMimeType(mimeType);
} }
@Override @Override
public Content getContent() { public Content getContent() {
return content; return content;

View File

@ -28,15 +28,8 @@ public class ImageHandler implements ContentHandler{
private static final Logger logger = LoggerFactory.getLogger(ImageHandler.class); private static final Logger logger = LoggerFactory.getLogger(ImageHandler.class);
@Override @Override
public boolean requiresInputStream() { public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
return true;
}
@Override
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception {
if (size<5242880) {
Image image = javax.imageio.ImageIO.read(is); Image image = javax.imageio.ImageIO.read(is);
int width = image.getWidth(null); int width = image.getWidth(null);
@ -45,7 +38,6 @@ public class ImageHandler implements ContentHandler{
content.setWidth(Long.valueOf(width)); content.setWidth(Long.valueOf(width));
content.setHeight(Long.valueOf(height)); content.setHeight(Long.valueOf(height));
try { try {
int[] dimension = getThumbnailDimension(width, height); int[] dimension = getThumbnailDimension(width, height);
@ -58,8 +50,6 @@ public class ImageHandler implements ContentHandler{
}catch(Throwable t) { }catch(Throwable t) {
logger.warn("thumbnail for file {} cannot be created ", fileName,t); logger.warn("thumbnail for file {} cannot be created ", fileName,t);
} }
}
content.setMimeType(mimeType); content.setMimeType(mimeType);
} }

View File

@ -17,12 +17,7 @@ public class OfficeAppHandler implements ContentHandler{
Content content = new Content(); Content content = new Content();
@Override @Override
public boolean requiresInputStream() { public void initiliseSpecificContent(InputStream is, String filename, String mimeType) throws Exception {
return true;
}
@Override
public void initiliseSpecificContent(InputStream is, String filename, String mimeType, long size) throws Exception {
//detecting the file type //detecting the file type
BodyContentHandler handler = new BodyContentHandler(); BodyContentHandler handler = new BodyContentHandler();
Metadata metadata = new Metadata(); Metadata metadata = new Metadata();

View File

@ -27,12 +27,7 @@ public class PdfHandler implements ContentHandler {
private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class); private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class);
@Override @Override
public boolean requiresInputStream() { public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
return true;
}
@Override
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception {
try { try {
PdfReader reader = new PdfReader(is); PdfReader reader = new PdfReader(is);
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages())); content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));

View File

@ -10,14 +10,13 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.ItemExistsException; import javax.jcr.ItemExistsException;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.PathNotFoundException; import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Value; import javax.jcr.Value;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.util.Text; import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.value.BinaryValue; import org.apache.jackrabbit.value.BinaryValue;
import org.apache.jackrabbit.value.BooleanValue; import org.apache.jackrabbit.value.BooleanValue;
@ -50,27 +49,11 @@ public class Item2NodeConverter {
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class); private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
public <T extends RootItem> Node getNode(Node parentNode, T item, String uuid){ public <T extends RootItem> Node getNode(Node parentNode, T item){
try { try {
String primaryType= ClassHandler.instance().getNodeType(item.getClass()); String primaryType= ClassHandler.instance().getNodeType(item.getClass());
Node newNode = null; Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
if (uuid==null) //newNode.setPrimaryType(primaryType);
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())){ for (Field field : retrieveAllFields(item.getClass())){
if (field.isAnnotationPresent(Attribute.class)){ if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class); Attribute attribute = field.getAnnotation(Attribute.class);
@ -99,11 +82,17 @@ public class Item2NodeConverter {
logger.debug("error setting value",e); logger.debug("error setting value",e);
} }
} }
} }
return newNode;
} catch (RepositoryException e) {
logger.error("error writing repository",e);
throw new RuntimeException(e);
}
} }
@SuppressWarnings("unchecked")
private void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{ private void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class); AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
@ -126,7 +115,6 @@ public class Item2NodeConverter {
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
Class returnType = field.getType(); Class returnType = field.getType();
Values values = getObjectValue(returnType, field.get(object)); Values values = getObjectValue(returnType, field.get(object));
if (values == null) continue;
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues()); if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue()); else newNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) { } catch (Exception e ) {
@ -157,28 +145,13 @@ public class Item2NodeConverter {
iterateItemNodeAttributeFields(obj,newNode, field.getName()+(i++)); 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" }) @SuppressWarnings({ "rawtypes" })
public static Values getObjectValue(Class returnType, Object value) throws Exception{ 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.equals(String.class)) return new Values(new StringValue((String) value));
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString())); if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
if (returnType.equals(Calendar.class)) return new Values(new DateValue((Calendar) value)); if (returnType.equals(Calendar.class)) return new Values(new DateValue((Calendar) value));
@ -216,8 +189,7 @@ public class Item2NodeConverter {
public <F extends AbstractFileItem> void replaceContent(Node node, F item, ItemAction action){ public <F extends AbstractFileItem> void replaceContent(Node node, F item, ItemAction action){
try { try {
String primaryType = item.getClass().getAnnotation(RootNode.class).value()[0]; node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value());
node.setPrimaryType(primaryType);
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME); Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
contentNode.setPrimaryType(item.getContent().getClass().getAnnotation(AttributeRootNode.class).value()); contentNode.setPrimaryType(item.getContent().getClass().getAnnotation(AttributeRootNode.class).value());
@ -225,9 +197,22 @@ public class Item2NodeConverter {
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), item.getLastModifiedBy()); node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), item.getLastModifiedBy());
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name()); 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());
replaceContentNodeInternal(contentNode, item.getContent().getClass(),item.getContent()); } catch (Exception e ) {
logger.debug("error setting value for attribute "+attribute.value(),e);
}
}
}
} catch (RepositoryException e) { } catch (RepositoryException e) {
logger.error("error writing repository",e); logger.error("error writing repository",e);
@ -236,40 +221,6 @@ 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 { public void updateHidden(Node node, Boolean hidden,String login) throws RepositoryException {
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED); Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
node.setProperty(NodeProperty.HIDDEN.toString(), hidden); node.setProperty(NodeProperty.HIDDEN.toString(), hidden);
@ -280,7 +231,6 @@ public class Item2NodeConverter {
node.setProperty(NodeProperty.DESCRIPTION.toString(), description); node.setProperty(NodeProperty.DESCRIPTION.toString(), description);
} }
@SuppressWarnings("unchecked")
public void updateOwnerOnSubTree(Node node, String owner) throws RepositoryException, BackendGenericError { public void updateOwnerOnSubTree(Node node, String owner) throws RepositoryException, BackendGenericError {
Class<? extends Item> classToHandle = (Class<? extends Item>)ClassHandler.instance().get(node.getPrimaryNodeType().getName()); Class<? extends Item> classToHandle = (Class<? extends Item>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return; if (classToHandle==null) return;

View File

@ -7,14 +7,17 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; 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 jakarta.inject.Inject; import javax.inject.Inject;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.lock.LockException; import javax.jcr.lock.LockException;
import javax.jcr.version.Version;
import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream; import org.apache.commons.compress.archivers.ArchiveInputStream;
@ -23,6 +26,7 @@ import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.Detector; import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream; import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata; 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.Excludes;
import org.gcube.common.storagehub.model.NodeConstants; import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.Paths; import org.gcube.common.storagehub.model.Paths;
@ -34,11 +38,12 @@ import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem; import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem; import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.MetaInfo; import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.storages.StorageBackend; import org.gcube.common.storagehub.model.storages.StorageBackend;
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
import org.gcube.common.storagehub.model.types.ItemAction; import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.AuthorizationChecker; 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.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler; import org.gcube.data.access.storagehub.handlers.VersionHandler;
@ -50,14 +55,14 @@ 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.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters; 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.items.builders.URLCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler; import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@Singleton @Singleton
public class ItemHandler { public class ItemHandler {
@Inject @Inject
AccountingHandler accountingHandler; AccountingHandler accountingHandler;
@ -71,29 +76,23 @@ public class ItemHandler {
VersionHandler versionHandler; VersionHandler versionHandler;
@Inject @Inject
StorageBackendHandler storageBackendHandler; FolderPluginHandler pluginHandler;
// private static ExecutorService executor = Executors.newFixedThreadPool(100); private static ExecutorService executor = Executors.newFixedThreadPool(100);
@Inject @Inject Node2ItemConverter node2Item;
Node2ItemConverter node2Item; @Inject Item2NodeConverter item2Node;
@Inject
Item2NodeConverter item2Node;
private static Logger log = LoggerFactory.getLogger(ItemHandler.class); private static Logger log = LoggerFactory.getLogger(ItemHandler.class);
// TODO: accounting
// provider URI host public <T extends CreateParameters> String create(T parameters) throws Exception{
// 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(); Session ses = parameters.getSession();
Node destination; Node destination;
try { try {
destination = ses.getNodeByIdentifier(parameters.getParentId()); destination = ses.getNodeByIdentifier(parameters.getParentId());
} catch (RepositoryException inf) { }catch(RepositoryException inf) {
throw new IdNotFoundException(parameters.getParentId()); throw new IdNotFoundException(parameters.getParentId());
} }
@ -102,16 +101,29 @@ public class ItemHandler {
authChecker.checkWriteAuthorizationControl(ses, parameters.getUser(), destination.getIdentifier(), true); authChecker.checkWriteAuthorizationControl(ses, parameters.getUser(), destination.getIdentifier(), true);
try { try {
Node newNode = switch (parameters.getMangedType()) { Node newNode = null;
case FILE -> create((FileCreationParameters) parameters, destination); switch (parameters.getMangedType()) {
case FOLDER -> create((FolderCreationParameters) parameters, destination); case FILE:
case ARCHIVE -> create((ArchiveStructureCreationParameter) parameters, destination); newNode = create((FileCreationParameters)parameters, destination);
case URL -> create((URLCreationParameters) parameters, destination); break;
case GCUBEITEM -> create((GCubeItemCreationParameters) parameters, destination); case FOLDER:
default -> throw new InvalidCallParameters("Item not supported"); newNode = create((FolderCreationParameters)parameters, destination);
}; break;
log.debug("item with id {} correctly created", newNode.getIdentifier()); case ARCHIVE:
newNode = create((ArchiveStructureCreationParameter)parameters, destination);
break;
case URL:
newNode = create((URLCreationParameters) parameters, destination);
break;
case GCUBEITEM:
newNode = create((GCubeItemCreationParameters) parameters, destination);
break;
default:
throw new InvalidCallParameters("Item not supported");
}
log.debug("item with id {} correctly created",newNode.getIdentifier());
return newNode.getIdentifier(); return newNode.getIdentifier();
} finally { } finally {
if (parameters.getSession().getWorkspace().getLockManager().isLocked(destination.getPath())) if (parameters.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
@ -120,199 +132,168 @@ 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); Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createFolderInternally(params, accountingHandler, false); Node newNode = Utils.createFolderInternally(params, accountingHandler);
params.getSession().save(); params.getSession().save();
return newNode; return newNode;
} }
private Node create(FileCreationParameters params, Node destination) throws Exception { private Node create(FileCreationParameters params, Node destination) throws Exception{
Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(), Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(), params.getDescription(), params.getUser(), true);
params.getDescription(), params.getFileDetails(), params.getUser(), true);
params.getSession().save(); params.getSession().save();
versionHandler.checkinContentNode(newNode); 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); Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createURLInternally(params.getSession(), destination, params.getName(), params.getUrl(), Node newNode = Utils.createURLInternally(params.getSession(), destination, params.getName(), params.getUrl(), params.getDescription(), params.getUser(), accountingHandler);
params.getDescription(), params.getUser(), accountingHandler);
params.getSession().save(); params.getSession().save();
return newNode; 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); Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
FolderCreationParameters folderParameters = FolderCreationParameters.builder() FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(params.getParentFolderName()).author(params.getUser()).on(destination.getIdentifier()).with(params.getSession()).build();
.name(params.getParentFolderName()).author(params.getUser()).on(destination.getIdentifier()) Node parentDirectoryNode = Utils.createFolderInternally(folderParameters, accountingHandler);
.with(params.getSession()).build();
Node parentDirectoryNode = Utils.createFolderInternally(folderParameters, accountingHandler, false);
params.getSession().save(); params.getSession().save();
try { try {
if (params.getSession().getWorkspace().getLockManager().isLocked(destination.getPath())) if (params.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
params.getSession().getWorkspace().getLockManager().unlock(destination.getPath()); params.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
} catch (Throwable t) { } catch (Throwable t){
log.warn("error unlocking {}", destination.getPath(), t); log.warn("error unlocking {}", destination.getPath(), t);
} }
Set<Node> fileNodes = new HashSet<>(); Set<Node> fileNodes = new HashSet<>();
HashMap<String, Node> directoryNodeMap = new HashMap<>(); HashMap<String, Node> directoryNodeMap = new HashMap<>();
ArchiveInputStream input = new ArchiveStreamFactory() try (ArchiveInputStream input = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(params.getStream())); .createArchiveInputStream(new BufferedInputStream(params.getStream(), 1024*64))){
ArchiveEntry entry; ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) { while ((entry = input.getNextEntry()) != null) {
String entirePath = entry.getName(); String entirePath = entry.getName();
log.debug("reading new entry ------> {} ", entirePath);
if (entry.isDirectory()) { if (entry.isDirectory()) {
log.debug("creating directory with entire path {} ", entirePath); log.debug("creating directory with entire path {} ", entirePath);
createPath(entirePath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser()); createPath(entirePath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
} else continue;
} else {
try { try {
String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2"); String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2");
String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1"); String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1");
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
parentPath);
Node fileNode = null; Node fileNode = null;
long fileSize = entry.getSize(); if (parentPath.isEmpty())
FormDataContentDisposition fileDetail = FormDataContentDisposition.name(name).size(fileSize) fileNode = createFileItemInternally(params.getSession(), parentDirectoryNode, input, name, "", params.getUser(), false);
.build(); else {
//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 (parentPath.isEmpty()) {
fileNode = createFileItemInternally(params.getSession(), parentDirectoryNode, notClosableIS, name, "",
fileDetail, params.getUser(), false);
} else {
Node parentNode = directoryNodeMap.get(parentPath); Node parentNode = directoryNodeMap.get(parentPath);
if (parentNode == null) if (parentNode ==null)
parentNode = createPath(parentPath, directoryNodeMap, parentDirectoryNode, parentNode = createPath(parentPath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
params.getSession(), params.getUser());
fileNode = createFileItemInternally(params.getSession(), parentNode, notClosableIS, name, "", fileNode = createFileItemInternally(params.getSession(), parentNode, input, name, "", params.getUser(), false);
fileDetail, params.getUser(), false);
} }
fileNodes.add(fileNode); fileNodes.add(fileNode);
} catch (Throwable e) { }catch(Exception e) {
log.warn("error getting file {}", entry.getName(), e); log.warn("error getting file {}",entry.getName(),e);
}
} }
} }
log.info("archive {} uploading finished ", params.getParentFolderName()); }
params.getSession().save(); params.getSession().save();
for (Node node : fileNodes) for (Node node : fileNodes)
versionHandler.checkinContentNode(node); versionHandler.checkinContentNode(node);
return parentDirectoryNode; 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[] parentPathSplit = parentPath.split("/");
String name = parentPathSplit[parentPathSplit.length - 1]; String name = parentPathSplit[parentPathSplit.length-1];
StringBuilder relParentPath = new StringBuilder(); 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("/"); relParentPath.append(parentPathSplit[i]).append("/");
if (relParentPath.toString().isEmpty()) { if (relParentPath.toString().isEmpty()) {
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user) FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(rootNode.getIdentifier()).with(ses).build();
.on(rootNode.getIdentifier()).with(ses).build(); Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler, false); directoryNodeMap.put(name+"/", createdNode);
directoryNodeMap.put(name + "/", createdNode);
return createdNode; return createdNode;
} else { }else {
Node relParentNode = directoryNodeMap.get(relParentPath.toString()); Node relParentNode = directoryNodeMap.get(relParentPath.toString());
if (relParentNode == null) { if (relParentNode==null) {
relParentNode = createPath(relParentPath.toString(), directoryNodeMap, rootNode, ses, user); relParentNode = createPath(relParentPath.toString(), directoryNodeMap, rootNode, ses, user);
} }
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user) FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(relParentNode.getIdentifier()).with(ses).build();
.on(relParentNode.getIdentifier()).with(ses).build(); Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler, false);
directoryNodeMap.put(relParentPath.append(name).append("/").toString(), createdNode); directoryNodeMap.put(relParentPath.append(name).append("/").toString(), createdNode);
return 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); Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createGcubeItemInternally(params.getSession(), destination, params.getItem().getName(), Node newNode = Utils.createGcubeItemInternally(params.getSession(), destination, params.getItem().getName(), params.getItem().getDescription(), params.getUser(), params.getItem(), accountingHandler);
params.getItem().getDescription(), params.getUser(), params.getItem(), accountingHandler);
params.getSession().save(); params.getSession().save();
return newNode; return newNode;
} }
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, StorageHubException{
String description, FormDataContentDisposition fileDetails, String login, boolean withLock)
throws RepositoryException, StorageHubException {
log.trace("UPLOAD: starting preparing file");
Node newNode; Node newNode;
FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL); FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL);
FolderManager folderManager = pluginHandler.getFolderManager(destinationItem);
StorageBackendFactory sbf = storageBackendHandler.get(destinationItem.getBackend()); StorageBackend storageBackend = folderManager.getStorageBackend();
StorageBackend sb = sbf.create(destinationItem.getBackend());
String relativePath = destinationNode.getPath(); String relativePath = destinationNode.getPath();
if (destinationItem.isExternalManaged())
relativePath = relativePath.replace(folderManager.getRootFolder().getPath(), "");
String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath(); String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath();
log.info("new node path is {}", newNodePath);
if (ses.nodeExists(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); newNode = ses.getNode(newNodePath);
authChecker.checkWriteAuthorizationControl(ses, login, newNode.getIdentifier(), false); authChecker.checkWriteAuthorizationControl(ses, login, newNode.getIdentifier(), false);
AbstractFileItem item = fillItemWithContent(stream, sb, name, description, fileDetails, relativePath, AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath,login);
login);
if (withLock) { if (withLock) {
try { try {
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0, login); ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
} catch (LockException le) { }catch (LockException le) {
throw new ItemLockedException(le); throw new ItemLockedException(le);
} }
} }
try { try {
versionHandler.checkoutContentNode(newNode); versionHandler.checkoutContentNode(newNode);
log.trace("replacing content of class {}", item.getContent().getClass()); log.trace("replacing content of class {}",item.getContent().getClass());
item2Node.replaceContent(newNode, item, ItemAction.UPDATED); item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
String versionName = null; accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, login, false);
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(); ses.save();
} catch (Throwable t) { }finally {
log.error("error saving item", t); if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
} 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); authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true);
AbstractFileItem item = fillItemWithContent(stream, sb, name, description, fileDetails, relativePath, AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath, login);
login);
if (withLock) { if (withLock) {
try { try {
log.debug("trying to acquire lock"); log.debug("trying to acquire lock");
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10); Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
} catch (LockException le) { }catch (LockException le) {
throw new ItemLockedException(le); throw new ItemLockedException(le);
} }
} }
@ -320,95 +301,98 @@ public class ItemHandler {
newNode = item2Node.getNode(destinationNode, item); newNode = item2Node.getNode(destinationNode, item);
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode, login, false); accountingHandler.createEntryCreate(item.getTitle(), ses, newNode, login, false);
ses.save(); ses.save();
} catch (Throwable t) { }finally {
log.error("error saving item", t); if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
throw new BackendGenericError(t);
} finally {
if (withLock)
ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
} }
versionHandler.makeVersionableContent(newNode); versionHandler.makeVersionableContent(newNode);
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, login, destinationNode, false);
ses, login, destinationNode, false);
} }
// TODO: Utils.updateParentSize()
return newNode; return newNode;
} }
private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name,
String description, FormDataContentDisposition fileDetails, String relPath, String login)
throws BackendGenericError { private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name, String description, String relPath, String login) throws BackendGenericError{
log.trace("UPLOAD: filling content"); ContentHandler handler = getContentHandler(stream, storageBackend, name, relPath, login);
ContentHandler handler = getContentHandler(stream, storageBackend, name, fileDetails, relPath, login); AbstractFileItem item =handler.buildItem(name, description, login);
return handler.buildItem(name, description, login); return item ;
} }
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError {
FormDataContentDisposition fileDetails, String relPath, String login) throws BackendGenericError {
log.trace("UPLOAD: handling content");
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(); long start = System.currentTimeMillis();
log.trace("UPLOAD: writing the stream - start"); log.debug("TIMING: reading the mimetype - start");
try { try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
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; org.apache.tika.mime.MediaType mediaType = null;
TikaConfig config = TikaConfig.getDefaultConfig(); TikaConfig config = TikaConfig.getDefaultConfig();
Detector detector = config.getDetector(); Detector detector = config.getDetector();
TikaInputStream tikastream = TikaInputStream.get(is1); TikaInputStream stream = TikaInputStream.get(is1);
Metadata metadata = new Metadata(); Metadata metadata = new Metadata();
mediaType = detector.detect(tikastream, metadata); metadata.add(Metadata.RESOURCE_NAME_KEY, name);
mimeType = mediaType.getBaseType().toString(); mediaType = detector.detect(stream, metadata);
String mimeType = mediaType.getBaseType().toString();
handler = contenthandlerFactory.create(mimeType); handler = contenthandlerFactory.create(mimeType);
log.debug("UPLOAD: reading the mimetype {} - finished in {}", mimeType, is1.reset();
System.currentTimeMillis() - start); handler.initiliseSpecificContent(is1, name, mimeType);
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
} catch (Throwable e) { } catch (Throwable e) {
log.error("error retrieving mimeType", e); log.error("error retrieving mimeType",e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return handler;
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);
};
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
@Override
public MetaInfo call() throws Exception {
try(InputStream is1 = mos.get()){
MetaInfo info = storageBackend.upload(is1, relPath, name);
return info;
}catch (Throwable e) {
log.error("error writing content",e );
throw e;
}
}
};
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
long start = System.currentTimeMillis();
log.debug("TIMING: writing the stream - start");
try {
mos.startWriting();
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
ContentHandler handler = detectorF.get();
MetaInfo info = uploaderF.get();
handler.getContent().setData(NodeConstants.CONTENT_NAME); handler.getContent().setData(NodeConstants.CONTENT_NAME);
handler.getContent().setStorageId(info.getStorageId()); handler.getContent().setStorageId(info.getStorageId());
handler.getContent().setSize(info.getSize()); 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; return handler;
} catch (Throwable e) { }catch (Exception e) {
log.error("error writing file", e);
throw new BackendGenericError(e); throw new BackendGenericError(e);
} }

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.NodeIterator; import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException; import javax.jcr.PathNotFoundException;
@ -41,15 +42,12 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.messages.Message; import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.handlers.ClassHandler; import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
import org.reflections.Configuration; import org.reflections.Configuration;
import org.reflections.Reflections; import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder; import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.inject.Singleton;
@Singleton @Singleton
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public class Node2ItemConverter { public class Node2ItemConverter {
@ -59,11 +57,11 @@ public class Node2ItemConverter {
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>(); private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{ public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName()); Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return null; if (classToHandle==null) return null;
if (itemTypePredicate != null && !itemTypePredicate.test(classToHandle)) return null; if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
else return retrieveItem(node, excludes, classToHandle); else return retrieveItem(node, excludes, classToHandle);
} }
@ -106,7 +104,7 @@ public class Node2ItemConverter {
private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{ private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{
T item; T item;
try { try {
item = classToHandle.getDeclaredConstructor().newInstance(); item = classToHandle.newInstance();
}catch (Exception e) { }catch (Exception e) {
throw new BackendGenericError(e); throw new BackendGenericError(e);
} }
@ -172,7 +170,17 @@ public class Node2ItemConverter {
private <T> void setGenericFields(Node node, Class<T> classToHandle,List<String> excludes, T instance){ private <T> void setGenericFields(Node node, Class<T> classToHandle,List<String> excludes, T instance){
for (Field field : retrieveAllFields(classToHandle)){ for (Field field : retrieveAllFields(classToHandle)){
if (field.isAnnotationPresent(Attribute.class)){ if (field.isAnnotationPresent(Attribute.class)){
setAttributeFieldCheckingDefault(field, instance, node); 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());
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){ } else if (field.isAnnotationPresent(NodeAttribute.class)){
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value(); String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
//for now it excludes only first level node //for now it excludes only first level node
@ -187,7 +195,7 @@ public class Node2ItemConverter {
}catch(PathNotFoundException e){ }catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} node",fieldNodeName); logger.trace("the current node dosn't contain {} node",fieldNodeName);
} catch (Exception e ) { } catch (Exception e ) {
logger.trace("error setting value",e); logger.debug("error setting value",e);
} }
@ -196,41 +204,21 @@ public class Node2ItemConverter {
} }
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{ private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
T obj = clazz.getDeclaredConstructor().newInstance(); T obj = clazz.newInstance();
for (Field field : retrieveAllFields(clazz)){ for (Field field : retrieveAllFields(clazz)){
if (field.isAnnotationPresent(Attribute.class)){ if (field.isAnnotationPresent(Attribute.class)){
setAttributeFieldCheckingDefault(field, obj, node); Attribute attribute = field.getAnnotation(Attribute.class);
} else if (field.isAnnotationPresent(MapAttribute.class)){
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
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); field.setAccessible(true);
try{ try{
Node fieldNode = node.getNode(fieldNodeName); Class returnType = field.getType();
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName); field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
field.set(obj, iterateNodeAttributeFields(field.getType(), fieldNode));
}catch(PathNotFoundException e){ }catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} node",fieldNodeName); logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) { } catch (Exception e ) {
logger.trace("error setting value",e); logger.debug("error setting value {}",e.getMessage());
} }
} else if (field.isAnnotationPresent(MapAttribute.class)){
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
}
}
return obj;
}
private <T> void setMapAttribute(Field field, T instance, Node node) throws Exception{
field.setAccessible(true); field.setAccessible(true);
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith(); String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
Map<String, Object> mapToset = new HashMap<String, Object>(); Map<String, Object> mapToset = new HashMap<String, Object>();
@ -244,18 +232,15 @@ public class Node2ItemConverter {
mapToset.put(prop.getName(), getPropertyValue(prop)); mapToset.put(prop.getName(), getPropertyValue(prop));
}catch(PathNotFoundException e){ }catch(PathNotFoundException e){
logger.trace("the property {} is not mapped",prop.getName()); logger.warn("the property {} is not mapped",prop.getName());
} catch (Exception e ) { } catch (Exception e ) {
logger.trace("error setting value {}",e); logger.debug("error setting value {}",e.getMessage());
} }
} }
} }
field.set(instance, mapToset); field.set(obj, mapToset);
} } 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());
@SuppressWarnings("unchecked")
private <T> void setListNode(Field field, T instance, Node node) throws Exception{
field.setAccessible(true); field.setAccessible(true);
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith(); String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith(); String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
@ -266,6 +251,7 @@ public class Node2ItemConverter {
if (!typeToSubtypeMap.containsKey(listType)) { if (!typeToSubtypeMap.containsKey(listType)) {
Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName()); Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName());
Reflections reflections = new Reflections(config); Reflections reflections = new Reflections(config);
Set<Class> subTypes = reflections.getSubTypesOf(listType); Set<Class> subTypes = reflections.getSubTypesOf(listType);
@ -283,7 +269,7 @@ public class Node2ItemConverter {
typeToSubtypeMap.put(listType, subTypesMap); typeToSubtypeMap.put(listType, subTypesMap);
} else { } else {
logger.debug("subtypes already found in cache"); logger.info("subtypes already found in cache");
subTypesMap = typeToSubtypeMap.get(listType); subTypesMap = typeToSubtypeMap.get(listType);
} }
@ -306,34 +292,11 @@ public class Node2ItemConverter {
toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode)); toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode));
else toSetList.add(iterateNodeAttributeFields(listType, currentNode)); else toSetList.add(iterateNodeAttributeFields(listType, currentNode));
} }
if (toSetList.size()!=0) field.set(instance, toSetList); if (toSetList.size()!=0) field.set(obj, 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());
} }
} }
return obj;
}
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
private Object getPropertyValue(Class returnType, Property prop) throws Exception{ private Object getPropertyValue(Class returnType, Property prop) throws Exception{

View File

@ -28,7 +28,7 @@ public class ArchiveStructureCreationParameter extends CreateParameters {
@Override @Override
protected boolean isValid() { protected boolean isValid() {
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream); return Objects.nonNull(parentFolderName) && Objects.nonNull(stream) && Objects.nonNull(fileDetails);
} }
@Override @Override

View File

@ -1,10 +1,7 @@
package org.gcube.data.access.storagehub.handlers.items.builders; package org.gcube.data.access.storagehub.handlers.items.builders;
import java.util.Map;
import java.util.Objects; 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; import org.gcube.common.storagehub.model.plugins.PluginParameters;
public class FolderCreationParameters extends CreateParameters { public class FolderCreationParameters extends CreateParameters {
@ -12,8 +9,8 @@ public class FolderCreationParameters extends CreateParameters {
private String name; private String name;
private String description=""; private String description="";
private boolean hidden = false; private boolean hidden = false;
private PayloadBackend backend; private String externalPluginName = null;
private PluginParameters externalPluginParameters = null;
protected FolderCreationParameters() {} protected FolderCreationParameters() {}
@ -29,8 +26,16 @@ public class FolderCreationParameters extends CreateParameters {
return hidden; return hidden;
} }
public PayloadBackend getBackend() { public boolean isExternal() {
return backend; return externalPluginName!=null;
}
public String getPluginName(String name) {
return this.externalPluginName;
}
public PluginParameters getPluginParameters() {
return externalPluginParameters;
} }
@Override @Override
@ -65,8 +70,8 @@ public class FolderCreationParameters extends CreateParameters {
return this; return this;
} }
public BackendCreationBuilder onRepository(String pluginName) { public ExternalFolderCreationBuilder onRepository(String pluginName) {
return new BackendCreationBuilder(pluginName, this); return new ExternalFolderCreationBuilder(pluginName, this);
} }
public FolderCreationBuilder hidden(boolean hidden) { public FolderCreationBuilder hidden(boolean hidden) {
@ -76,26 +81,19 @@ public class FolderCreationParameters extends CreateParameters {
} }
public static class BackendCreationBuilder { public static class ExternalFolderCreationBuilder {
FolderCreationBuilder cb; FolderCreationBuilder cb;
String plugin; protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
this.cb.parameters.externalPluginName = pluginName;
protected BackendCreationBuilder(String pluginName, FolderCreationBuilder cb) {
this.cb = cb;
this.plugin = pluginName;
} }
public FolderCreationBuilder withParameters(Map<String, Object> params){ public FolderCreationBuilder withParameters(PluginParameters params){
this.cb.parameters.backend = new PayloadBackend(plugin, new Metadata(params)); this.cb.parameters.externalPluginParameters = params;
return this.cb; return this.cb;
} }
public FolderCreationBuilder withoutParameters(){
this.cb.parameters.backend = new PayloadBackend(plugin, null);
return this.cb;
}
} }

View File

@ -0,0 +1,80 @@
package org.gcube.data.access.storagehub.handlers.plugins;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.items.ExternalFolder;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeFolderManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class FolderPluginHandler {
private static Logger log = LoggerFactory.getLogger(FolderPluginHandler.class);
@Inject
Node2ItemConverter node2Item;
private GcubeFolderManager defaultManager = new GcubeFolderManager();
public FolderManager getDefault() {
return defaultManager;
}
@Inject
Instance<FolderManagerConnector> connectors;
private Map<String, FolderManagerConnector> connectorsMap;
FolderPluginHandler(){
if (connectors !=null)
connectorsMap = connectors.stream().collect(Collectors.toMap(FolderManagerConnector::getName, e -> e ));
else {
log.info("connectors are null");
connectorsMap = Collections.emptyMap();
}
}
public FolderManagerConnector getConnector(String name) throws PluginNotFoundException {
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
return connectorsMap.get(name);
}
public FolderManager getFolderManager(Item item) throws PluginInitializationException, PluginNotFoundException, RepositoryException, BackendGenericError{
if (!item.isExternalManaged())
return defaultManager;
Session session = ((Node)item.getRelatedNode()).getSession();
Item parent = null;
do {
String parentId = item.getParentId();
Node node = session.getNodeByIdentifier(parentId);
parent = node2Item.getItem(node, Excludes.ALL);
if (parent !=null && parent instanceof ExternalFolder) {
ExternalFolder extParent = (ExternalFolder) parent;
String plugin = extParent.getManagedBy();
Map<String, Object> parameters = extParent.getConnectionParameters().getMap();
return getConnector(plugin).connect(extParent, parameters);
}
} while (parent!=null);
throw new BackendGenericError("selected external managed item doesn't have a parent external folder");
}
}

View File

@ -0,0 +1,28 @@
package org.gcube.data.access.storagehub.handlers.plugins;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class OperationMediator {
@Inject
FolderPluginHandler folderHandler;
/*
boolean onMove(Item source, Item destination, Session session) throws PluginInitializationException, PluginNotFoundException, BackendGenericError, RepositoryException{
FolderManager sourceFolderManager = folderHandler.getFolderManager(source);
FolderManager destinationFolderManager = folderHandler.getFolderManager(destination);
if (source instanceof FolderItem) {
destinationFolderManager.onCreatedFolder((FolderItem) source);
session.move(source.getPath(), destination.getPath());
sourceFolderManager.onDeletingFolder((FolderItem) source);
} else if (source instanceof AbstractFileItem){
}
}
*/
}

View File

@ -1,61 +0,0 @@
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();
}
}

View File

@ -1,51 +0,0 @@
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;
}
}

View File

@ -6,26 +6,32 @@ import java.util.Map;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.servlet.ServletContext;
import org.apache.jackrabbit.api.JackrabbitSession; import org.apache.jackrabbit.api.JackrabbitSession;
import org.gcube.common.security.ContextBean; import org.apache.jackrabbit.api.security.user.Group;
import org.gcube.common.security.ContextBean.Type; import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.Item; import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.repository.StoragehubRepository; import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
@Singleton @Singleton
public class VREManager { public class VREManager {
@ -33,7 +39,8 @@ public class VREManager {
private Map<String, VRE> vreMap = new HashMap<>(); private Map<String, VRE> vreMap = new HashMap<>();
StoragehubRepository repository = StoragehubRepository.repository; @Inject
RepositoryInitializer repository;
@Inject @Inject
Node2ItemConverter node2Item; Node2ItemConverter node2Item;
@ -42,12 +49,19 @@ public class VREManager {
PathUtil pathUtil; PathUtil pathUtil;
@Inject @Inject
GroupManagerDelegate groupHandler; GroupHandler groupHandler;
ExecutorService executor = Executors.newFixedThreadPool(5); ExecutorService executor = Executors.newFixedThreadPool(5);
SimpleCredentials credentials;
private synchronized VRE getVRE(String completeName) { @Inject
public VREManager(ServletContext context) {
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
}
public synchronized VRE getVRE(String completeName) {
logger.trace("requesting VRE {}",completeName); logger.trace("requesting VRE {}",completeName);
if (vreMap.containsKey(completeName)) if (vreMap.containsKey(completeName))
return vreMap.get(completeName); return vreMap.get(completeName);
@ -60,26 +74,36 @@ public class VREManager {
logger.trace("inserting VRE {}",vreFolder.getTitle()); logger.trace("inserting VRE {}",vreFolder.getTitle());
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)"); if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
else { else {
VRE toReturn = new VRE(vreFolder, repository.getRepository(), Constants.JCR_CREDENTIALS, node2Item, executor); VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, node2Item, executor);
vreMap.put(vreFolder.getTitle(), toReturn); vreMap.put(vreFolder.getTitle(), toReturn);
return toReturn; return toReturn;
} }
} }
public String retrieveGroupNameFromContext(String context) throws StorageHubException{ public synchronized VRE getVreFolderItem(JackrabbitSession ses, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
ContextBean bean = new ContextBean(context); ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE"); if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-"); String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
return entireScopeName; return getVreFolderItemByGroupName(ses, entireScopeName, userId, excludes);
} }
public synchronized VRE getVreFolderItemByGroupName(JackrabbitSession ses, String groupName, List<String> excludes ) throws RepositoryException, StorageHubException{ public synchronized VRE getVreFolderItemByGroupName(JackrabbitSession ses, String groupName, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
UserManager um = ses.getUserManager();
Group groupAuth = um.getAuthorizable(groupName, Group.class);
User userAuth = um.getAuthorizable(userId, User.class);
if (groupAuth == null || userAuth == null || !groupAuth.isMember(userAuth))
throw new InvalidCallParameters("error getting VRE with user "+userId+" for group "+groupName);
VRE vre = this.getVRE(groupName); VRE vre = this.getVRE(groupName);
if (vre!=null) return vre; if (vre!=null) return vre;
else { else {
Node vreFolderNode = groupHandler.getFolderNodeRelatedToGroup(ses, groupName); Node vreFolderNode = groupHandler.getFolderNodeRelatedToGroup(ses, groupName);
Item vreFolder = node2Item.getItem(vreFolderNode, excludes); Item vreFolder = node2Item.getItem(vreFolderNode, excludes);
return this.putVRE(vreFolder); return this.putVRE(vreFolder);
} }

View File

@ -1,41 +0,0 @@
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();
}
}
}

View File

@ -1,35 +0,0 @@
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();
}
}

View File

@ -1,28 +0,0 @@
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;
}
}

View File

@ -1,29 +0,0 @@
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;
}
}

View File

@ -1,9 +0,0 @@
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>> {
}

View File

@ -1,6 +1,6 @@
package org.gcube.data.access.storagehub.query.sql2.evaluators; package org.gcube.data.access.storagehub.query.sql2.evaluators;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;

View File

@ -1,8 +1,8 @@
package org.gcube.data.access.storagehub.query.sql2.evaluators; package org.gcube.data.access.storagehub.query.sql2.evaluators;
import jakarta.enterprise.inject.Instance; import javax.enterprise.inject.Instance;
import jakarta.inject.Inject; import javax.inject.Inject;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
@ -19,7 +19,6 @@ public class Evaluators {
@Inject @Inject
Instance<Evaluator<?>> evaluators; Instance<Evaluator<?>> evaluators;
@SuppressWarnings({ "rawtypes", "unchecked" })
public String evaluate(Expression<?> expression) { public String evaluate(Expression<?> expression) {
for (Evaluator eval: evaluators) { for (Evaluator eval: evaluators) {
if (eval.getType().equals(expression.getClass())) if (eval.getType().equals(expression.getClass()))

View File

@ -5,7 +5,7 @@ import java.text.SimpleDateFormat;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.date.Before; import org.gcube.common.storagehub.model.expressions.date.Before;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.logical.And; import org.gcube.common.storagehub.model.expressions.logical.And;

View File

@ -1,6 +1,6 @@
package org.gcube.data.access.storagehub.query.sql2.evaluators.logical; package org.gcube.data.access.storagehub.query.sql2.evaluators.logical;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant; import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.logical.Or; import org.gcube.common.storagehub.model.expressions.logical.Or;

View File

@ -1,6 +1,6 @@
package org.gcube.data.access.storagehub.query.sql2.evaluators.text; package org.gcube.data.access.storagehub.query.sql2.evaluators.text;
import jakarta.inject.Singleton; import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression; import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.text.Contains; import org.gcube.common.storagehub.model.expressions.text.Contains;

View File

@ -1,108 +0,0 @@
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");
}
}

View File

@ -1,14 +0,0 @@
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();
}

View File

@ -2,10 +2,24 @@ package org.gcube.data.access.storagehub.services;
import java.util.Collections; import java.util.Collections;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.NodeIterator; import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.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.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes; import org.gcube.common.storagehub.model.Excludes;
@ -21,13 +35,11 @@ import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.VreFolder; import org.gcube.common.storagehub.model.items.VreFolder;
import org.gcube.common.storagehub.model.types.ACLList; import org.gcube.common.storagehub.model.types.ACLList;
import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager; import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.handlers.ACLHandler; import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler; import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; 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.data.access.storagehub.services.interfaces.ACLManagerInterface;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
@ -38,23 +50,8 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("items")
@ManagedBy(StorageHubApplicationManager.class) @ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
}) })
@ -62,12 +59,7 @@ public class ACLManager extends Impersonable {
private static final Logger log = LoggerFactory.getLogger(ACLManager.class); private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
ACLHandler aclHandler;
@RequestScoped @RequestScoped
@PathParam("id") @PathParam("id")
@ -98,13 +90,13 @@ public class ACLManager extends Impersonable {
@Path("{id}/acls") @Path("{id}/acls")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ACLList getACL() { public ACLList getACL() {
InnerMethodName.set("getACLById"); InnerMethodName.instance.set("getACLById");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL); Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
return new ACLList(aclManagerDelegate.getByItem(item, ses)); return new ACLList(aclManagerDelegate.get(item, ses));
}catch(RepositoryException re){ }catch(RepositoryException re){
log.error("jcr error getting acl", re); log.error("jcr error getting acl", re);
throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re)); throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re));
@ -135,13 +127,13 @@ public class ACLManager extends Impersonable {
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("{id}/acls") @Path("{id}/acls")
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) { public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
InnerMethodName.set("setACLById"); InnerMethodName.instance.set("setACLById");
Session ses = null; Session ses = null;
try { try {
if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified"); if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified");
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id); Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL); Item item = node2Item.getItem(node, Excludes.ALL);
@ -156,9 +148,12 @@ public class ACLManager extends Impersonable {
authChecker.checkAdministratorControl(ses, currentUser, folder); authChecker.checkAdministratorControl(ses, currentUser, folder);
if (item instanceof VreFolder || folder.isVreFolder()) if (folder.isVreFolder()) {
throw new InvalidCallParameters("acls in vreFolder cannot be updated with this method"); 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");
} else {
NodeIterator sharedSet = node.getSharedSet(); NodeIterator sharedSet = node.getSharedSet();
boolean found = false; boolean found = false;
while (sharedSet.hasNext() && !found) { while (sharedSet.hasNext() && !found) {
@ -168,9 +163,9 @@ public class ACLManager extends Impersonable {
} }
if (!found) if (!found)
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user); throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
}
aclManagerDelegate.update(user, folder, accessType, ses);
aclManagerDelegate.update(user, node, accessType, ses);
}catch(RepositoryException re){ }catch(RepositoryException re){
log.error("jcr error extracting archive", re); log.error("jcr error extracting archive", re);
@ -202,10 +197,10 @@ public class ACLManager extends Impersonable {
@Consumes(MediaType.TEXT_PLAIN) @Consumes(MediaType.TEXT_PLAIN)
@Path("{id}/acls/{user}") @Path("{id}/acls/{user}")
public void removeACL(@PathParam("user") String user) { public void removeACL(@PathParam("user") String user) {
InnerMethodName.set("removeACLById"); InnerMethodName.instance.set("removeACLById");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id); Node node = ses.getNodeByIdentifier(id);
@ -236,11 +231,11 @@ public class ACLManager extends Impersonable {
@GET @GET
@Path("{id}/acls/write") @Path("{id}/acls/write")
public Boolean canWriteInto() { public Boolean canWriteInto() {
InnerMethodName.set("canWriteIntoFolder"); InnerMethodName.instance.set("canWriteIntoFolder");
Session ses = null; Session ses = null;
Boolean canWrite = false; Boolean canWrite = false;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id); Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL); Item item = node2Item.getItem(node, Excludes.ALL);
if (!(item instanceof FolderItem)) if (!(item instanceof FolderItem))

View File

@ -4,25 +4,24 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import jakarta.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import jakarta.ws.rs.GET; import javax.ws.rs.GET;
import jakarta.ws.rs.Path; import javax.ws.rs.Path;
import jakarta.ws.rs.WebApplicationException; import javax.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context; import javax.ws.rs.core.Context;
import jakarta.ws.rs.core.Response.Status;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@Path("api-docs") @Path("api-docs")
public class DocsGenerator { public class DocManager {
private static Logger logger = LoggerFactory.getLogger(DocsGenerator.class); private static Logger logger = LoggerFactory.getLogger(DocManager.class);
@GET @GET
@Path("/{any: .*}") @Path("/{any: .*}")
public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException { public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException {
logger.info(DocsGenerator.class.getSimpleName() + " toDoc called"); logger.info(DocManager.class.getSimpleName() + " toDoc called");
String pathInfo = req.getPathInfo(); String pathInfo = req.getPathInfo();
logger.debug("pathInfo {}", pathInfo); logger.debug("pathInfo {}", pathInfo);
@ -42,8 +41,7 @@ public class DocsGenerator {
return new FileInputStream(new File(realPath)); return new FileInputStream(new File(realPath));
} catch (Exception e) { } catch (Exception e) {
logger.error("error getting the docs", e); throw new WebApplicationException("error getting docs",e);
throw new WebApplicationException(e,Status.SERVICE_UNAVAILABLE);
} }
} }
} }

View File

@ -3,25 +3,70 @@ 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.INFRASTRUCTURE_MANAGER_ROLE;
import static org.gcube.data.access.storagehub.Roles.VREMANAGER_ROLE; import static org.gcube.data.access.storagehub.Roles.VREMANAGER_ROLE;
import java.security.Principal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException; 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.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.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.acls.AccessType; import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; 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.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager; import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.repository.StoragehubRepository; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate; import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.vres.VRE;
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
@ -31,52 +76,65 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("groups")
@Singleton @ManagedBy(StorageHubAppllicationManager.class)
@ManagedBy(StorageHubApplicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
}) })
public class GroupManager { public class GroupManager {
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository; @Context ServletContext context;
@Inject @Inject
GroupManagerDelegate groupHandler; TrashHandler trashHandler;
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
VREManager vreManager;
@Inject
GroupHandler groupHandler;
@Inject
Node2ItemConverter node2Item;
@Inject @Inject
PathUtil pathUtil; PathUtil pathUtil;
@Inject
AuthorizationChecker authChecker;
@GET @GET
@Path("") @Path("")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public List<String> getGroups(){ public List<String> getGroups(){
InnerMethodName.set("getGroups"); InnerMethodName.instance.set("getGroups");
JackrabbitSession session = null; JackrabbitSession session = null;
List<String> groups= new ArrayList<>(); List<String> groups= new ArrayList<>();
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
groups = groupHandler.getGroups(session);
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());
}
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
@ -90,14 +148,32 @@ public class GroupManager {
@POST @POST
@Path("") @Path("")
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}) @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner, @FormDataParam("useDefaultStorage") @DefaultValue("true") boolean useDefaultStorage){ public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner){
InnerMethodName.instance.set("createGroup");
InnerMethodName.set("createGroup");
JackrabbitSession session = null; JackrabbitSession session = null;
String groupId = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groupHandler.createGroup(session, group, accessType, folderOwner, useDefaultStorage); 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.save(); session.save();
}catch(StorageHubException se) { }catch(StorageHubException se) {
log.error("error creating group {}", group, se); log.error("error creating group {}", group, se);
@ -109,19 +185,37 @@ public class GroupManager {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
return group;
return groupId;
} }
@DELETE @DELETE
@Path("{group}") @Path("{group}")
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}) @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteGroup(@PathParam("group") String group){ public String deleteGroup(@PathParam("group") String group){
InnerMethodName.set("deleteGroup"); InnerMethodName.instance.set("deleteGroup");
JackrabbitSession session = null; JackrabbitSession session = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groupHandler.deleteGroup(session, group); 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.save(); session.save();
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
@ -134,31 +228,50 @@ public class GroupManager {
} }
public boolean isInfraManager() { return SecretManagerProvider.get().getOwner().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); } public boolean isInfraManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); }
public boolean isVREManager() { return SecretManagerProvider.get().getOwner().getRoles().contains(VREMANAGER_ROLE); } public boolean isVREManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(VREMANAGER_ROLE); }
@PUT @PUT
@Path("{id}/admins") @Path("{id}/admins")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){ public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
InnerMethodName.set("addAdmin"); InnerMethodName.instance.set("addAdmin");
JackrabbitSession session = null; JackrabbitSession session = null;
try { try {
Objects.nonNull(groupId); Objects.nonNull(groupId);
Objects.nonNull(userId); Objects.nonNull(userId);
String currentUser = SecretManagerProvider.get().getOwner().getId(); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)) && Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser)) String currentUser = AuthorizationProvider.instance.get().getClient().getId();
throw new UserNotAuthorizedException();
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
groupHandler.addAdministratorToGroup(session, groupId, userId); org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)session).getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User authUser = (User)usrManager.getAuthorizable(userId);
if (group ==null)
throw new InvalidCallParameters("invalid group "+groupId);
if (authUser ==null)
throw new InvalidCallParameters("invalid user "+userId);
if (!group.isMember(authUser))
throw new InvalidCallParameters("user "+userId+" is not in the group "+groupId);
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
Principal principal = AccessControlUtils.getPrincipal(session, userId);
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(vreFolder.getPath(), acls);
session.save(); session.save();
}catch(StorageHubException she ){ }catch(StorageHubException she ){
@ -171,8 +284,6 @@ public class GroupManager {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
} }
@DELETE @DELETE
@ -180,23 +291,35 @@ public class GroupManager {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){ public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){
InnerMethodName.set("removeAdmin"); InnerMethodName.instance.set("removeAdmin");
JackrabbitSession session = null; JackrabbitSession session = null;
try { try {
Objects.nonNull(groupId); Objects.nonNull(groupId);
Objects.nonNull(userId); Objects.nonNull(userId);
String currentUser = SecretManagerProvider.get().getOwner().getId(); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)) && if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser)) authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
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(); session.save();
}catch(StorageHubException she ){ }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
@ -204,7 +327,7 @@ public class GroupManager {
}catch(Throwable re ){ }catch(Throwable re ){
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re));
} finally { }finally {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
@ -215,19 +338,37 @@ public class GroupManager {
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public List<String> getAdmins(@PathParam("groupId") String groupId){ public List<String> getAdmins(@PathParam("groupId") String groupId){
InnerMethodName.set("getAdmins"); InnerMethodName.instance.set("getAdmins");
List<String> users = new ArrayList<>(); String login = AuthorizationProvider.instance.get().getClient().getId();
JackrabbitSession session = null; JackrabbitSession session = null;
List<String> users = new ArrayList<>();
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
users = groupHandler.getGroupAdministators(session, groupId); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
VRE vreFolder = vreManager.getVreFolderItemByGroupName(session, groupId, login, Excludes.ALL);
AccessControlManager acm = session.getAccessControlManager();
//authChecker.checkAdministratorControl(session, (VreFolder)vreFolder.getVreFolder());
Node node = session.getNodeByIdentifier(vreFolder.getVreFolder().getId());
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, node.getPath());
for (AccessControlEntry acl: acls.getAccessControlEntries())
for (Privilege pr: acl.getPrivileges()) {
if (pr.getName().equals(AccessType.ADMINISTRATOR.getValue())){
users.add(acl.getPrincipal().getName());
}
}
}catch(StorageHubException she ){ }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable re ){ }catch(Exception re ){
log.error("jcr error getting admins", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting admins", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { }finally {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
@ -239,29 +380,41 @@ public class GroupManager {
@PUT @PUT
@Path("{id}/users") @Path("{id}/users")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}) @AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){ public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){
InnerMethodName.set("addUserToGroup"); InnerMethodName.instance.set("addUserToGroup");
JackrabbitSession session = null; JackrabbitSession session = null;
boolean success = false; boolean success = false;
try { try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId))) if (!isInfraManager() && !isValidGroupForContext(groupId))
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation"); throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
groupHandler.addUserToGroup(session, userId, groupId);
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);
success = true;
session.save(); session.save();
}catch(StorageHubException she ){ }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error adding user to group", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error adding user to group", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { }finally {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
@ -269,25 +422,43 @@ public class GroupManager {
return success; return success;
} }
private boolean internalAddUserToGroup(JackrabbitSession session, Group group, User user) throws RepositoryException, StorageHubException {
boolean success = group.addMember(user);
session.save();
String folderName = group.getPrincipal().getName();
Node folder = groupHandler.getFolderNodeRelatedToGroup(session, folderName);
String userPath = Paths.append(pathUtil.getVREsPath(user.getPrincipal().getName(), session), folderName).toPath();
log.debug("creating folder in user path {} from {}", userPath, folder.getPath() );
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
try {
session.getNode(userPath);
log.debug("the new folder exists ({}) ", userPath );
}catch (PathNotFoundException e) {
log.debug("the new folder doesn't exists ({}) ", userPath );
}
return success;
}
@DELETE @DELETE
@Path("{groupId}/users/{userId}") @Path("{groupId}/users/{userId}")
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}) @AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){ public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
InnerMethodName.set("removeUserFromGroup"); InnerMethodName.instance.set("removeUserFromGroup");
JackrabbitSession session = null; JackrabbitSession session = null;
boolean success = false; boolean success = false;
try { try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId))) if (!isValidGroupForContext(groupId) && !isInfraManager())
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation"); throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
success = groupHandler.removeUserFromGroup(session, groupId, userId); success = groupHandler.removeUserFromGroup(groupId, userId, session);
session.save(); session.save();
}catch(StorageHubException she ){ }catch(StorageHubException she ){
@ -307,25 +478,39 @@ public class GroupManager {
@GET @GET
@Path("{groupId}/users") @Path("{groupId}/users")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}) @AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){ public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
InnerMethodName.set("getUsersOfGroup");
InnerMethodName.instance.set("getUsersOfGroup");
JackrabbitSession session = null; JackrabbitSession session = null;
List<String> users = new ArrayList<>(); List<String> users = new ArrayList<>();
try { try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId))) if (!isValidGroupForContext(groupId) && !isInfraManager())
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation"); throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
users = groupHandler.getUsersBelongingToGroup(session, groupId);
}catch (StorageHubException e) { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
log.error("error getting users", e);
GXOutboundErrorResponse.throwException(e); 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()));
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error getting users", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting users", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { }finally {
if (session!=null) if (session!=null)
session.logout(); session.logout();
} }
@ -333,11 +518,51 @@ public class GroupManager {
return users; 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){ private boolean isValidGroupForContext(String group){
String currentContext = SecretManagerProvider.get().getContext(); String currentContext = ScopeProvider.instance.get();
String expectedGroupId= currentContext.replace("/", "-").substring(1); String expectedGroupId= currentContext.replace("/", "-").substring(1);
return group.equals(expectedGroupId); return group.equals(expectedGroupId);
} }

View File

@ -3,33 +3,36 @@ 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.INFRASTRUCTURE_MANAGER_ROLE;
import org.gcube.common.security.Owner; import javax.enterprise.context.RequestScoped;
import org.gcube.common.security.providers.SecretManagerProvider; import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.ClientInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; 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("") @Path("")
public abstract class Impersonable { public abstract class Impersonable {
Logger log = LoggerFactory.getLogger(Impersonable.class); Logger log = LoggerFactory.getLogger(Impersonable.class);
String currentUser = null; String currentUser;
@RequestScoped
@Inject @Inject
public void setCurrentUser(@Context final HttpServletRequest request) { public void setCurrentUser(@Context final HttpServletRequest request) {
String impersonate = request!=null ? request.getParameter("impersonate") : null ; String impersonate = request!=null ? request.getParameter("impersonate") : null ;
Owner owner = SecretManagerProvider.get().getOwner(); ClientInfo info = AuthorizationProvider.instance.get().getClient();
if(impersonate!=null && owner.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) { if(impersonate!=null && info.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
this.currentUser = impersonate; this.currentUser = impersonate;
} else } else
this.currentUser = owner.getId(); this.currentUser = info.getId();
log.info("called with login {} and impersonate {}",owner.getId(), impersonate); log.info("called with login {} and impersonate {}",info.getId(), impersonate);
} }
} }

View File

@ -4,12 +4,24 @@ import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.lock.LockException; import javax.jcr.lock.LockException;
import javax.jcr.security.AccessControlManager; import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege; 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.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils; import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
@ -31,12 +43,13 @@ import org.gcube.common.storagehub.model.types.PrimaryNodeType;
import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler; import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter; import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; 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.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam; import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -45,19 +58,6 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("items")
@ -68,7 +68,7 @@ public class ItemSharing extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemSharing.class); private static final Logger log = LoggerFactory.getLogger(ItemSharing.class);
private final StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject @Inject
AccountingHandler accountingHandler; AccountingHandler accountingHandler;
@ -98,7 +98,7 @@ public class ItemSharing extends Impersonable{
@POST @POST
@Path("{id}/share") @Path("{id}/share")
public String shareWithMap(@FormParam("mapUserPermission") String mapUserPermissionString, @FormParam("defaultAccessType") String defaultAccessTypeString){ public String shareWithMap(@FormParam("mapUserPermission") String mapUserPermissionString, @FormParam("defaultAccessType") String defaultAccessTypeString){
InnerMethodName.set("shareFolder"); InnerMethodName.instance.set("shareFolder");
HashMap<String,String> mapUserPermission; HashMap<String,String> mapUserPermission;
Session ses = null; Session ses = null;
@ -116,7 +116,7 @@ public class ItemSharing extends Impersonable{
throw new InvalidCallParameters("invalid default accessType"); throw new InvalidCallParameters("invalid default accessType");
} }
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL); Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
@ -200,12 +200,13 @@ public class ItemSharing extends Impersonable{
@PUT @PUT
@Path("{id}/share") @Path("{id}/share")
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@Deprecated
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){ public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
InnerMethodName.set("shareFolder"); InnerMethodName.instance.set("shareFolder");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL); Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
@ -216,8 +217,6 @@ public class ItemSharing extends Impersonable{
if (users==null || users.isEmpty()) if (users==null || users.isEmpty())
throw new InvalidCallParameters("users is empty"); 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); Node nodeToShare = ses.getNodeByIdentifier(id);
boolean alreadyShared = false; boolean alreadyShared = false;
@ -251,9 +250,8 @@ public class ItemSharing extends Impersonable{
for (String user : users) for (String user : users)
try { try {
addUserToSharing(sharedFolderNode, ses, user, null, userPrivileges, acls); addUserToSharing(sharedFolderNode, ses, user, null, userPrivileges, acls);
log.info("added user {} to the shared node",user);
}catch(Exception e){ }catch(Exception e){
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName(),e); log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName());
} }
acm.setPolicy(sharedFolderNode.getPath(), acls); acm.setPolicy(sharedFolderNode.getPath(), acls);
@ -275,9 +273,6 @@ public class ItemSharing extends Impersonable{
}catch(StorageHubException she ){ }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Exception e){
log.error("jcr sharing", e);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error sharing folder", e));
}finally{ }finally{
if (ses!=null) if (ses!=null)
ses.logout(); ses.logout();
@ -307,7 +302,6 @@ public class ItemSharing extends Impersonable{
} }
private void addUserToSharing(Node sharedFolderNode, Session ses, String user, Item itemToShare, Privilege[] userPrivileges, JackrabbitAccessControlList acls) throws RepositoryException{ private void addUserToSharing(Node sharedFolderNode, Session ses, String user, Item itemToShare, Privilege[] userPrivileges, JackrabbitAccessControlList acls) throws RepositoryException{
try {
String userRootWSId; String userRootWSId;
String userPath; String userPath;
if (itemToShare==null) { if (itemToShare==null) {
@ -332,10 +326,6 @@ public class ItemSharing extends Impersonable{
else else
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME); usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString())); 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);
}
} }
@ -343,12 +333,12 @@ public class ItemSharing extends Impersonable{
@Path("{id}/unshare") @Path("{id}/unshare")
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
public String unshare(@FormDataParam("users") Set<String> users){ public String unshare(@FormDataParam("users") Set<String> users){
InnerMethodName.set("unshareFolder"); InnerMethodName.instance.set("unshareFolder");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try { try {
log.debug("unsharing folder with id {} with users {}", id, users); log.debug("unsharing folder with id {} with users {}", id, users);
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node sharedNode = ses.getNodeByIdentifier(id); Node sharedNode = ses.getNodeByIdentifier(id);
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser); toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared"); if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");

View File

@ -1,29 +1,29 @@
package org.gcube.data.access.storagehub.services; package org.gcube.data.access.storagehub.services;
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI;
import java.net.URL; 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.RepositoryException;
import javax.jcr.Session; 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.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.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.GCubeItem; import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.plugins.PluginParameters; import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.handlers.items.ItemHandler; 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.ArchiveStructureCreationParameter;
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters; import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
@ -31,7 +31,6 @@ 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.GCubeItemCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder; 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.handlers.items.builders.URLCreationParameters;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
@ -42,32 +41,18 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("items")
@ManagedBy(StorageHubApplicationManager.class) @ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), })
}) public class ItemsCreator extends Impersonable {
public class ItemsCreator extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class); private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
@Context @Context
ServletContext context; ServletContext context;
private final StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject @Inject
ItemHandler itemHandler; ItemHandler itemHandler;
@ -77,25 +62,26 @@ public class ItemsCreator extends Impersonable{
@Path("/{id}/create/FOLDER") @Path("/{id}/create/FOLDER")
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name, public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden) { @FormParam("description") String description, @FormParam("hidden") boolean hidden) {
InnerMethodName.set("createItem(FOLDER)"); InnerMethodName.instance.set("createItem(FOLDER)");
log.info("create folder item called"); log.info("create folder item called");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try{ try {
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name).description(description).hidden(hidden).on(id).with(ses).author(currentUser); ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
.description(description).hidden(hidden).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build()); toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){ } catch (RepositoryException re) {
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{ } finally {
if (ses!=null) if (ses != null)
ses.logout(); ses.logout();
} }
@ -103,43 +89,33 @@ public class ItemsCreator extends Impersonable{
} }
@POST @POST
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/EXTERNALFOLDER") @Path("/{id}/create/EXTERNALFOLDER")
public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name, public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden, @FormParam("description") String description, @FormParam("hidden") boolean hidden,
@FormParam("pluginName") String pluginName, @FormParam("pluginName") String pluginName, @FormParam("parameters") String pluginParameters) {
@Context HttpServletRequest request) { InnerMethodName.instance.set("createItem(EXTERNALFOLDER)");
InnerMethodName.set("createItem(EXTERNALFOLDER)");
log.info("create folder item called"); log.info("create folder item called");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try{ try {
Iterator<String> paramIt = request.getParameterNames().asIterator(); // TODO
Iterable<String> iterable = () -> paramIt; ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
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) ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
.description(description).onRepository(pluginName).withParameters(pluginParams.getParameters()).hidden(hidden).on(id).with(ses).author(currentUser); .description(description).onRepository(pluginName).withParameters(null).hidden(hidden).on(id)
.with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build()); toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){ } catch (RepositoryException re) {
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{ } finally {
if (ses!=null) if (ses != null)
ses.logout(); ses.logout();
} }
@ -149,144 +125,97 @@ public class ItemsCreator extends Impersonable{
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/URL") @Path("/{id}/create/URL")
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) { public Response createURL(@PathParam("id") String id, @FormParam("name") String name,
InnerMethodName.set("createItem(URL)"); @FormParam("description") String description, @FormParam("value") URL value) {
InnerMethodName.instance.set("createItem(URL)");
log.info("create url called"); log.info("create url called");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try{ try {
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name).description(description).url(value).on(id).with(ses).author(currentUser); ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name)
.description(description).url(value).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build()); toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){ } catch (RepositoryException re) {
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{ } finally {
if (ses!=null) if (ses != null)
ses.logout(); ses.logout();
} }
return Response.ok(toReturn).build(); return Response.ok(toReturn).build();
} }
@POST @POST
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/create/GCUBEITEM") @Path("/{id}/create/GCUBEITEM")
public String createGcubeItem(@PathParam("id") String id, GCubeItem item) { public String createGcubeItem(@PathParam("id") String id, GCubeItem item) {
InnerMethodName.set("createItem(GCUBEITEM)"); InnerMethodName.instance.set("createItem(GCUBEITEM)");
log.info("create Gcube item called"); log.info("create Gcube item called");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try{ try {
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder().item(item).on(id).with(ses).author(currentUser); ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder()
.item(item).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build()); toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){ } catch (RepositoryException re) {
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{ } finally {
if (ses!=null) if (ses != null)
ses.logout(); ses.logout();
} }
return toReturn; return toReturn;
} }
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/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);
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));
}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 @POST
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/FILE") @Path("/{id}/create/FILE")
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name, public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
@FormDataParam("description") String description, @FormDataParam("description") String description, @FormDataParam("file") InputStream stream,
@FormDataParam("file") InputStream file, @FormDataParam("file") FormDataContentDisposition fileDetail) {
@FormDataParam("file") FormDataContentDisposition fileDetail){ InnerMethodName.instance.set("createItem(FILE)");
InnerMethodName.set("createItem(FILE)");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try(InputStream is = new BufferedInputStream(file)){ try {
long size = fileDetail.getSize(); 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);
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()); toReturn = itemHandler.create(builder.build());
log.debug("UPLOAD: call finished");
}catch(RepositoryException re ){ } catch (RepositoryException re) {
log.error("jcr error creating file item", re); log.error("jcr error creating file item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{ } finally {
if (ses!=null && ses.isLive()) { if (ses != null && ses.isLive()) {
log.info("session closed"); log.info("session closed");
ses.logout(); ses.logout();
} }
@ -295,79 +224,39 @@ public class ItemsCreator extends Impersonable{
} }
@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 @POST
@Consumes(MediaType.MULTIPART_FORM_DATA) @Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/ARCHIVE") @Path("/{id}/create/ARCHIVE")
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName, public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
@FormDataParam("file") InputStream stream, @FormDataParam("file") InputStream stream, @FormDataParam("file") FormDataContentDisposition fileDetail) {
@FormDataParam("file") FormDataContentDisposition fileDetail){ InnerMethodName.instance.set("createItem(ARCHIVE)");
InnerMethodName.set("createItem(ARCHIVE)");
Session ses = null; Session ses = null;
String toReturn = null; String toReturn = null;
try(InputStream is = new BufferedInputStream(stream)){ try {
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(is).fileDetails(fileDetail) ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter
.on(id).with(ses).author(currentUser); .builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail).on(id).with(ses)
.author(currentUser);
toReturn = itemHandler.create(builder.build()); toReturn = itemHandler.create(builder.build());
}catch(RepositoryException | ArchiveException | IOException re){ } catch (RepositoryException | ArchiveException | IOException re) {
log.error("jcr error extracting archive", re); log.error("jcr error extracting archive", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
}catch(StorageHubException she ){ } catch (StorageHubException she) {
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable e ){ } catch (Throwable e) {
log.error("unexpected error", e); log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally{ } finally {
if (ses!=null) if (ses != null)
ses.logout(); ses.logout();
} }
return toReturn; return toReturn;
} }
} }

View File

@ -1,13 +1,24 @@
package org.gcube.data.access.storagehub.services; 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.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64;
import java.util.Collections; import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; 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.ItemNotFoundException;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.NodeIterator; import javax.jcr.NodeIterator;
@ -15,16 +26,39 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.jcr.lock.LockException; import javax.jcr.lock.LockException;
import javax.jcr.version.Version; import 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.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes; import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants; 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.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException; import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters; import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException; import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException; import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem; import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem; import org.gcube.common.storagehub.model.items.FolderItem;
@ -32,32 +66,29 @@ import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder; import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.VreFolder; import org.gcube.common.storagehub.model.items.VreFolder;
import org.gcube.common.storagehub.model.items.nodes.Content; import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.service.ItemList; import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper; import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.common.storagehub.model.service.VersionList; import org.gcube.common.storagehub.model.service.VersionList;
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.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty; import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker; import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Range; import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.StorageHubApplicationManager; import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.ClassHandler; import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.gcube.data.access.storagehub.handlers.DownloadHandler; import org.gcube.data.access.storagehub.handlers.CompressHandler;
import org.gcube.data.access.storagehub.handlers.PublicLinkHandler; import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler; import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler; import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter; import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter; import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.StorageOperationMediator; import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
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.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -66,25 +97,9 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("items")
@ManagedBy(StorageHubApplicationManager.class) @ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
}) })
@ -92,11 +107,12 @@ public class ItemsManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemsManager.class); private static final Logger log = LoggerFactory.getLogger(ItemsManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject @Inject
AccountingHandler accountingHandler; AccountingHandler accountingHandler;
@RequestScoped
@PathParam("id") @PathParam("id")
String id; String id;
@ -109,9 +125,6 @@ public class ItemsManager extends Impersonable{
@Inject @Inject
VersionHandler versionHandler; VersionHandler versionHandler;
@Inject
DownloadHandler downloadHandler;
@Inject @Inject
TrashHandler trashHandler; TrashHandler trashHandler;
@ -121,24 +134,22 @@ public class ItemsManager extends Impersonable{
@Inject Item2NodeConverter item2Node; @Inject Item2NodeConverter item2Node;
@Inject
FolderPluginHandler folderPluginHandler;
@Inject @Inject
StorageOperationMediator opMediator; CompressHandler compressHandler;
@Inject
PublicLinkHandler publicLinkHandler;
@GET @GET
@Path("{id}") @Path("{id}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getById(@QueryParam("exclude") List<String> excludes){ public ItemWrapper<Item> getById(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getById"); InnerMethodName.instance.set("getById");
Session ses = null; Session ses = null;
Item toReturn = null; Item toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id); Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = node2Item.getItem(node, excludes); toReturn = node2Item.getItem(node, excludes);
@ -163,11 +174,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/path") @Path("{id}/path")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){ public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getByPath"); InnerMethodName.instance.set("getByPath");
Session ses = null; Session ses = null;
Item toReturn = null; Item toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
String relativePath = path.startsWith("/")? path.substring(1) : path; String relativePath = path.startsWith("/")? path.substring(1) : path;
@ -225,7 +236,7 @@ public class ItemsManager extends Impersonable{
@Path("{id}/items/{name}") @Path("{id}/items/{name}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){ public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
InnerMethodName.set("findChildrenByNamePattern"); InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name); return _findChildrenByNamePattern(excludes, name);
} }
@ -233,7 +244,7 @@ public class ItemsManager extends Impersonable{
@Path("{id}/items") @Path("{id}/items")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){ public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
InnerMethodName.set("findChildrenByNamePattern"); InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name); return _findChildrenByNamePattern(excludes, name);
} }
@ -241,7 +252,7 @@ public class ItemsManager extends Impersonable{
Session ses = null; Session ses = null;
List<Item> toReturn = new ArrayList<>(); List<Item> toReturn = new ArrayList<>();
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
//NOT using the internal pattern matching of jcr because of title for shared folder //NOT using the internal pattern matching of jcr because of title for shared folder
@ -280,17 +291,16 @@ public class ItemsManager extends Impersonable{
@GET @GET
@Path("{id}/children/count") @Path("{id}/children/count")
@Produces(MediaType.APPLICATION_JSON)
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){ public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.set("countById"); InnerMethodName.instance.set("countById");
Session ses = null; Session ses = null;
Long toReturn = null; Long toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null; toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemCount(node, showHidden==null?false:showHidden, itemPredicate );
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -311,15 +321,13 @@ public class ItemsManager extends Impersonable{
@Path("{id}/children") @Path("{id}/children")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){ public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.set("listById"); InnerMethodName.instance.set("listById");
Session ses = null; Session ses = null;
List<? extends Item> toReturn = null; List<? extends Item> toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null; toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemList(node, excludes, null, showHidden==null?false:showHidden, itemPredicate);
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -341,16 +349,14 @@ public class ItemsManager extends Impersonable{
@Path("{id}/search") @Path("{id}/search")
@Produces(MediaType.APPLICATION_JSON) @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 ){ 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.set("search"); InnerMethodName.instance.set("search");
Session ses = null; Session ses = null;
List<? extends Item> toReturn = null; List<? extends Item> toReturn = null;
try{ try{
log.debug("search for node {}",name); log.debug("search for node {}",name);
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null; 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);
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()); log.debug("search retrieved {} elements",toReturn.size());
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
@ -373,15 +379,13 @@ public class ItemsManager extends Impersonable{
@Path("{id}/children/paged") @Path("{id}/children/paged")
@Produces(MediaType.APPLICATION_JSON) @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){ 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.set("listByIdPaged"); InnerMethodName.instance.set("listByIdPaged");
Session ses = null; Session ses = null;
List<? extends Item> toReturn = null; List<? extends Item> toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null; toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemList(node, excludes, new Range(start, limit),showHidden==null?false:showHidden, itemPredicate);
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -401,26 +405,62 @@ public class ItemsManager extends Impersonable{
@GET @GET
@Path("publiclink/{id}") @Path("publiclink/{id}")
@AuthorizationControl(allowedUsers={"URIResolver"}) @AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
public Response resolvePublicLink() { public Response resolvePublicLink() {
InnerMethodName.set("resolvePubliclink"); InnerMethodName.instance.set("resolvePubliclink");
log.warn("arrived id is {}",id); log.warn("arrived id is {}",id);
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
PublicLink publicLink = publicLinkHandler.resolveEnchriptedId(id); String complexId = id;
switch (publicLink.getType()) {
case VOLATILE: if (id.startsWith(enchriptedPrefix)) {
return downloadHandler.downloadFileFromStorageBackend(publicLink.getId(), publicLink.getStorageName()); String currentScope = ScopeProvider.instance.get();
case VERSIONED: try {
Item versionedItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT); ScopeBean bean= new ScopeBean(currentScope);
return downloadHandler.downloadVersionedItem(ses, currentUser, (AbstractFileItem) versionedItem, publicLink.getVersion(), true); while (!bean.is(Type.INFRASTRUCTURE)) {
default: bean = bean.enclosingScope();
Item currentItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT);
return downloadHandler.downloadFileItem(ses,(AbstractFileItem) currentItem, currentUser, true);
} }
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);
}
}
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 ){ }catch(RepositoryException re ){
log.error("jcr error getting public link", re); log.error("jcr error getting public link", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re)); GXOutboundErrorResponse.throwException(new BackendGenericError(re));
@ -438,11 +478,11 @@ public class ItemsManager extends Impersonable{
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Path("{id}/publiclink") @Path("{id}/publiclink")
public URL getPublicLink(@QueryParam("version") String version) { public URL getPublicLink(@QueryParam("version") String version) {
InnerMethodName.set("getPubliclink"); InnerMethodName.instance.set("getPubliclink");
Session ses = null; Session ses = null;
URL toReturn = null; URL toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node selectedNode = ses.getNodeByIdentifier(id); Node selectedNode = ses.getNodeByIdentifier(id);
@ -471,10 +511,28 @@ public class ItemsManager extends Impersonable{
ses.getWorkspace().getLockManager().unlock(selectedNode.getPath()); 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();
}
String url = version!=null ? publicLinkHandler.getForVersionedItem(id, version, context): ScopeProvider.instance.set(bean.toString());
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); toReturn = new URL(url);
@ -493,19 +551,21 @@ 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 @PUT
@Path("{id}/publish") @Path("{id}/publish")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public String makeFolderPublic(@FormParam("publish") boolean publish){ public String makeFolderPublic(@FormParam("publish") boolean publish){
InnerMethodName.set("makeFolderPublic("+publish+")"); InnerMethodName.instance.set("makeFolderPublic("+publish+")");
Session ses = null; Session ses = null;
Item folder= null; Item folder= null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Node currentNode =ses.getNodeByIdentifier(id); Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath()); log.trace("current node is {}",currentNode.getPath());
@ -520,7 +580,7 @@ public class ItemsManager extends Impersonable{
ses.save(); ses.save();
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error publishing folder", re); log.error("jcr error getting rootSharedFolder", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re)); GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){ }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
@ -537,11 +597,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/rootSharedFolder") @Path("{id}/rootSharedFolder")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){ public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getRootSharedFolder"); InnerMethodName.instance.set("getRootSharedFolder");
Session ses = null; Session ses = null;
Item sharedParent= null; Item sharedParent= null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode =ses.getNodeByIdentifier(id); Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath()); log.trace("current node is {}",currentNode.getPath());
@ -580,11 +640,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/versions") @Path("{id}/versions")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public VersionList getVersions(){ public VersionList getVersions(){
InnerMethodName.set("getVersions"); InnerMethodName.instance.set("getVersions");
Session ses = null; Session ses = null;
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>(); List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node node = ses.getNodeByIdentifier(id); Node node = ses.getNodeByIdentifier(id);
@ -616,17 +676,13 @@ public class ItemsManager extends Impersonable{
@GET @GET
@Path("{id}/versions/{version}/download") @Path("{id}/versions/{version}/download")
public Response downloadVersion(@PathParam("version") String versionName){ public Response downloadVersion(@PathParam("version") String versionName){
InnerMethodName.set("downloadSpecificVersion"); InnerMethodName.instance.set("downloadSpecificVersion");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); 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 downloadHandler.downloadVersionedItem(ses, currentUser, (AbstractFileItem) currentItem, versionName, true); return downloadVersionInternal(ses, currentUser, id, versionName, true);
}catch(RepositoryException re ){ }catch(RepositoryException re ){
log.error("jcr error downloading version", re); log.error("jcr error downloading version", re);
@ -641,60 +697,56 @@ public class ItemsManager extends Impersonable{
return Response.serverError().build(); return Response.serverError().build();
} }
@DELETE private Response downloadVersionInternal(Session ses, String login, String id, String versionName, boolean withAccounting) throws RepositoryException, StorageHubException{
@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); Node node = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT); Item currentItem = node2Item.getItem(node, Excludes.ALL);
if (!(currentItem instanceof AbstractFileItem)) if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not a file"); throw new InvalidItemException("this item is not a file");
List<Version> versions = versionHandler.getContentVersionHistory(node); List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
boolean found = false; for (Version version: jcrVersions) {
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
for(Version version : versions)
if (version.getName().equals(versionName)) { if (version.getName().equals(versionName)) {
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString()); Content content = node2Item.getContentFromVersion(version);
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()); FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
}catch(RepositoryException re ){ final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
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();
}
}
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();
}
}
throw new InvalidItemException("the version is not valid");
}
@GET @GET
@Path("{id}/anchestors") @Path("{id}/anchestors")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){ public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getAnchestors"); InnerMethodName.instance.set("getAnchestors");
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser); org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
Session ses = null; Session ses = null;
List<Item> toReturn = new LinkedList<>(); List<Item> toReturn = new LinkedList<>();
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode = ses.getNodeByIdentifier(id); Node currentNode = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(currentNode, excludes); Item currentItem = node2Item.getItem(currentNode, excludes);
@ -744,17 +796,50 @@ public class ItemsManager extends Impersonable{
@GET @GET
@Path("{id}/download") @Path("{id}/download")
public Response download(@QueryParam("exclude") List<String> excludes){ public Response download(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("downloadById"); InnerMethodName.instance.set("downloadById");
Session ses = null; Session ses = null;
Response response = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
final Node node = ses.getNodeByIdentifier(id); final Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Item item = node2Item.getItem(node, null); final Item item = node2Item.getItem(node, null);
if (item instanceof AbstractFileItem){ if (item instanceof AbstractFileItem){
return downloadHandler.downloadFileItem(ses, (AbstractFileItem) item, currentUser, true); return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
} else if (item instanceof FolderItem){ } else if (item instanceof FolderItem){
return downloadHandler.downloadFolderItem(ses, currentUser, (FolderItem)item, true);
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();
}
} else throw new InvalidItemException("item type not supported for download: "+item.getClass()); } else throw new InvalidItemException("item type not supported for download: "+item.getClass());
}catch(RepositoryException re ){ }catch(RepositoryException re ){
@ -766,19 +851,40 @@ public class ItemsManager extends Impersonable{
} finally{ } finally{
if (ses!=null) ses.logout(); if (ses!=null) ses.logout();
} }
return null;
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();
} }
@PUT @PUT
@Path("{id}/move") @Path("{id}/move")
public String move(@FormParam("destinationId") String destinationId){ public String move(@FormParam("destinationId") String destinationId){
InnerMethodName.set("move"); InnerMethodName.instance.set("move");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id); authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true); authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
@ -823,11 +929,10 @@ public class ItemsManager extends Impersonable{
if (movingSharedItemOutside) if (movingSharedItemOutside)
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser); item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
//add onMove (if it changes the remotePath) and in case of different backend //folderHandler.onMove(source, destination);
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false); accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false); accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false);
ses.save(); ses.save();
}finally { }finally {
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath()); ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
@ -851,20 +956,20 @@ public class ItemsManager extends Impersonable{
@PUT @PUT
@Path("{id}/copy") @Path("{id}/copy")
public String copy(@FormParam("destinationId") String destinationId, @FormParam("fileName") String newFileName){ public String copy(@FormParam("destinationId") String destinationId, @FormParam("fileName") String newFileName){
InnerMethodName.set("copy"); InnerMethodName.instance.set("copy");
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root or if the item is thrashed //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; Session ses = null;
String newFileIdentifier = null; String newFileIdentifier = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true); authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
authChecker.checkReadAuthorizationControl(ses, currentUser, id); authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Node nodeToCopy = ses.getNodeByIdentifier(id); final Node nodeToCopy = ses.getNodeByIdentifier(id);
final Node destination = ses.getNodeByIdentifier(destinationId); final Node destination = ses.getNodeByIdentifier(destinationId);
FolderItem destinationItem = (FolderItem)node2Item.getItem(destination,null); //Item destinationItem = node2Item.getItem(destination,null);
final Item item = node2Item.getItem(nodeToCopy, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME)); final Item item = node2Item.getItem(nodeToCopy, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
@ -877,7 +982,6 @@ public class ItemsManager extends Impersonable{
}catch (LockException e) { }catch (LockException e) {
throw new ItemLockedException(e); throw new ItemLockedException(e);
} }
try { try {
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destination, newFileName); String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destination, newFileName);
String newPath= String.format("%s/%s", destination.getPath(), uniqueName); String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
@ -885,20 +989,22 @@ public class ItemsManager extends Impersonable{
Node newNode = ses.getNode(newPath); Node newNode = ses.getNode(newPath);
newFileIdentifier = newNode.getIdentifier(); newFileIdentifier = newNode.getIdentifier();
Content contentToCopy = ((AbstractFileItem) item).getContent(); //TODO: folderHandler.onCopy(source, destination);
MetaInfo contentInfo = opMediator.copy(contentToCopy, destinationItem.getBackend(), destination.getPath(), uniqueName, currentUser);
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); item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
//replaces content copied with new information }
Utils.setContentFromMetaInfo((AbstractFileItem) item, contentInfo);
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED); Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser); newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false); newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName); newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
String mimeTypeForAccounting = ((AbstractFileItem) item).getContent().getMimeType(); String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false); accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
@ -926,12 +1032,12 @@ public class ItemsManager extends Impersonable{
@PUT @PUT
@Path("{id}/rename") @Path("{id}/rename")
public Response rename(@FormParam("newName") String newName){ public Response rename(@FormParam("newName") String newName){
InnerMethodName.set("rename"); InnerMethodName.instance.set("rename");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id); authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -941,10 +1047,11 @@ public class ItemsManager extends Impersonable{
final Item item = node2Item.getItem(nodeToMove, null); final Item item = node2Item.getItem(nodeToMove, null);
if (item instanceof SharedFolder) if (item instanceof SharedFolder)
if (getSharedParentNode(nodeToMove).getIdentifier() == item.getId()) throw new InvalidItemException("shared folder");
throw new InvalidItemException("root shared folder name cannot be modfied");
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()))
throw new InvalidItemException("protected folder cannot be renamed");
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
try { try {
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser); ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
@ -952,7 +1059,10 @@ public class ItemsManager extends Impersonable{
}catch (LockException e) { }catch (LockException e) {
throw new ItemLockedException(e); throw new ItemLockedException(e);
} }
try { try {
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName); String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName); nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED); Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
@ -984,13 +1094,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/hidden") @Path("/{id}/hidden")
public Response setItemAsHidden(Boolean hidden){ public Response setItemAsHidden(Boolean hidden){
InnerMethodName.set("setHidden"); InnerMethodName.instance.set("setHidden");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1029,13 +1139,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/description") @Path("/{id}/description")
public Response setDescription(String description){ public Response setDescription(String description){
InnerMethodName.set("setDescription"); InnerMethodName.instance.set("setDescription");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1073,13 +1183,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/metadata") @Path("/{id}/metadata")
public Response setMetadata(org.gcube.common.storagehub.model.Metadata metadata){ public Response setMetadata(org.gcube.common.storagehub.model.Metadata metadata){
InnerMethodName.set("updateMetadata"); InnerMethodName.instance.set("updateMetadata");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1118,7 +1228,7 @@ public class ItemsManager extends Impersonable{
@DELETE @DELETE
@Path("{id}") @Path("{id}")
public Response deleteItem(@QueryParam("force") boolean force){ public Response deleteItem(@QueryParam("force") boolean force){
InnerMethodName.set("deleteItem("+force+")"); InnerMethodName.instance.set("deleteItem("+force+")");
Session ses = null; Session ses = null;
try{ try{
@ -1126,7 +1236,7 @@ public class ItemsManager extends Impersonable{
log.info("removing node with id {}", id); log.info("removing node with id {}", id);
//TODO check if it is possible to change all the ACL on a workspace //TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false); authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
authChecker.checkMoveOpsForProtectedFolders(ses, id); authChecker.checkMoveOpsForProtectedFolders(ses, id);
@ -1163,30 +1273,5 @@ public class ItemsManager extends Impersonable{
return Response.ok().build(); 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);
}
} }

View File

@ -5,11 +5,28 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException; import javax.jcr.ItemNotFoundException;
import javax.jcr.Node; import javax.jcr.Node;
import javax.jcr.NodeIterator; import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
import javax.jcr.Session; import javax.jcr.Session;
import javax.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.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.User; import org.apache.jackrabbit.api.security.user.User;
@ -23,29 +40,23 @@ import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException; import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem; import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.Item; 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.items.nodes.Owner;
import org.gcube.common.storagehub.model.messages.Message; import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.common.storagehub.model.service.ItemList; 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.ItemAction;
import org.gcube.common.storagehub.model.types.MessageList; import org.gcube.common.storagehub.model.types.MessageList;
import org.gcube.common.storagehub.model.types.NodeProperty; import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager; import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler; import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler; import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter; import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter.Values; 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.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler; import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
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.data.access.storagehub.types.MessageSharable;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
@ -55,24 +66,8 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; 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") @Path("messages")
@ManagedBy(StorageHubApplicationManager.class) @ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
}) })
@ -80,7 +75,7 @@ public class MessageManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(MessageManager.class); private static final Logger log = LoggerFactory.getLogger(MessageManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject @Inject
AccountingHandler accountingHandler; AccountingHandler accountingHandler;
@ -89,6 +84,9 @@ public class MessageManager extends Impersonable{
@PathParam("id") @PathParam("id")
String id; String id;
@Context
ServletContext context;
@Inject PathUtil pathUtil; @Inject PathUtil pathUtil;
@Inject Node2ItemConverter node2Item; @Inject Node2ItemConverter node2Item;
@ -96,18 +94,15 @@ public class MessageManager extends Impersonable{
@Inject TrashHandler trashHandler; @Inject TrashHandler trashHandler;
@Inject
StorageBackendHandler storageBackendHandler;
@GET @GET
@Path("{id}") @Path("{id}")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Message getById(){ public Message getById(){
InnerMethodName.set("getMessageById"); InnerMethodName.instance.set("getMessageById");
Session ses = null; Session ses = null;
Message toReturn = null; Message toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id); Node messageNode = ses.getNodeByIdentifier(id);
toReturn = node2Item.getMessageItem(messageNode); toReturn = node2Item.getMessageItem(messageNode);
checkRights(currentUser, toReturn); checkRights(currentUser, toReturn);
@ -131,28 +126,25 @@ public class MessageManager extends Impersonable{
@DELETE @DELETE
@Path("{id}") @Path("{id}")
public void deleteById(){ public void deleteById(){
InnerMethodName.set("deleteMessageById"); InnerMethodName.instance.set("deleteMessageById");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id); Node messageNode = ses.getNodeByIdentifier(id);
Message message = node2Item.getMessageItem(messageNode); Message message = node2Item.getMessageItem(messageNode);
Node personalNode = checkRights(currentUser, message); Node personalNode = checkRights(currentUser, message);
if (countSharedSet(messageNode)>1) { if (countSharedSet(messageNode)>1)
log.debug("removing node message "+personalNode.getPath()); personalNode.removeShare();
personalNode.remove(); else {
}else {
if (message.isWithAttachments()) { if (message.isWithAttachments()) {
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME); Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
ItemTypePredicate itemPredicate = new IncludeTypePredicate(AbstractFileItem.class); List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, itemPredicate);
trashHandler.removeOnlyNodesContent(ses, attachments); trashHandler.removeOnlyNodesContent(ses, attachments);
} }
messageNode.removeSharedSet(); messageNode.removeSharedSet();
} }
ses.save(); ses.save();
log.debug("removing node message saved");
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -172,17 +164,16 @@ public class MessageManager extends Impersonable{
@Path("{id}/attachments") @Path("{id}/attachments")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public ItemList getAttachments(){ public ItemList getAttachments(){
InnerMethodName.set("getAttachmentsByMessageId"); InnerMethodName.instance.set("getAttachmentsByMessageId");
Session ses = null; Session ses = null;
List<Item> attachments = new ArrayList<>(); List<Item> attachments = new ArrayList<>();
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id); Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode); Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem); checkRights(currentUser, messageItem);
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME); Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
ItemTypePredicate itemPredicate = new IncludeTypePredicate(AbstractFileItem.class); attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, itemPredicate);
}catch (ItemNotFoundException e) { }catch (ItemNotFoundException e) {
log.error("id {} not found",id,e); log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -204,11 +195,11 @@ public class MessageManager extends Impersonable{
@Path("inbox") @Path("inbox")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){ public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.set("getReceivedMessages"); InnerMethodName.instance.set("getReceivedMessages");
Session ses = null; Session ses = null;
List<Message> toReturn = null; List<Message> toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath()); Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath());
@ -229,11 +220,11 @@ public class MessageManager extends Impersonable{
@Path("sent") @Path("sent")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){ public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.set("getSentMessages"); InnerMethodName.instance.set("getSentMessages");
Session ses = null; Session ses = null;
List<Message> toReturn = null; List<Message> toReturn = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath()); Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
@ -253,10 +244,10 @@ public class MessageManager extends Impersonable{
@Path("{id}/{prop}") @Path("{id}/{prop}")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public void setProperty(@PathParam("prop") String property,Object value){ public void setProperty(@PathParam("prop") String property,Object value){
InnerMethodName.set("setPropertyOnMessage("+property+")"); InnerMethodName.instance.set("setPropertyOnMessage("+property+")");
Session ses = null; Session ses = null;
try{ try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id); Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode); Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem); checkRights(currentUser, messageItem);
@ -286,7 +277,7 @@ public class MessageManager extends Impersonable{
public String sendMessage(@FormParam("to[]") List<String> addresses, public String sendMessage(@FormParam("to[]") List<String> addresses,
@FormParam("subject") String subject, @FormParam("body") String body, @FormParam("subject") String subject, @FormParam("body") String body,
@FormParam("attachments[]") List<String> attachments){ @FormParam("attachments[]") List<String> attachments){
InnerMethodName.set("sendMessage"); InnerMethodName.instance.set("sendMessage");
JackrabbitSession ses = null; JackrabbitSession ses = null;
String messageId = null; String messageId = null;
try{ try{
@ -295,7 +286,7 @@ public class MessageManager extends Impersonable{
log.debug("attachments send are {}",attachments); log.debug("attachments send are {}",attachments);
ses = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Message message = new MessageSharable(); Message message = new MessageSharable();
message.setAddresses(addresses.toArray(new String[0])); message.setAddresses(addresses.toArray(new String[0]));
@ -303,9 +294,6 @@ public class MessageManager extends Impersonable{
message.setBody(body); message.setBody(body);
message.setName(UUID.randomUUID().toString()); message.setName(UUID.randomUUID().toString());
User user = ses.getUserManager().getAuthorizable(currentUser, User.class); User user = ses.getUserManager().getAuthorizable(currentUser, User.class);
if (user ==null)
throw new InvalidCallParameters("invalid storagehub user: "+currentUser);
Owner owner = new Owner(); Owner owner = new Owner();
owner.setUserId(user.getID()); owner.setUserId(user.getID());
owner.setUserName(user.getPrincipal().getName()); owner.setUserName(user.getPrincipal().getName());
@ -343,7 +331,7 @@ public class MessageManager extends Impersonable{
private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, StorageHubException{ private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, BackendGenericError{
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME); Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
for (String itemId: attachments) { for (String itemId: attachments) {
@ -363,7 +351,7 @@ public class MessageManager extends Impersonable{
NodeIterator nodeIt = node.getNodes(); NodeIterator nodeIt = node.getNodes();
while(nodeIt.hasNext()) { while(nodeIt.hasNext()) {
Node child = nodeIt.nextNode(); Node child = nodeIt.nextNode();
log.trace("message type "+child.getPrimaryNodeType().getName()); log.info("message type "+child.getPrimaryNodeType().getName());
Message message = node2Item.getMessageItem(child); Message message = node2Item.getMessageItem(child);
if (message == null) { if (message == null) {
log.info("message discarded"); log.info("message discarded");
@ -408,8 +396,10 @@ public class MessageManager extends Impersonable{
return personalNode== null ? messageNode : personalNode; 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, StorageHubException{ private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, BackendGenericError{
//it needs to be locked ?? //it needs to be locked ??
Node nodeToCopy = ((Node)itemToCopy.getRelatedNode()); Node nodeToCopy = ((Node)itemToCopy.getRelatedNode());
String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() ); String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() );
@ -419,15 +409,9 @@ public class MessageManager extends Impersonable{
if (itemToCopy instanceof AbstractFileItem) { if (itemToCopy instanceof AbstractFileItem) {
AbstractFileItem newNodeItem = node2Item.getItem(newNode, Excludes.EXCLUDE_ACCOUNTING); AbstractFileItem newNodeItem = node2Item.getItem(newNode, Excludes.EXCLUDE_ACCOUNTING);
newNodeItem.getContent().setRemotePath(newPath);
Content contentToCopy = newNodeItem.getContent(); String newStorageID = folderPluginHandler.getDefault().getStorageBackend().onCopy(newNodeItem);
newNodeItem.getContent().setStorageId(newStorageID);
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); item2Node.replaceContent(newNode, newNodeItem, ItemAction.CLONED);
} }

View File

@ -0,0 +1,10 @@
package org.gcube.data.access.storagehub.services;
import javax.jcr.Repository;
public interface RepositoryInitializer {
Repository getRepository();
void shutdown();
}

View File

@ -1,40 +0,0 @@
package org.gcube.data.access.storagehub.services;
import java.util.ArrayList;
import java.util.List;
import org.gcube.common.storagehub.model.storages.StorageDescriptor;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("storages")
@ManagedBy(StorageHubApplicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class StorageManager {
@Inject
StorageBackendHandler storageBackendHandler;
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public List<StorageDescriptor> getStorages(){
InnerMethodName.set("getStorages");
List<StorageDescriptor> storages = new ArrayList<>();
storageBackendHandler.getAllImplementations().forEach( f -> storages.add(new StorageDescriptor(f.getName())));
return storages;
}
}

View File

@ -1,22 +1,58 @@
package org.gcube.data.access.storagehub.services; package org.gcube.data.access.storagehub.services;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException; import javax.jcr.RepositoryException;
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.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.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.Query;
import org.apache.jackrabbit.api.security.user.QueryBuilder;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
import org.gcube.common.authorization.control.annotations.AuthorizationControl; import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse; import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError; import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException; import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException; import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.service.UsersList; import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.types.SHUBUser; import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants; import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.StorageHubApplicationManager; import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.repository.StoragehubRepository; import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.services.delegates.UserManagerDelegate; import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName; import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -25,73 +61,103 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader; import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders; import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
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.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("users") @Path("users")
@ManagedBy(StorageHubApplicationManager.class) @ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({ @RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), }) @RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class UserManager { public class UserManager {
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager"; private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
@Context ServletContext context;
private static final Logger log = LoggerFactory.getLogger(UserManager.class); private static final Logger log = LoggerFactory.getLogger(UserManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository; RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject @Inject
UserManagerDelegate userHandler; UnshareHandler unshareHandler;
@Inject
AuthorizationChecker authChecker;
@Inject
TrashHandler trashHandler;
@Inject
GroupHandler groupHandler;
@Inject
PathUtil pathUtil;
@GET @GET
@Path("") @Path("")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public UsersList getUsers() { public List<String> getUsers(){
InnerMethodName.set("getUsers");
InnerMethodName.instance.set("getUsers");
JackrabbitSession session = null; JackrabbitSession session = null;
List<String> users = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
return new UsersList(userHandler.getAllUsers(session));
} catch (Throwable e) {
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(User.class);
}
});
Set<String> usersSet= new HashSet<>();
String adminUser = context.getInitParameter(Constants.ADMIN_PARAM_NAME);
while (result.hasNext()) {
Authorizable user = result.next();
log.debug("user {} found",user.getPrincipal().getName());
if (user.getPrincipal().getName().equals(adminUser)) continue;
usersSet.add(user.getPrincipal().getName());
}
users = new ArrayList<>(usersSet);
Collections.sort(users);
}catch(Exception e) {
log.error("jcr error getting users", e); log.error("jcr error getting users", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally { } finally {
if (session != null) if (session!=null)
session.logout(); session.logout();
} }
return null; return users;
} }
@GET @GET
@Path("{user}") @Path("{user}")
@Produces(MediaType.APPLICATION_JSON) public String getUser(@PathParam("user") String user){
public SHUBUser getUser(@PathParam("user") String user) {
InnerMethodName.set("getUser");
InnerMethodName.instance.set("getUser");
JackrabbitSession session = null; JackrabbitSession session = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
return userHandler.getUser(session, user);
} catch (StorageHubException se) { org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
log.error("error getting user", se); Authorizable authorizable = usrManager.getAuthorizable(user);
GXOutboundErrorResponse.throwException(se);
} catch (Exception e) { if (authorizable != null && !authorizable.isGroup())
return authorizable.getPrincipal().getName();
log.debug("user {} not found", user);
}catch(Exception e) {
log.error("jcr error getting user", e); log.error("jcr error getting user", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e)); GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally { } finally {
if (session != null) if (session!=null)
session.logout(); session.logout();
} }
@ -103,114 +169,201 @@ public class UserManager {
@POST @POST
@Path("") @Path("")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE }) @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createUser(@FormParam("user") String user, @FormParam("password") String password) { public String createUser(@FormParam("user") String user, @FormParam("password") String password){
InnerMethodName.set("createUser"); InnerMethodName.instance.set("createUser");
JackrabbitSession session = null; JackrabbitSession session = null;
String userId = null; String userId = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
userId = userHandler.createUser(session, user, password);
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
User createdUser = usrManager.createUser(user, password);
userId = createdUser.getID();
Node homeNode = session.getNode("/Home");
Node userHome = homeNode.addNode(user, "nthl:home");
userHome.setProperty(Constants.HOME_VERSION_PROP, 1l);
//creating workspace folder
FolderCreationParameters wsFolderParameters = FolderCreationParameters.builder().name(Constants.WORKSPACE_ROOT_FOLDER_NAME).description("workspace of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(wsFolderParameters, null);
//creating thrash folder
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(trashFolderParameters, null);
//creating Vre container folder
FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder().name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(vreFolderParameters, null);
//creating inbox folder
FolderCreationParameters inboxFolderParameters = FolderCreationParameters.builder().name(Constants.INBOX_FOLDER_NAME).description("inbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(inboxFolderParameters, null);
//creating outbox folder
FolderCreationParameters outboxFolderParameters = FolderCreationParameters.builder().name(Constants.OUTBOX_FOLDER_NAME).description("outbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(outboxFolderParameters, null);
session.save(); session.save();
} catch (StorageHubException she) { }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) { }catch(RepositoryException re ){
log.error("jcr error creating item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { } finally {
if (session != null) if (session!=null)
session.logout(); session.logout();
} }
return userId; return userId;
} }
@PUT
@Path("{user}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE })
public String updateHomeUserToLatestVersion(@PathParam("user") String user) {
InnerMethodName.set("updateHomeUserToLatestVersion");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
userId = userHandler.updateHomeUserToLatestVersion(session, userId);
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 {
if (session != null)
session.logout();
}
return userId;
}
@DELETE @DELETE
@Path("{user}") @Path("{user}")
@AuthorizationControl(allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE }) @AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteUser(@PathParam("user") final String user) { public String deleteUser(@PathParam("user") final String user){
InnerMethodName.set("deleteUser"); InnerMethodName.instance.set("deleteUser");
JackrabbitSession session = null; JackrabbitSession session = null;
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS); session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
userHandler.deleteUser(session, user); org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
User authorizable = (User) usrManager.getAuthorizable(new PrincipalImpl(user));
if (authorizable!=null)
removeUserFromBelongingGroup(session, authorizable, usrManager);
else log.warn("user was already deleted from jackrabbit, trying to delete folders");
unshareUsersFolders(session, user);
removeUserHomeAndDeleteFiles(session, user);
//FINALIZE user removal
if (authorizable!=null && !authorizable.isGroup()) {
log.info("removing user {}", user);
authorizable.remove();
} else log.warn("the user {} was already deleted, it should never happen", user);
session.save(); session.save();
} catch (StorageHubException she) { }catch(StorageHubException she ){
log.error(she.getErrorMessage(), she); log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) { }catch(RepositoryException re ){
log.error("jcr error removing item", re); log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing item", re)); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { } finally {
if (session != null) if (session!=null)
session.logout(); session.logout();
} }
return user; return user;
} }
@GET private void removeUserFromBelongingGroup(JackrabbitSession session, User authorizable, org.apache.jackrabbit.api.security.user.UserManager usrManager) throws RepositoryException, StorageHubException {
@Path("{user}/groups") Iterator<Authorizable> groups = session.getUserManager().findAuthorizables(new Query() {
@Produces(MediaType.APPLICATION_JSON)
public List<String> getGroupsPerUser(@PathParam("user") final String user) {
InnerMethodName.set("getGroupsPerUser"); @Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(Group.class);
}
});
JackrabbitSession session = null;
List<String> groups = new ArrayList<>();
String user = authorizable.getPrincipal().getName();
while(groups.hasNext()) {
Authorizable group = groups.next();
log.info("group found {}", group.getPrincipal().getName() );
if (group.isGroup() && ((Group)group).isMember(authorizable)) {
boolean success = groupHandler.removeUserFromGroup(group.getPrincipal().getName(), user, session);
log.warn("user {} {} removed from vre {}",user,success?"":"not" ,group.getPrincipal().getName());
}
}
}
private void unshareUsersFolders(JackrabbitSession session, String user){
try { try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
userHandler.getGroupsPerUser(session, user); Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH);
} catch (RepositoryException re) {
log.error("jcr error creating item", re); Predicate<Node> sharedWithUserChecker = new Predicate<Node>() {
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally { @Override
if (session != null) public boolean test(Node t) {
session.logout(); try {
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
return true;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
List<SharedFolder> items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class);
log.debug(" Shared folder to unshare found are {}", items.size());
for (SharedFolder item: items) {
String title = item.getTitle();
log.debug("in list folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue;
if (item.isVreFolder()) continue;
log.info("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
String owner = item.getOwner();
Set<String> usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user);
try {
unshareHandler.unshareForRemoval(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user);
}catch (Throwable e) {
log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e);
}
}
} catch (Throwable t) {
log.warn("error getting folder shared with {}",user, t);
} }
return groups;
} }
private void removeUserHomeAndDeleteFiles(JackrabbitSession session, String user) throws RepositoryException, StorageHubException {
org.gcube.common.storagehub.model.Path homePath = pathUtil.getHome(user);
org.gcube.common.storagehub.model.Path workspacePath = pathUtil.getWorkspacePath(user);
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(user, session);
try {
Node workspaceNode = session.getNode(workspacePath.toPath());
List<Item> workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null).stream().filter(i -> !i.isShared()).collect(Collectors.toList());
trashHandler.removeOnlyNodesContent(session, workspaceItems);
} catch (PathNotFoundException e) {
log.warn("{} workspace dir {} was already deleted", user, homePath.toPath());
}
try {
Node trashNode = session.getNode(trashPath.toPath());
List<Item> trashItems = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
trashHandler.removeOnlyNodesContent(session, trashItems);
} catch (PathNotFoundException e) {
log.warn("{} trash dir {} was already deleted", user, homePath.toPath());
}
try {
Node homeNode = session.getNode(homePath.toPath());
homeNode.remove();
} catch (PathNotFoundException e) {
log.warn("{} home dir {} was already deleted", user, homePath.toPath());
}
}
} }

Some files were not shown because too many files have changed in this diff Show More