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

6
.gitignore vendored
View File

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

View File

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

View File

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

View File

@ -1,21 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
@ -40,23 +24,7 @@
<wb-module deploy-name="storagehub">
@ -81,23 +49,7 @@
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
@ -122,78 +74,57 @@
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/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>
@ -218,23 +149,7 @@
<property name="context-root" value="storagehub"/>
@ -259,23 +174,7 @@
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
@ -300,23 +199,7 @@
</wb-module>

View File

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

View File

@ -1,22 +1,23 @@
# Changelog for "storagehub"
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.0.0]
## [v1.4.2] - [2023-05-22]
- ceph as default storage
- vre folders can define specific bucket as backend
- enunciate docs
- dockerization of the service
- added enunciate libraries for documentation
## [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
- incident solved [#22184]
- incident #22184 solved
## [v1.3.2] - [2021-09-28]
- fix 22087
- fix 22087
## [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]
possibility to impersonate people added
- possibility to impersonate people added
## [v1.2.5] - [2021-03-11]
@ -48,6 +49,8 @@ method for description update added
bug on Archive uploader solved
## [v1.2.0] - [2020-04-15]
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
## [v1.0.8] - [2019-09-20]
Bug on ushare owner fixed
## [v1.0.5] - [2019-04-04]
Active wait for lock in case of item creation added
## [v1.0.0] - [2015-07-01]
First commit

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>

442
pom.xml
View File

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

View File

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

View File

@ -3,8 +3,6 @@ package org.gcube.data.access.storagehub;
import java.util.Arrays;
import java.util.List;
import javax.jcr.SimpleCredentials;
public class Constants {
public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
@ -19,8 +17,6 @@ public class Constants {
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe";
//public static final String MYSHARED_PARENT_NAME = "MyShared";
public static final String SHARED_FOLDER_PATH = "/Share";
public static final String WORKSPACE_ROOT_FOLDER_NAME ="Workspace";
@ -29,6 +25,10 @@ public class Constants {
public static final String QUERY_LANGUAGE ="JCR-SQL2";
public static final String ADMIN_PARAM_NAME ="admin-username";
public static final String ADMIN_PARAM_PWD ="admin-pwd";
public static final String HOME_VERSION_PROP = "hl:version";
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
@ -36,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> 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;
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.ApplicationEventListener;
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.LoggerFactory;
import jakarta.ws.rs.ext.Provider;
@Provider
public class MyApplicationListener implements ApplicationEventListener {
private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
StoragehubRepository repository = StoragehubRepository.repository;
@Inject
RepositoryInitializer repository;
@Override
public void onEvent(ApplicationEvent event) {
log.info("StorageHub - event called");
switch (event.getType()) {
case DESTROY_FINISHED:
log.info("Destroying application storageHub");
repository.shutdown();
((JackrabbitRepository) repository.getRepository()).shutdown();
log.info("Jackrabbit repository stopped");
default:
break;

View File

@ -1,6 +1,6 @@
package org.gcube.data.access.storagehub;
import jakarta.inject.Singleton;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@ -46,13 +46,8 @@ public class PathUtil {
}
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 {
Path home = getHome(login);

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.OutputStream;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.StreamingOutput;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;
import org.slf4j.Logger;
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.Set;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Application;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
import org.gcube.data.access.storagehub.services.ACLManager;
import org.gcube.data.access.storagehub.services.DocsGenerator;
import org.gcube.data.access.storagehub.services.DocManager;
import org.gcube.data.access.storagehub.services.GroupManager;
import org.gcube.data.access.storagehub.services.Impersonable;
import org.gcube.data.access.storagehub.services.ItemSharing;
import org.gcube.data.access.storagehub.services.ItemsCreator;
import org.gcube.data.access.storagehub.services.ItemsManager;
import org.gcube.data.access.storagehub.services.MessageManager;
import org.gcube.data.access.storagehub.services.StorageManager;
import org.gcube.data.access.storagehub.services.UserManager;
import org.gcube.data.access.storagehub.services.WorkspaceManager;
import org.gcube.data.access.storagehub.services.admin.ScriptManager;
@ -38,11 +37,10 @@ public class StorageHub extends Application {
classes.add(GroupManager.class);
classes.add(ScriptManager.class);
classes.add(MessageManager.class);
classes.add(StorageManager.class);
classes.add(DocsGenerator.class);
classes.add(MultiPartFeature.class);
classes.add(SerializableErrorEntityTextWriter.class);
classes.add(MyApplicationListener.class);
classes.add(DocManager.class);
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.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
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.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.ExternalLink;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.items.GenericFileItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.types.FolderInfoType;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -79,25 +72,11 @@ public class Utils {
return digest;
}
public static long getItemCount(Node parent, boolean showHidden, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, itemTypePredicate).size();
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
}
public static FolderInfoType getFolderInfo(Node parent) throws RepositoryException, BackendGenericError{
FolderInfoType info = new FolderInfoType(0, 0);
List<Item> items = getItemList(parent, Excludes.GET_ONLY_CONTENT, null, false, null);
for (Item item: items)
if (item instanceof FolderItem) {
FolderInfoType fit = getFolderInfo((Node) item.getRelatedNode());
info.setCount(info.getCount() + fit.getCount());
info.setSize(info.getSize() + fit.getSize());
} else if (item instanceof AbstractFileItem gfi)
info.setSize(info.getSize() + gfi.getContent().getSize());
info.setCount(info.getCount() + items.size());
return info;
}
public static void acquireLockWithWait(Session ses, String nodePath, boolean isDeep, String login, int maxTries) throws RepositoryException, ItemLockedException {
Lock lock = null;
@ -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 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, ItemTypePredicate itemTypePredicate) throws RepositoryException, BackendGenericError{
return getItemList(null, parent, excludes, range, showHidden, itemTypePredicate);
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
return getItemList(null, parent, excludes, range, showHidden, nodeTypeToInclude);
}
public static <T extends Item> List<T> getItemList(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());
long start = System.currentTimeMillis();
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent);
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, 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>();
logger.trace("nodeType is {}",nodeTypeToInclude);
int count =0;
logger.trace("selected range is {}", range);
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());
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;
returnList.add(item);
}
@ -209,7 +188,7 @@ public class Utils {
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[2048];
@ -232,20 +211,19 @@ public class Utils {
return false;
}
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
String escapedName = Text.escapeIllegalJcrChars(name);
try {
destination.getNode(escapedName);
destination.getNode(name);
}catch(PathNotFoundException pnf) {
return escapedName;
return Text.escapeIllegalJcrChars(name);
} catch (Exception e) {
throw new BackendGenericError(e);
}
try {
String filename = FilenameUtils.getBaseName(escapedName);
String ext = FilenameUtils.getExtension(escapedName);
String filename = FilenameUtils.getBaseName(name);
String ext = FilenameUtils.getExtension(name);
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) ;
return newName;
return Text.escapeIllegalJcrChars(newName);
} catch (Exception 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());
Node destinationNode;
FolderItem destinationItem;
try {
destinationNode = params.getSession().getNodeByIdentifier(params.getParentId());
destinationItem = (FolderItem) new Node2ItemConverter().getItem(destinationNode, Excludes.ALL);
}catch (RepositoryException e) {
logger.error("id not found",e);
}catch (RepositoryException e) {
throw new IdNotFoundException(params.getParentId());
}
String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName());
@ -288,20 +263,6 @@ public class Utils {
item.setName(uniqueName);
item.setTitle(uniqueName);
item.setDescription(params.getDescription());
if (isInternalWSFolder) {
item.setBackend(StorageBackendHandler.getDefaultPayloadForFolder());
} else {
if (params.getBackend() != null)
item.setBackend(params.getBackend());
else {
if (destinationItem.getBackend() != null)
item.setBackend(destinationItem.getBackend());
else
item.setBackend(StorageBackendHandler.getDefaultPayloadForFolder());
}
}
//TODO: item.setExternalStorage();
//item.setCreationTime(now);
@ -351,7 +312,6 @@ public class Utils {
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
if (accountingHandler!=null) {
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
@ -386,11 +346,5 @@ public class Utils {
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
}
public static void setContentFromMetaInfo(AbstractFileItem item, MetaInfo contentInfo) {
item.getContent().setSize(contentInfo.getSize());
item.getContent().setRemotePath(contentInfo.getRemotePath());
item.getContent().setSize(contentInfo.getSize());
item.getContent().setPayloadBackend(contentInfo.getPayloadBackend());
}
}

View File

@ -4,17 +4,21 @@ import java.util.Calendar;
import java.util.Set;
import java.util.UUID;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.inject.Singleton;
@Singleton
public class AccountingHandler {
@ -28,12 +32,11 @@ public class AccountingHandler {
private static final String OLD_ITEM_NAME = "hl:oldItemName";
private static final String NEW_ITEM_NAME = "hl:newItemName";
private static final String BASE_VERSION ="1.0";
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
public void createReadObj(String title, String version, Session ses, Node node, String login, boolean saveHistory ) {
public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -46,8 +49,20 @@ public class AccountingHandler {
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
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();
} catch (RepositoryException e) {
logger.warn("error trying to retrieve accountign node",e);
@ -66,8 +81,6 @@ public class AccountingHandler {
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, BASE_VERSION);
if (saveHistory) ses.save();
} catch (RepositoryException e) {
@ -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 {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -84,35 +97,26 @@ public class AccountingHandler {
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, version);
if (saveHistory) ses.save();
} catch (RepositoryException e) {
logger.warn("error trying to retrieve accountign node",e);
}
}
public void createVersionDeleted(String title, String version, Session ses, Node node, String login, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
node.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
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);
}
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.DELETE.getNodeTypeDefinition());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(VERSION_ACCOUNTING, version);
if (saveHistory) ses.save();
} catch (RepositoryException e) {

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);
for (Class<?> clazz: classesAnnotated ){
if (RootItem.class.isAssignableFrom(clazz) && clazz.isAnnotationPresent(RootNode.class)) {
String[] values = clazz.getAnnotation(RootNode.class).value();
log.debug("loading class {} with values {} ", clazz, values );
for (String value: values)
classMap.put(value, (Class<? extends RootItem>) clazz);
typeMap.put((Class<? extends RootItem>) clazz, values[0]);
if (RootItem.class.isAssignableFrom(clazz)) {
String value = clazz.getAnnotation(RootNode.class).value();
log.debug("loading class {} with value {} ", clazz, value );
classMap.put(value, (Class<? extends RootItem>) clazz);
typeMap.put((Class<? extends RootItem>) clazz, value);
}
}
}

View File

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

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

View File

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

View File

@ -4,9 +4,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import jakarta.inject.Singleton;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
@ -53,14 +52,7 @@ public class VersionHandler {
logger.warn("cannot checkoutNode content node",e);
}
}
public Version getCurrentVersion(Node node) throws RepositoryException{
Session session = node.getSession();
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
VersionManager versionManager = session.getWorkspace().getVersionManager();
return versionManager.getBaseVersion(contentNode.getPath());
}
public List<Version> getContentVersionHistory(Node node) {
try {
Session session = node.getSession();
@ -76,17 +68,10 @@ public class VersionHandler {
logger.debug("version name {} with nodeType {}",version.getName(),version.getPrimaryNodeType().getName());
}
return versions;
}catch(Throwable e ) {
}catch(Exception e ) {
logger.warn("cannot get version history content node",e);
return Collections.emptyList();
}
}
public void removeContentVersion(Node node, String versionName) throws RepositoryException{
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
VersionHistory history = contentNode.getSession().getWorkspace().getVersionManager().getVersionHistory(contentNode.getPath());
history.removeVersion(versionName);
}
}

View File

@ -7,18 +7,10 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
public interface ContentHandler {
boolean requiresInputStream();
default void initiliseSpecificContent(InputStream is, String fileName, String mimeType, long size) throws Exception{
throw new UnsupportedOperationException();
}
default void initiliseSpecificContent(String fileName, String mimeType) throws Exception {
throw new UnsupportedOperationException();
}
void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception;
Content getContent();
AbstractFileItem buildItem(String name, String description, String login);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,14 +10,13 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import jakarta.inject.Singleton;
import javax.inject.Singleton;
import javax.jcr.ItemExistsException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.util.Text;
import org.apache.jackrabbit.value.BinaryValue;
import org.apache.jackrabbit.value.BooleanValue;
@ -50,62 +49,52 @@ public class Item2NodeConverter {
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 {
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
Node newNode = null;
if (uuid==null)
newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
else ((NodeImpl)parentNode).addNodeWithUuid(item.getName(), primaryType, uuid);
fillNode(newNode, item);
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
//newNode.setPrimaryType(primaryType);
for (Field field : retrieveAllFields(item.getClass())){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
if (attribute.isReadOnly()) continue;
field.setAccessible(true);
try{
//Class<?> returnType = field.getType();
logger.trace("creating node - added field {}",field.getName());
Values values = getObjectValue(field.getType(), field.get(item));
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.warn("error setting value for attribute {}: {}",attribute.value(), e.getMessage());
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
if (nodeAttribute.isReadOnly()) continue;
String nodeName = nodeAttribute.value();
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Object obj = field.get(item);
if (obj!=null)
iterateItemNodeAttributeFields(obj, newNode, nodeName);
} catch (Exception e ) {
logger.debug("error setting value",e);
}
}
}
return newNode;
} catch (RepositoryException e) {
logger.error("error writing repository",e);
throw new RuntimeException(e);
}
}
public <T extends RootItem> Node getNode(Node parentNode, T item){
return getNode(parentNode, item, null);
}
private <T extends RootItem> void fillNode(Node newNode, T item) throws RepositoryException {
for (Field field : retrieveAllFields(item.getClass())){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
if (attribute.isReadOnly()) continue;
field.setAccessible(true);
try{
//Class<?> returnType = field.getType();
logger.trace("creating node - added field {}",field.getName());
Values values = getObjectValue(field.getType(), field.get(item));
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.warn("error setting value for attribute {}: {}",attribute.value(), e.getMessage());
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
if (nodeAttribute.isReadOnly()) continue;
String nodeName = nodeAttribute.value();
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Object obj = field.get(item);
if (obj!=null)
iterateItemNodeAttributeFields(obj, newNode, nodeName);
} catch (Exception e ) {
logger.debug("error setting value",e);
}
}
}
}
@SuppressWarnings("unchecked")
private void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
Node newNode;
@ -126,7 +115,6 @@ public class Item2NodeConverter {
@SuppressWarnings("rawtypes")
Class returnType = field.getType();
Values values = getObjectValue(returnType, field.get(object));
if (values == null) continue;
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
@ -157,28 +145,13 @@ public class Item2NodeConverter {
iterateItemNodeAttributeFields(obj,newNode, field.getName()+(i++));
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
if (nodeAttribute.isReadOnly()) continue;
String subNodeName = nodeAttribute.value();
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Object obj = field.get(object);
if (obj!=null)
iterateItemNodeAttributeFields(obj, newNode, subNodeName);
} catch (Exception e ) {
logger.debug("error setting value",e);
}
}
}
}
@SuppressWarnings({ "rawtypes" })
public static Values getObjectValue(Class returnType, Object value) throws Exception{
if (value== null) return null;
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
if (returnType.equals(Calendar.class)) return new Values(new DateValue((Calendar) value));
@ -215,9 +188,8 @@ public class Item2NodeConverter {
public <F extends AbstractFileItem> void replaceContent(Node node, F item, ItemAction action){
try {
String primaryType = item.getClass().getAnnotation(RootNode.class).value()[0];
node.setPrimaryType(primaryType);
node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value());
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
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_ACTION.toString(), action.name());
replaceContentNodeInternal(contentNode, item.getContent().getClass(),item.getContent());
for (Field field : retrieveAllFields(item.getContent().getClass())){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
if (attribute.isReadOnly()) continue;
field.setAccessible(true);
try{
//Class<?> returnType = field.getType();
Values values = getObjectValue(field.getType(), field.get(item.getContent()));
if (values.isMulti()) contentNode.setProperty(attribute.value(), values.getValues() );
else contentNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.debug("error setting value for attribute "+attribute.value(),e);
}
}
}
} catch (RepositoryException e) {
logger.error("error writing repository",e);
@ -235,41 +220,7 @@ public class Item2NodeConverter {
}
}
//VALID ONLY FOR CONTENT
public void replaceContentNodeInternal(Node node, Class<?> clazz, Object instance) {
for (Field field : retrieveAllFields(clazz)){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
if (attribute.isReadOnly()) continue;
field.setAccessible(true);
try{
//Class<?> returnType = field.getType();
Values values = getObjectValue(field.getType(), field.get(instance));
if (values.isMulti()) node.setProperty(attribute.value(), values.getValues() );
else node.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.debug("error setting value for attribute "+attribute.value(),e);
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
if (nodeAttribute.isReadOnly()) continue;
String subNodeName = nodeAttribute.value();
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Object obj = field.get(instance);
if (obj!=null)
iterateItemNodeAttributeFields(obj, node, subNodeName);
} catch (Exception e ) {
logger.debug("error setting value",e);
}
}
}
}
public void updateHidden(Node node, Boolean hidden,String login) throws RepositoryException {
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
node.setProperty(NodeProperty.HIDDEN.toString(), hidden);
@ -280,7 +231,6 @@ public class Item2NodeConverter {
node.setProperty(NodeProperty.DESCRIPTION.toString(), description);
}
@SuppressWarnings("unchecked")
public void updateOwnerOnSubTree(Node node, String owner) throws RepositoryException, BackendGenericError {
Class<? extends Item> classToHandle = (Class<? extends Item>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return;

View File

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

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
@ -41,15 +42,12 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
import org.reflections.Configuration;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.inject.Singleton;
@Singleton
@SuppressWarnings("rawtypes")
public class Node2ItemConverter {
@ -59,11 +57,11 @@ public class Node2ItemConverter {
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, 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")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
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);
}
@ -85,7 +83,7 @@ public class Node2ItemConverter {
setGenericFields(node.getFrozenNode(), Content.class, null, content);
return content;
}
public Message getMessageItem(Node node) throws RepositoryException{
if (!(node.getPrimaryNodeType().getName().equals("nthl:itemSentRequest")
|| node.getPrimaryNodeType().getName().equals("nthl:itemSentRequestSH")))
@ -97,7 +95,7 @@ public class Node2ItemConverter {
}catch (Throwable e) {
msg.setWithAttachments(false);
}
setRootItemCommonFields(node, Collections.emptyList(), Message.class, msg);
return msg;
}
@ -106,7 +104,7 @@ public class Node2ItemConverter {
private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{
T item;
try {
item = classToHandle.getDeclaredConstructor().newInstance();
item = classToHandle.newInstance();
}catch (Exception e) {
throw new BackendGenericError(e);
}
@ -131,7 +129,7 @@ public class Node2ItemConverter {
item.setExternalManaged(false);
}
item.setLocked(node.isLocked());
setRootItemCommonFields(node, excludes, classToHandle, item);
@ -139,7 +137,7 @@ public class Node2ItemConverter {
return item;
}
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
if(node==null) return false;
@ -148,16 +146,16 @@ public class Node2ItemConverter {
private <T extends RootItem> void setRootItemCommonFields(Node node, List<String> excludes, Class<T> classToHandle, T instance) throws RepositoryException{
try{
instance.setParentId(node.getParent().getIdentifier());
instance.setParentPath(node.getParent().getPath());
}catch (Throwable e) {
logger.trace("Root node doesn't have a parent");
}
instance.setRelatedNode(node);
instance.setId(node.getIdentifier());
instance.setName(Text.unescapeIllegalJcrChars(node.getName()));
@ -168,11 +166,21 @@ public class Node2ItemConverter {
setGenericFields(node, classToHandle, excludes, instance);
}
private <T> void setGenericFields(Node node, Class<T> classToHandle,List<String> excludes, T instance){
for (Field field : retrieveAllFields(classToHandle)){
if (field.isAnnotationPresent(Attribute.class)){
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)){
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
//for now it excludes only first level node
@ -187,7 +195,7 @@ public class Node2ItemConverter {
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} node",fieldNodeName);
} catch (Exception e ) {
logger.trace("error setting value",e);
logger.debug("error setting value",e);
}
@ -196,145 +204,100 @@ public class Node2ItemConverter {
}
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)){
if (field.isAnnotationPresent(Attribute.class)){
setAttributeFieldCheckingDefault(field, obj, node);
} else if (field.isAnnotationPresent(MapAttribute.class)){
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
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());
Attribute attribute = field.getAnnotation(Attribute.class);
field.setAccessible(true);
try{
Node fieldNode = node.getNode(fieldNodeName);
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
field.set(obj, iterateNodeAttributeFields(field.getType(), fieldNode));
Class returnType = field.getType();
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
}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 ) {
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());
field.setAccessible(true);
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
Map<String, Object> mapToset = new HashMap<String, Object>();
PropertyIterator iterator = node.getProperties();
if (iterator!=null) {
while (iterator.hasNext()){
Property prop = iterator.nextProperty();
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
try{
logger.trace("adding {} in the map",prop.getName());
mapToset.put(prop.getName(), getPropertyValue(prop));
}catch(PathNotFoundException e){
logger.warn("the property {} is not mapped",prop.getName());
} catch (Exception e ) {
logger.debug("error setting value {}",e.getMessage());
}
}
}
field.set(obj, mapToset);
} 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());
field.setAccessible(true);
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
Class listType = field.getAnnotation(ListNodes.class).listClass();
Map<String, Class> subTypesMap = Collections.emptyMap();
if (!typeToSubtypeMap.containsKey(listType)) {
Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName());
Reflections reflections = new Reflections(config);
Set<Class> subTypes = reflections.getSubTypesOf(listType);
if (subTypes.size()>0) {
subTypesMap = new HashMap<>();
for (Class subtype: subTypes)
if (subtype.isAnnotationPresent(AttributeRootNode.class)) {
AttributeRootNode attributeRootNode = (AttributeRootNode)subtype.getAnnotation(AttributeRootNode.class);
subTypesMap.put(attributeRootNode.value(), subtype);
}
} else logger.trace("no subtypes found for {}",listType.getName());
typeToSubtypeMap.put(listType, subTypesMap);
} else {
logger.info("subtypes already found in cache");
subTypesMap = typeToSubtypeMap.get(listType);
}
List<Object> toSetList = new ArrayList<>();
NodeIterator iterator = node.getNodes();
while (iterator.hasNext()){
Node currentNode = iterator.nextNode();
String primaryType = currentNode.getPrimaryNodeType().getName();
logger.trace("the current node {} has a list",currentNode.getName());
if (!include.isEmpty() && !primaryType.startsWith(include))
continue;
if (!exclude.isEmpty() && primaryType.startsWith(exclude))
continue;
if (subTypesMap.containsKey(primaryType))
toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode));
else toSetList.add(iterateNodeAttributeFields(listType, currentNode));
}
if (toSetList.size()!=0) field.set(obj, toSetList);
}
}
return obj;
}
private <T> void setMapAttribute(Field field, T instance, Node node) throws Exception{
field.setAccessible(true);
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
Map<String, Object> mapToset = new HashMap<String, Object>();
PropertyIterator iterator = node.getProperties();
if (iterator!=null) {
while (iterator.hasNext()){
Property prop = iterator.nextProperty();
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
try{
logger.trace("adding {} in the map",prop.getName());
mapToset.put(prop.getName(), getPropertyValue(prop));
}catch(PathNotFoundException e){
logger.trace("the property {} is not mapped",prop.getName());
} catch (Exception e ) {
logger.trace("error setting value {}",e);
}
}
}
field.set(instance, mapToset);
}
@SuppressWarnings("unchecked")
private <T> void setListNode(Field field, T instance, Node node) throws Exception{
field.setAccessible(true);
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
Class listType = field.getAnnotation(ListNodes.class).listClass();
Map<String, Class> subTypesMap = Collections.emptyMap();
if (!typeToSubtypeMap.containsKey(listType)) {
Configuration config = new ConfigurationBuilder().forPackages(listType.getPackage().getName());
Reflections reflections = new Reflections(config);
Set<Class> subTypes = reflections.getSubTypesOf(listType);
if (subTypes.size()>0) {
subTypesMap = new HashMap<>();
for (Class subtype: subTypes)
if (subtype.isAnnotationPresent(AttributeRootNode.class)) {
AttributeRootNode attributeRootNode = (AttributeRootNode)subtype.getAnnotation(AttributeRootNode.class);
subTypesMap.put(attributeRootNode.value(), subtype);
}
} else logger.trace("no subtypes found for {}",listType.getName());
typeToSubtypeMap.put(listType, subTypesMap);
} else {
logger.debug("subtypes already found in cache");
subTypesMap = typeToSubtypeMap.get(listType);
}
List<Object> toSetList = new ArrayList<>();
NodeIterator iterator = node.getNodes();
while (iterator.hasNext()){
Node currentNode = iterator.nextNode();
String primaryType = currentNode.getPrimaryNodeType().getName();
logger.trace("the current node {} has a list",currentNode.getName());
if (!include.isEmpty() && !primaryType.startsWith(include))
continue;
if (!exclude.isEmpty() && primaryType.startsWith(exclude))
continue;
if (subTypesMap.containsKey(primaryType))
toSetList.add(iterateNodeAttributeFields(subTypesMap.get(primaryType), currentNode));
else toSetList.add(iterateNodeAttributeFields(listType, currentNode));
}
if (toSetList.size()!=0) field.set(instance, toSetList);
}
private <T> void setAttributeFieldCheckingDefault(Field field, T instance, Node node) {
Attribute attribute = field.getAnnotation(Attribute.class);
field.setAccessible(true);
try{
Object propValue;
Class<?> returnType = field.getType();
if (node.hasProperty(attribute.value())) {
propValue = getPropertyValue(returnType, node.getProperty(attribute.value()));
if (!attribute.defaultValue().isEmpty() && propValue==null )
propValue = returnType.cast(attribute.defaultValue());
field.set(instance, propValue);
logger.trace("retrieve item - added field {}",field.getName());
} else if (!attribute.defaultValue().isEmpty()){
propValue = returnType.cast(attribute.defaultValue());
field.set(instance, propValue);
logger.trace("retrieve item - setting default for field {}",field.getName());
} else
logger.trace("property not found for field {}",field.getName());
} catch (Exception e ) {
logger.debug("error setting value for property {} ",attribute.value());
}
}
@SuppressWarnings({ "unchecked" })
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
if (returnType.equals(String.class)) return prop.getString();

View File

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

View File

@ -1,10 +1,7 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.util.Map;
import java.util.Objects;
import org.gcube.common.storagehub.model.Metadata;
import org.gcube.common.storagehub.model.items.nodes.PayloadBackend;
import org.gcube.common.storagehub.model.plugins.PluginParameters;
public class FolderCreationParameters extends CreateParameters {
@ -12,8 +9,8 @@ public class FolderCreationParameters extends CreateParameters {
private String name;
private String description="";
private boolean hidden = false;
private PayloadBackend backend;
private String externalPluginName = null;
private PluginParameters externalPluginParameters = null;
protected FolderCreationParameters() {}
@ -29,8 +26,16 @@ public class FolderCreationParameters extends CreateParameters {
return hidden;
}
public PayloadBackend getBackend() {
return backend;
public boolean isExternal() {
return externalPluginName!=null;
}
public String getPluginName(String name) {
return this.externalPluginName;
}
public PluginParameters getPluginParameters() {
return externalPluginParameters;
}
@Override
@ -65,8 +70,8 @@ public class FolderCreationParameters extends CreateParameters {
return this;
}
public BackendCreationBuilder onRepository(String pluginName) {
return new BackendCreationBuilder(pluginName, this);
public ExternalFolderCreationBuilder onRepository(String pluginName) {
return new ExternalFolderCreationBuilder(pluginName, this);
}
public FolderCreationBuilder hidden(boolean hidden) {
@ -76,26 +81,19 @@ public class FolderCreationParameters extends CreateParameters {
}
public static class BackendCreationBuilder {
public static class ExternalFolderCreationBuilder {
FolderCreationBuilder cb;
String plugin;
protected BackendCreationBuilder(String pluginName, FolderCreationBuilder cb) {
this.cb = cb;
this.plugin = pluginName;
protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
this.cb.parameters.externalPluginName = pluginName;
}
public FolderCreationBuilder withParameters(Map<String, Object> params){
this.cb.parameters.backend = new PayloadBackend(plugin, new Metadata(params));
public FolderCreationBuilder withParameters(PluginParameters params){
this.cb.parameters.externalPluginParameters = params;
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.Executors;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.SimpleCredentials;
import javax.servlet.ServletContext;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.gcube.common.security.ContextBean;
import org.gcube.common.security.ContextBean.Type;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
@Singleton
public class VREManager {
@ -33,7 +39,8 @@ public class VREManager {
private Map<String, VRE> vreMap = new HashMap<>();
StoragehubRepository repository = StoragehubRepository.repository;
@Inject
RepositoryInitializer repository;
@Inject
Node2ItemConverter node2Item;
@ -42,12 +49,19 @@ public class VREManager {
PathUtil pathUtil;
@Inject
GroupManagerDelegate groupHandler;
GroupHandler groupHandler;
ExecutorService executor = Executors.newFixedThreadPool(5);
private synchronized VRE getVRE(String completeName) {
SimpleCredentials credentials;
@Inject
public VREManager(ServletContext context) {
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
}
public synchronized VRE getVRE(String completeName) {
logger.trace("requesting VRE {}",completeName);
if (vreMap.containsKey(completeName))
return vreMap.get(completeName);
@ -60,26 +74,36 @@ public class VREManager {
logger.trace("inserting VRE {}",vreFolder.getTitle());
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
else {
VRE toReturn = new VRE(vreFolder, repository.getRepository(), Constants.JCR_CREDENTIALS, node2Item, executor);
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, node2Item, executor);
vreMap.put(vreFolder.getTitle(), toReturn);
return toReturn;
}
}
public String retrieveGroupNameFromContext(String context) throws StorageHubException{
ContextBean bean = new ContextBean(context);
public synchronized VRE getVreFolderItem(JackrabbitSession ses, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
return 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);
if (vre!=null) return vre;
else {
Node vreFolderNode = groupHandler.getFolderNodeRelatedToGroup(ses, groupName);
Item vreFolder = node2Item.getItem(vreFolderNode, excludes);
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;
import jakarta.inject.Singleton;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.expressions.Expression;

View File

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

View File

@ -5,7 +5,7 @@ import java.text.SimpleDateFormat;
import java.util.List;
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.date.Before;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List;
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.logical.And;

View File

@ -1,6 +1,6 @@
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.logical.ISDescendant;

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List;
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.logical.Or;

View File

@ -1,6 +1,6 @@
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.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 javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
@ -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.types.ACLList;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.handlers.ACLHandler;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
@ -38,23 +50,8 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.servlet.ServletContext;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("items")
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
@ -62,32 +59,27 @@ public class ACLManager extends Impersonable {
private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
StoragehubRepository repository = StoragehubRepository.repository;
@Inject
ACLHandler aclHandler;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@RequestScoped
@PathParam("id")
String id;
@Inject
AuthorizationChecker authChecker;
@Inject
PathUtil pathUtil;
@Context
ServletContext context;
@Inject Node2ItemConverter node2Item;
@Inject UnshareHandler unshareHandler;
@Inject ACLManagerInterface aclManagerDelegate;
/**
* returns the AccessType for all the users in a shared folder
*
@ -98,13 +90,13 @@ public class ACLManager extends Impersonable {
@Path("{id}/acls")
@Produces(MediaType.APPLICATION_JSON)
public ACLList getACL() {
InnerMethodName.set("getACLById");
InnerMethodName.instance.set("getACLById");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
return new ACLList(aclManagerDelegate.getByItem(item, ses));
return new ACLList(aclManagerDelegate.get(item, ses));
}catch(RepositoryException re){
log.error("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)
@Path("{id}/acls")
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
InnerMethodName.set("setACLById");
InnerMethodName.instance.set("setACLById");
Session ses = null;
try {
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);
Item item = node2Item.getItem(node, Excludes.ALL);
@ -153,25 +145,28 @@ public class ACLManager extends Impersonable {
throw new UserNotAuthorizedException("owner acl cannot be changed");
SharedFolder folder = (SharedFolder) item;
authChecker.checkAdministratorControl(ses, currentUser, folder);
if (folder.isVreFolder()) {
if (accessType==AccessType.ADMINISTRATOR) throw new InvalidCallParameters("a VRE admin cannot be changed with this method");
if (item instanceof VreFolder || folder.isVreFolder())
throw new InvalidCallParameters("acls in vreFolder cannot be updated with this method");
if (!user.equals(folder.getTitle())) throw new InvalidCallParameters("the groupId in the argument is different to the one of the VREFolder");
NodeIterator sharedSet = node.getSharedSet();
boolean found = false;
while (sharedSet.hasNext() && !found) {
Node current = sharedSet.nextNode();
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
found = true;
} else {
NodeIterator sharedSet = node.getSharedSet();
boolean found = false;
while (sharedSet.hasNext() && !found) {
Node current = sharedSet.nextNode();
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
found = true;
}
if (!found)
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
}
if (!found)
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
aclManagerDelegate.update(user, node, accessType, ses);
aclManagerDelegate.update(user, folder, accessType, ses);
}catch(RepositoryException re){
log.error("jcr error extracting archive", re);
throw new WebApplicationException(new BackendGenericError("jcr error setting acl", re));
@ -202,21 +197,21 @@ public class ACLManager extends Impersonable {
@Consumes(MediaType.TEXT_PLAIN)
@Path("{id}/acls/{user}")
public void removeACL(@PathParam("user") String user) {
InnerMethodName.set("removeACLById");
InnerMethodName.instance.set("removeACLById");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
if (!(item instanceof SharedFolder))
throw new InvalidItemException("the item is not a shared folder");
if (item instanceof VreFolder || ((SharedFolder) item).isVreFolder())
throw new InvalidCallParameters("acls in vreFolder cannot be removed with this method");
authChecker.checkAdministratorControl(ses, currentUser, (SharedFolder) item);
unshareHandler.unshare(ses, Collections.singleton(user), node, currentUser);
@ -236,11 +231,11 @@ public class ACLManager extends Impersonable {
@GET
@Path("{id}/acls/write")
public Boolean canWriteInto() {
InnerMethodName.set("canWriteIntoFolder");
InnerMethodName.instance.set("canWriteIntoFolder");
Session ses = null;
Boolean canWrite = false;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
if (!(item instanceof FolderItem))

View File

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

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.VREMANAGER_ROLE;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.Query;
import org.apache.jackrabbit.api.security.user.QueryBuilder;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.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.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.services.delegates.GroupManagerDelegate;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.vres.VRE;
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
@ -31,52 +76,65 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("groups")
@Singleton
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class GroupManager {
@Context ServletContext context;
@Inject
TrashHandler trashHandler;
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
GroupManagerDelegate groupHandler;
VREManager vreManager;
@Inject
GroupHandler groupHandler;
@Inject
Node2ItemConverter node2Item;
@Inject
PathUtil pathUtil;
@Inject
AuthorizationChecker authChecker;
@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getGroups(){
InnerMethodName.set("getGroups");
InnerMethodName.instance.set("getGroups");
JackrabbitSession session = null;
List<String> groups= new ArrayList<>();
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groups = groupHandler.getGroups(session);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(Group.class);
}
});
while (result.hasNext()) {
Authorizable group = result.next();
log.info("group {} found",group.getPrincipal().getName());
groups.add(group.getPrincipal().getName());
}
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
@ -90,14 +148,32 @@ public class GroupManager {
@POST
@Path("")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner, @FormDataParam("useDefaultStorage") @DefaultValue("true") boolean useDefaultStorage){
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner){
InnerMethodName.instance.set("createGroup");
InnerMethodName.set("createGroup");
JackrabbitSession session = null;
String groupId = null;
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();
}catch(StorageHubException se) {
log.error("error creating group {}", group, se);
@ -109,19 +185,37 @@ public class GroupManager {
if (session!=null)
session.logout();
}
return group;
return groupId;
}
@DELETE
@Path("{group}")
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteGroup(@PathParam("group") String group){
InnerMethodName.set("deleteGroup");
InnerMethodName.instance.set("deleteGroup");
JackrabbitSession session = null;
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();
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
@ -134,32 +228,51 @@ 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
@Path("{id}/admins")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
InnerMethodName.set("addAdmin");
InnerMethodName.instance.set("addAdmin");
JackrabbitSession session = null;
try {
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)) &&
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser))
throw new UserNotAuthorizedException();
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)session).getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User authUser = (User)usrManager.getAuthorizable(userId);
if (group ==null)
throw new InvalidCallParameters("invalid group "+groupId);
if (authUser ==null)
throw new InvalidCallParameters("invalid user "+userId);
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groupHandler.addAdministratorToGroup(session, groupId, userId);
if (!group.isMember(authUser))
throw new InvalidCallParameters("user "+userId+" is not in the group "+groupId);
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
Principal principal = AccessControlUtils.getPrincipal(session, userId);
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(vreFolder.getPath(), acls);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
@ -171,8 +284,6 @@ public class GroupManager {
if (session!=null)
session.logout();
}
}
@DELETE
@ -180,23 +291,35 @@ public class GroupManager {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){
InnerMethodName.set("removeAdmin");
InnerMethodName.instance.set("removeAdmin");
JackrabbitSession session = null;
try {
Objects.nonNull(groupId);
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)) &&
!groupHandler.getGroupAdministators(session, groupId).contains(currentUser))
throw new UserNotAuthorizedException();
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groupHandler.removeAdministratorFromGroup(session, groupId, userId);
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
AccessControlEntry toRemove = null;
for (AccessControlEntry acl: acls.getAccessControlEntries())
if (acl.getPrincipal().getName().equals(userId)) {
toRemove = acl;
break;
}
acls.removeAccessControlEntry(toRemove);
acm.setPolicy(vreFolder.getPath(), acls);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
@ -204,7 +327,7 @@ public class GroupManager {
}catch(Throwable re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re));
} finally {
}finally {
if (session!=null)
session.logout();
}
@ -215,19 +338,37 @@ public class GroupManager {
@Produces(MediaType.APPLICATION_JSON)
public List<String> getAdmins(@PathParam("groupId") String groupId){
InnerMethodName.set("getAdmins");
List<String> users = new ArrayList<>();
InnerMethodName.instance.set("getAdmins");
String login = AuthorizationProvider.instance.get().getClient().getId();
JackrabbitSession session = null;
List<String> users = new ArrayList<>();
try {
session = (JackrabbitSession) repository.getRepository().login(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 ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable re ){
log.error("jcr error getting admins", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting admins", re));
} finally {
}catch(Exception re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
}
@ -239,29 +380,41 @@ public class GroupManager {
@PUT
@Path("{id}/users")
@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){
InnerMethodName.set("addUserToGroup");
InnerMethodName.instance.set("addUserToGroup");
JackrabbitSession session = null;
boolean success = false;
try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)))
if (!isInfraManager() && !isValidGroupForContext(groupId))
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User user = (User)usrManager.getAuthorizable(userId);
if (user==null)
throw new InvalidCallParameters("user "+userId+" not exists");
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
groupHandler.addUserToGroup(session, userId, groupId);
success = true;
if (group.isMember(user))
throw new InvalidCallParameters("user "+userId+" is already member of group "+groupId);
this.internalAddUserToGroup(session, group, user);
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 adding user to group", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error adding user to group", re));
} finally {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
}
@ -269,25 +422,43 @@ public class GroupManager {
return success;
}
private boolean internalAddUserToGroup(JackrabbitSession session, Group group, User user) throws RepositoryException, StorageHubException {
boolean success = group.addMember(user);
session.save();
String folderName = group.getPrincipal().getName();
Node folder = groupHandler.getFolderNodeRelatedToGroup(session, folderName);
String userPath = Paths.append(pathUtil.getVREsPath(user.getPrincipal().getName(), session), folderName).toPath();
log.debug("creating folder in user path {} from {}", userPath, folder.getPath() );
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
try {
session.getNode(userPath);
log.debug("the new folder exists ({}) ", userPath );
}catch (PathNotFoundException e) {
log.debug("the new folder doesn't exists ({}) ", userPath );
}
return success;
}
@DELETE
@Path("{groupId}/users/{userId}")
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE})
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
InnerMethodName.set("removeUserFromGroup");
InnerMethodName.instance.set("removeUserFromGroup");
JackrabbitSession session = null;
boolean success = false;
try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)))
if (!isValidGroupForContext(groupId) && !isInfraManager())
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();
}catch(StorageHubException she ){
@ -307,25 +478,39 @@ public class GroupManager {
@GET
@Path("{groupId}/users")
@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){
InnerMethodName.set("getUsersOfGroup");
InnerMethodName.instance.set("getUsersOfGroup");
JackrabbitSession session = null;
List<String> users = new ArrayList<>();
try {
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId)))
if (!isValidGroupForContext(groupId) && !isInfraManager())
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
users = groupHandler.getUsersBelongingToGroup(session, groupId);
}catch (StorageHubException e) {
log.error("error getting users", e);
GXOutboundErrorResponse.throwException(e);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
Iterator<Authorizable> it = group.getMembers();
while (it.hasNext()) {
Authorizable user = it.next();
users.add(user.getPrincipal().getName());
}
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error getting users", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting users", re));
} finally {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
}
@ -333,11 +518,51 @@ public class GroupManager {
return users;
}
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType, String owner ) throws Exception{
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
String name = groupId;
String currentScope = ScopeProvider.instance.get();
ScopeBean bean = new ScopeBean(currentScope);
while (!bean.is(Type.INFRASTRUCTURE)) {
bean = bean.enclosingScope();
}
String root = bean.toString().replaceAll("/", "");
String displayName = groupId.replaceAll(root+"-[^\\-]*\\-(.*)", "$1");
log.info("creating vreFolder with name {} and title {} and owner {}", name, displayName, owner);
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).description( "VREFolder for "+groupId).author(owner).on(sharedRootNode.getIdentifier()).with(session).build();
Node folder= Utils.createFolderInternally(folderParameters, null);
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
folder.setProperty(NodeProperty.TITLE.toString(), name);
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), displayName);
session.save();
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
/*Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session, AuthorizationProvider.instance.get().getClient().getId()), adminPrivileges );
*/
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,groupId), usersPrivileges );
acm.setPolicy(folder.getPath(), acls);
log.debug("vrefolder created with id {}",folder.getIdentifier());
}
private boolean isValidGroupForContext(String group){
String currentContext = SecretManagerProvider.get().getContext();
String currentContext = ScopeProvider.instance.get();
String expectedGroupId= currentContext.replace("/", "-").substring(1);
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 org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.ClientInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
@Path("")
public abstract class Impersonable {
Logger log = LoggerFactory.getLogger(Impersonable.class);
String currentUser = null;
String currentUser;
@RequestScoped
@Inject
public void setCurrentUser(@Context final HttpServletRequest request) {
String impersonate = request!=null ? request.getParameter("impersonate") : null ;
Owner owner = SecretManagerProvider.get().getOwner();
if(impersonate!=null && owner.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
ClientInfo info = AuthorizationProvider.instance.get().getClient();
if(impersonate!=null && info.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
this.currentUser = impersonate;
} 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.Set;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
@ -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.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
@ -45,19 +58,6 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.servlet.ServletContext;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("items")
@ -68,7 +68,7 @@ public class ItemSharing extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemSharing.class);
private final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@ -79,10 +79,10 @@ public class ItemSharing extends Impersonable{
@Context
ServletContext context;
@Inject
AuthorizationChecker authChecker;
@Inject
PathUtil pathUtil;
@ -92,15 +92,15 @@ public class ItemSharing extends Impersonable{
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@SuppressWarnings("unchecked")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@POST
@Path("{id}/share")
public String shareWithMap(@FormParam("mapUserPermission") String mapUserPermissionString, @FormParam("defaultAccessType") String defaultAccessTypeString){
InnerMethodName.set("shareFolder");
InnerMethodName.instance.set("shareFolder");
HashMap<String,String> mapUserPermission;
Session ses = null;
String toReturn = null;
try{
@ -111,17 +111,17 @@ public class ItemSharing extends Impersonable{
}
AccessType defaultAccessType;
try {
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
}catch (IllegalArgumentException e) {
throw new InvalidCallParameters("invalid default accessType");
}
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
if (mapUserPermission==null || mapUserPermission.isEmpty())
throw new InvalidCallParameters("users is empty");
@ -200,12 +200,13 @@ public class ItemSharing extends Impersonable{
@PUT
@Path("{id}/share")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Deprecated
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
InnerMethodName.set("shareFolder");
InnerMethodName.instance.set("shareFolder");
Session ses = null;
String toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
@ -216,8 +217,6 @@ public class ItemSharing extends Impersonable{
if (users==null || users.isEmpty())
throw new InvalidCallParameters("users is empty");
log.info("shared method called with users {} and default access type {} ", users, accessType.getValue());
Node nodeToShare = ses.getNodeByIdentifier(id);
boolean alreadyShared = false;
@ -251,9 +250,8 @@ public class ItemSharing extends Impersonable{
for (String user : users)
try {
addUserToSharing(sharedFolderNode, ses, user, null, userPrivileges, acls);
log.info("added user {} to the shared node",user);
}catch(Exception e){
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName(),e);
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName());
}
acm.setPolicy(sharedFolderNode.getPath(), acls);
@ -275,9 +273,6 @@ public class ItemSharing extends Impersonable{
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Exception e){
log.error("jcr sharing", e);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error sharing folder", e));
}finally{
if (ses!=null)
ses.logout();
@ -289,7 +284,7 @@ public class ItemSharing extends Impersonable{
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(currentUser))
throw new InvalidItemException("item with id "+id+" cannot be shared");
@ -307,35 +302,30 @@ public class ItemSharing extends Impersonable{
}
private void addUserToSharing(Node sharedFolderNode, Session ses, String user, Item itemToShare, Privilege[] userPrivileges, JackrabbitAccessControlList acls) throws RepositoryException{
try {
String userRootWSId;
String userPath;
if (itemToShare==null) {
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
userRootWSId = ses.getNode(userRootWS).getIdentifier();
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
}
else {
userPath = itemToShare.getPath();
userRootWSId = itemToShare.getParentId();
}
log.info("cloning directory to {} ",userPath);
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), userPath , false);
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
Node usersNode =null;
if (sharedFolderNode.hasNode(NodeConstants.USERS_NAME))
usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
else
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString()));
}catch (Exception e) {
log.error("error sharing node with user {}",user,e);
throw new RepositoryException(e);
String userRootWSId;
String userPath;
if (itemToShare==null) {
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
userRootWSId = ses.getNode(userRootWS).getIdentifier();
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
}
else {
userPath = itemToShare.getPath();
userRootWSId = itemToShare.getParentId();
}
log.info("cloning directory to {} ",userPath);
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), userPath , false);
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
Node usersNode =null;
if (sharedFolderNode.hasNode(NodeConstants.USERS_NAME))
usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
else
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString()));
}
@ -343,12 +333,12 @@ public class ItemSharing extends Impersonable{
@Path("{id}/unshare")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String unshare(@FormDataParam("users") Set<String> users){
InnerMethodName.set("unshareFolder");
InnerMethodName.instance.set("unshareFolder");
Session ses = null;
String toReturn = null;
try {
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);
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
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;
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.inject.Inject;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.compress.archivers.ArchiveException;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.plugins.PluginParameters;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
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.ItemsParameterBuilder;
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
@ -42,60 +41,47 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.inject.Inject;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
@Path("items")
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class ItemsCreator extends Impersonable{
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), })
public class ItemsCreator extends Impersonable {
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
@Context
ServletContext context;
private final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
ItemHandler itemHandler;
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/FOLDER")
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden) {
InnerMethodName.set("createItem(FOLDER)");
InnerMethodName.instance.set("createItem(FOLDER)");
log.info("create folder item called");
Session ses = null;
String toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name).description(description).hidden(hidden).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){
try {
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
.description(description).hidden(hidden).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{
if (ses!=null)
} finally {
if (ses != null)
ses.logout();
}
@ -103,43 +89,33 @@ public class ItemsCreator extends Impersonable{
}
@POST
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE})
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/EXTERNALFOLDER")
public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name,
public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden,
@FormParam("pluginName") String pluginName,
@Context HttpServletRequest request) {
InnerMethodName.set("createItem(EXTERNALFOLDER)");
@FormParam("pluginName") String pluginName, @FormParam("parameters") String pluginParameters) {
InnerMethodName.instance.set("createItem(EXTERNALFOLDER)");
log.info("create folder item called");
Session ses = null;
String toReturn = null;
try{
Iterator<String> paramIt = request.getParameterNames().asIterator();
Iterable<String> iterable = () -> paramIt;
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);
PluginParameters pluginParams = new PluginParameters();
targetStream.filter(v -> v.startsWith("plugin."))
.forEach(v -> pluginParams.add(v.replace("plugin.", ""), request.getParameter(v)));
log.debug("parameters for external folder with plugin {} are {}",pluginName, pluginParams.toString());
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
try {
// TODO
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
.description(description).onRepository(pluginName).withParameters(pluginParams.getParameters()).hidden(hidden).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){
.description(description).onRepository(pluginName).withParameters(null).hidden(hidden).on(id)
.with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
} catch (RepositoryException re) {
log.error("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);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{
if (ses!=null)
} finally {
if (ses != null)
ses.logout();
}
@ -149,144 +125,97 @@ public class ItemsCreator extends Impersonable{
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/URL")
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) {
InnerMethodName.set("createItem(URL)");
public Response createURL(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("value") URL value) {
InnerMethodName.instance.set("createItem(URL)");
log.info("create url called");
Session ses = null;
String toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
try {
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());
}catch(StorageHubException she ){
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{
if (ses!=null)
} finally {
if (ses != null)
ses.logout();
}
return Response.ok(toReturn).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/create/GCUBEITEM")
public String createGcubeItem(@PathParam("id") String id, GCubeItem item) {
InnerMethodName.set("createItem(GCUBEITEM)");
InnerMethodName.instance.set("createItem(GCUBEITEM)");
log.info("create Gcube item called");
Session ses = null;
String toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder().item(item).on(id).with(ses).author(currentUser);
try {
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder()
.item(item).on(id).with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
}catch(StorageHubException she ){
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}catch(Throwable e ){
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{
if (ses!=null)
} finally {
if (ses != null)
ses.logout();
}
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
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/FILE")
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
@FormDataParam("description") String description,
@FormDataParam("file") InputStream file,
@FormDataParam("file") FormDataContentDisposition fileDetail){
InnerMethodName.set("createItem(FILE)");
@FormDataParam("description") String description, @FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {
InnerMethodName.instance.set("createItem(FILE)");
Session ses = null;
String toReturn = null;
try(InputStream is = new BufferedInputStream(file)){
try {
long size = fileDetail.getSize();
log.info("UPLOAD: call started with file size {}",size);
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description(description).stream(file).fileDetails(fileDetail)
.on(id).with(ses).author(currentUser);
log.debug("UPLOAD: item prepared");
toReturn = itemHandler.create(builder.build());
log.debug("UPLOAD: call finished");
}catch(RepositoryException re ){
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name)
.description(description).stream(stream).fileDetails(fileDetail).on(id).with(ses)
.author(currentUser);
toReturn = itemHandler.create(builder.build());
} catch (RepositoryException re) {
log.error("jcr error creating file item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
}catch(StorageHubException she ){
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable e ){
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}finally{
if (ses!=null && ses.isLive()) {
} finally {
if (ses != null && ses.isLive()) {
log.info("session closed");
ses.logout();
}
@ -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
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/ARCHIVE")
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
@FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail){
InnerMethodName.set("createItem(ARCHIVE)");
@FormDataParam("file") InputStream stream, @FormDataParam("file") FormDataContentDisposition fileDetail) {
InnerMethodName.instance.set("createItem(ARCHIVE)");
Session ses = null;
String toReturn = null;
try(InputStream is = new BufferedInputStream(stream)){
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
try {
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(is).fileDetails(fileDetail)
.on(id).with(ses).author(currentUser);
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter
.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);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
}catch(StorageHubException she ){
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable e ){
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally{
if (ses!=null)
} finally {
if (ses != null)
ses.logout();
}
return toReturn;
}
}

View File

@ -1,13 +1,24 @@
package org.gcube.data.access.storagehub.services;
import static org.gcube.common.storagehub.model.Constants.enchriptedPrefix;
import static org.gcube.common.storagehub.model.Constants.versionPrefix;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.ZipOutputStream;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
@ -15,16 +26,39 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.version.Version;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.io.FilenameUtils;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
@ -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.VreFolder;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.common.storagehub.model.service.VersionList;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.types.FolderInfoType;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.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.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.DownloadHandler;
import org.gcube.data.access.storagehub.handlers.PublicLinkHandler;
import org.gcube.data.access.storagehub.handlers.CompressHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.StorageOperationMediator;
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.types.PublicLink;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
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.RequestHeaders;
import jakarta.inject.Inject;
import jakarta.servlet.ServletContext;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
@Path("items")
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@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 final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@RequestScoped
@PathParam("id")
String id;
@ -105,40 +121,35 @@ public class ItemsManager extends Impersonable{
@Inject
AuthorizationChecker authChecker;
@Inject
VersionHandler versionHandler;
@Inject
DownloadHandler downloadHandler;
@Inject
TrashHandler trashHandler;
@Inject PathUtil pathUtil;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject
StorageOperationMediator opMediator;
FolderPluginHandler folderPluginHandler;
@Inject
PublicLinkHandler publicLinkHandler;
CompressHandler compressHandler;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getById(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getById");
InnerMethodName.instance.set("getById");
Session ses = null;
Item toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = node2Item.getItem(node, excludes);
@ -163,11 +174,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/path")
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getByPath");
InnerMethodName.instance.set("getByPath");
Session ses = null;
Item toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
String relativePath = path.startsWith("/")? path.substring(1) : path;
@ -225,7 +236,7 @@ public class ItemsManager extends Impersonable{
@Path("{id}/items/{name}")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
InnerMethodName.set("findChildrenByNamePattern");
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
@ -233,15 +244,15 @@ public class ItemsManager extends Impersonable{
@Path("{id}/items")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
InnerMethodName.set("findChildrenByNamePattern");
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
public ItemList _findChildrenByNamePattern(List<String> excludes, String name){
Session ses = null;
List<Item> toReturn = new ArrayList<>();
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
//NOT using the internal pattern matching of jcr because of title for shared folder
@ -273,24 +284,23 @@ public class ItemsManager extends Impersonable{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@GET
@Path("{id}/children/count")
@Produces(MediaType.APPLICATION_JSON)
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.set("countById");
InnerMethodName.instance.set("countById");
Session ses = null;
Long toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemCount(node, showHidden==null?false:showHidden, itemPredicate );
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -311,15 +321,13 @@ public class ItemsManager extends Impersonable{
@Path("{id}/children")
@Produces(MediaType.APPLICATION_JSON)
public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.set("listById");
InnerMethodName.instance.set("listById");
Session ses = null;
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemList(node, excludes, null, showHidden==null?false:showHidden, itemPredicate);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -341,16 +349,14 @@ public class ItemsManager extends Impersonable{
@Path("{id}/search")
@Produces(MediaType.APPLICATION_JSON)
public ItemList searchItems(@QueryParam("showHidden") Boolean showHidden, @QueryParam("excludeTrashed") Boolean excludeTrashed, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType,@QueryParam("name") String name ){
InnerMethodName.set("search");
InnerMethodName.instance.set("search");
Session ses = null;
List<? extends Item> toReturn = null;
try{
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);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.searchByNameOnFolder(ses, currentUser, authChecker, node, excludes, null, showHidden==null?false:showHidden, excludeTrashed==true?false:excludeTrashed, itemPredicate, name);
toReturn = Utils.searchByNameOnFolder(ses, currentUser, authChecker, ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden,excludeTrashed==true?false:excludeTrashed , nodeType!=null ? ClassHandler.instance().get(nodeType) : null, name);
log.debug("search retrieved {} elements",toReturn.size());
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
@ -373,15 +379,13 @@ public class ItemsManager extends Impersonable{
@Path("{id}/children/paged")
@Produces(MediaType.APPLICATION_JSON)
public ItemList listByIdPaged(@QueryParam("showHidden") Boolean showHidden, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.set("listByIdPaged");
InnerMethodName.instance.set("listByIdPaged");
Session ses = null;
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
ItemTypePredicate itemPredicate = nodeType!=null ? new IncludeTypePredicate(ClassHandler.instance().get(nodeType)) : null;
Node node = ses.getNodeByIdentifier(id);
toReturn = Utils.getItemList(node, excludes, new Range(start, limit),showHidden==null?false:showHidden, itemPredicate);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -401,26 +405,62 @@ public class ItemsManager extends Impersonable{
@GET
@Path("publiclink/{id}")
@AuthorizationControl(allowedUsers={"URIResolver"})
@AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
public Response resolvePublicLink() {
InnerMethodName.set("resolvePubliclink");
InnerMethodName.instance.set("resolvePubliclink");
log.warn("arrived id is {}",id);
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
PublicLink publicLink = publicLinkHandler.resolveEnchriptedId(id);
switch (publicLink.getType()) {
case VOLATILE:
return downloadHandler.downloadFileFromStorageBackend(publicLink.getId(), publicLink.getStorageName());
case VERSIONED:
Item versionedItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT);
return downloadHandler.downloadVersionedItem(ses, currentUser, (AbstractFileItem) versionedItem, publicLink.getVersion(), true);
default:
Item currentItem = node2Item.getItem(publicLink.getId(), ses, Excludes.GET_ONLY_CONTENT);
return downloadHandler.downloadFileItem(ses,(AbstractFileItem) currentItem, currentUser, true);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
String complexId = id;
if (id.startsWith(enchriptedPrefix)) {
String currentScope = ScopeProvider.instance.get();
try {
ScopeBean bean= new ScopeBean(currentScope);
while (!bean.is(Type.INFRASTRUCTURE)) {
bean = bean.enclosingScope();
}
ScopeProvider.instance.set(bean.toString());
complexId = StringEncrypter.getEncrypter().decrypt(new String(Base64.getUrlDecoder().decode(id.replace(enchriptedPrefix, ""))));
}catch(Exception e){
throw new BackendGenericError("invalid public url",e);
}finally {
ScopeProvider.instance.set(currentScope);
}
}
String itemId = complexId;
String versionName = null;
if (complexId.contains(versionPrefix)) {
String[] split = complexId.split(versionPrefix);
itemId = split[0];
versionName = split[1];
}
log.warn("item id to retrieve is {}",itemId);
Node selectedNode;
try {
selectedNode= ses.getNodeByIdentifier(itemId);
}catch (ItemNotFoundException e) {
throw new IdNotFoundException(itemId);
}
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
if (versionName!=null)
return downloadVersionInternal(ses, currentUser, itemId, versionName, false);
else
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
}catch(RepositoryException re ){
log.error("jcr error getting public link", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
@ -438,11 +478,11 @@ public class ItemsManager extends Impersonable{
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}/publiclink")
public URL getPublicLink(@QueryParam("version") String version) {
InnerMethodName.set("getPubliclink");
InnerMethodName.instance.set("getPubliclink");
Session ses = null;
URL toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node selectedNode = ses.getNodeByIdentifier(id);
@ -471,10 +511,28 @@ public class ItemsManager extends Impersonable{
ses.getWorkspace().getLockManager().unlock(selectedNode.getPath());
}*/
String url = null;
String currentScope = ScopeProvider.instance.get();
try {
ScopeBean bean= new ScopeBean(currentScope);
while (!bean.is(Type.INFRASTRUCTURE)) {
bean = bean.enclosingScope();
}
String url = version!=null ? publicLinkHandler.getForVersionedItem(id, version, context):
publicLinkHandler.getForItem(id, context);
ScopeProvider.instance.set(bean.toString());
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);
@ -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
@Path("{id}/publish")
@Produces(MediaType.APPLICATION_JSON)
public String makeFolderPublic(@FormParam("publish") boolean publish){
InnerMethodName.set("makeFolderPublic("+publish+")");
InnerMethodName.instance.set("makeFolderPublic("+publish+")");
Session ses = null;
Item folder= null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath());
@ -520,7 +580,7 @@ public class ItemsManager extends Impersonable{
ses.save();
}catch(RepositoryException re ){
log.error("jcr error publishing folder", re);
log.error("jcr error getting rootSharedFolder", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
@ -537,11 +597,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/rootSharedFolder")
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getRootSharedFolder");
InnerMethodName.instance.set("getRootSharedFolder");
Session ses = null;
Item sharedParent= null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath());
@ -580,11 +640,11 @@ public class ItemsManager extends Impersonable{
@Path("{id}/versions")
@Produces(MediaType.APPLICATION_JSON)
public VersionList getVersions(){
InnerMethodName.set("getVersions");
InnerMethodName.instance.set("getVersions");
Session ses = null;
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node node = ses.getNodeByIdentifier(id);
@ -616,17 +676,13 @@ public class ItemsManager extends Impersonable{
@GET
@Path("{id}/versions/{version}/download")
public Response downloadVersion(@PathParam("version") String versionName){
InnerMethodName.set("downloadSpecificVersion");
InnerMethodName.instance.set("downloadSpecificVersion");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
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 ){
log.error("jcr error downloading version", re);
@ -641,60 +697,56 @@ public class ItemsManager extends Impersonable{
return Response.serverError().build();
}
@DELETE
@Path("{id}/versions/{version}")
public void deleteVersion(@PathParam("version") String versionName){
InnerMethodName.set("deleteVersion");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Node node = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT);
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not a file");
List<Version> versions = versionHandler.getContentVersionHistory(node);
boolean found = false;
for(Version version : versions)
if (version.getName().equals(versionName)) {
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
if (currentVersion)
throw new InvalidCallParameters("current version cannot be removed");
versionHandler.removeContentVersion(node, versionName);
accountingHandler.createVersionDeleted(currentItem.getTitle(), versionName, ses, node, currentUser, false);
ses.save();
found = true;
break;
}
if (!found) throw new InvalidItemException("the version "+versionName+" is not valid or is current version for item "+currentItem.getTitle());
}catch(RepositoryException re ){
log.error("jcr error removing version", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
private Response downloadVersionInternal(Session ses, String login, String id, String versionName, boolean withAccounting) throws RepositoryException, StorageHubException{
Node node = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(node, Excludes.ALL);
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not a file");
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
for (Version version: jcrVersions) {
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
if (version.getName().equals(versionName)) {
Content content = node2Item.getContentFromVersion(version);
FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
log.debug("retrieved storage id is {} with storageBackend {} (stream is null? {})",content.getStorageId(), folderManager.getStorageBackend().getClass().getSimpleName(), streamToWrite==null );
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
String ext = FilenameUtils.getExtension(currentItem.getTitle());
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
if (withAccounting)
accountingHandler.createReadObj(fileName, ses, node, login, true);
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
return Response
.ok(so)
.header("content-disposition","attachment; filename = "+fileName)
.header("Content-Length", content.getSize())
.header("Content-Type", content.getMimeType())
.build();
}
}
throw new InvalidItemException("the version is not valid");
}
@GET
@Path("{id}/anchestors")
@Produces(MediaType.APPLICATION_JSON)
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("getAnchestors");
InnerMethodName.instance.set("getAnchestors");
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
Session ses = null;
List<Item> toReturn = new LinkedList<>();
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(currentNode, excludes);
@ -744,17 +796,50 @@ public class ItemsManager extends Impersonable{
@GET
@Path("{id}/download")
public Response download(@QueryParam("exclude") List<String> excludes){
InnerMethodName.set("downloadById");
InnerMethodName.instance.set("downloadById");
Session ses = null;
Response response = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
final Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Item item = node2Item.getItem(node, null);
if (item instanceof AbstractFileItem){
return downloadHandler.downloadFileItem(ses, (AbstractFileItem) item, currentUser, true);
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
} 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());
}catch(RepositoryException re ){
@ -766,19 +851,40 @@ public class ItemsManager extends Impersonable{
} finally{
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
@Path("{id}/move")
public String move(@FormParam("destinationId") String destinationId){
InnerMethodName.set("move");
InnerMethodName.instance.set("move");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
@ -822,12 +928,11 @@ public class ItemsManager extends Impersonable{
if (movingSharedItemOutside)
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.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
@ -851,20 +956,20 @@ public class ItemsManager extends Impersonable{
@PUT
@Path("{id}/copy")
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
Session ses = null;
String newFileIdentifier = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Node nodeToCopy = ses.getNodeByIdentifier(id);
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));
@ -877,7 +982,6 @@ public class ItemsManager extends Impersonable{
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destination, newFileName);
String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
@ -885,20 +989,22 @@ public class ItemsManager extends Impersonable{
Node newNode = ses.getNode(newPath);
newFileIdentifier = newNode.getIdentifier();
Content contentToCopy = ((AbstractFileItem) item).getContent();
MetaInfo contentInfo = opMediator.copy(contentToCopy, destinationItem.getBackend(), destination.getPath(), uniqueName, currentUser);
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
//replaces content copied with new information
Utils.setContentFromMetaInfo((AbstractFileItem) item, contentInfo);
//TODO: folderHandler.onCopy(source, destination);
if (item instanceof AbstractFileItem) {
FolderManager manager = folderPluginHandler.getFolderManager(item);
((AbstractFileItem) item).getContent().setRemotePath(newPath);
String newStorageID = manager.getStorageBackend().onCopy((AbstractFileItem) item);
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
}
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
String mimeTypeForAccounting = ((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);
@ -926,25 +1032,26 @@ public class ItemsManager extends Impersonable{
@PUT
@Path("{id}/rename")
public Response rename(@FormParam("newName") String newName){
InnerMethodName.set("rename");
InnerMethodName.instance.set("rename");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToMove = ses.getNodeByIdentifier(id);
final Item item = node2Item.getItem(nodeToMove, null);
if (item instanceof SharedFolder)
if (getSharedParentNode(nodeToMove).getIdentifier() == item.getId())
throw new InvalidItemException("root shared folder name cannot be modfied");
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
if (item instanceof SharedFolder)
throw new InvalidItemException("shared folder");
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()))
throw new InvalidItemException("protected folder cannot be renamed");
try {
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
@ -952,7 +1059,10 @@ public class ItemsManager extends Impersonable{
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
@ -984,13 +1094,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/hidden")
public Response setItemAsHidden(Boolean hidden){
InnerMethodName.set("setHidden");
InnerMethodName.instance.set("setHidden");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1029,13 +1139,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/description")
public Response setDescription(String description){
InnerMethodName.set("setDescription");
InnerMethodName.instance.set("setDescription");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1073,13 +1183,13 @@ public class ItemsManager extends Impersonable{
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/metadata")
public Response setMetadata(org.gcube.common.storagehub.model.Metadata metadata){
InnerMethodName.set("updateMetadata");
InnerMethodName.instance.set("updateMetadata");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
@ -1118,15 +1228,15 @@ public class ItemsManager extends Impersonable{
@DELETE
@Path("{id}")
public Response deleteItem(@QueryParam("force") boolean force){
InnerMethodName.set("deleteItem("+force+")");
InnerMethodName.instance.set("deleteItem("+force+")");
Session ses = null;
try{
log.info("removing node with id {}", id);
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
authChecker.checkMoveOpsForProtectedFolders(ses, id);
@ -1139,7 +1249,7 @@ public class ItemsManager extends Impersonable{
if (itemToDelete.isExternalManaged() && !force)
throw new InvalidItemException("External managed Items cannot be moved to Trash");
log.debug("item is trashed? {}", itemToDelete.isTrashed());
if (!itemToDelete.isTrashed() && !force) {
@ -1163,30 +1273,5 @@ public class ItemsManager extends Impersonable{
return Response.ok().build();
}
@Path("{id}/info")
@GET
@Produces(MediaType.APPLICATION_JSON)
public FolderInfoType getFolderInfo() {
InnerMethodName.set("getFolderInfo");
Session ses = null;
try {
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
if (!(item instanceof FolderItem))
throw new InvalidCallParameters("the item is not a folder");
return Utils.getFolderInfo(node);
} catch (RepositoryException re) {
log.error("error getting workspace total size", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} finally {
if (ses != null)
ses.logout();
}
return new FolderInfoType(0, 0);
}
}

View File

@ -5,11 +5,28 @@ import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.User;
@ -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.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.items.nodes.Owner;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.storages.StorageBackend;
import org.gcube.common.storagehub.model.storages.StorageBackendFactory;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.MessageList;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter.Values;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.StorageBackendHandler;
import org.gcube.data.access.storagehub.predicates.IncludeTypePredicate;
import org.gcube.data.access.storagehub.predicates.ItemTypePredicate;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.types.MessageSharable;
import org.gcube.smartgears.annotations.ManagedBy;
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.RequestHeaders;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
@Path("messages")
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
@ -80,8 +75,8 @@ public class MessageManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(MessageManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@ -89,25 +84,25 @@ public class MessageManager extends Impersonable{
@PathParam("id")
String id;
@Context
ServletContext context;
@Inject PathUtil pathUtil;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject TrashHandler trashHandler;
@Inject
StorageBackendHandler storageBackendHandler;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Message getById(){
InnerMethodName.set("getMessageById");
InnerMethodName.instance.set("getMessageById");
Session ses = null;
Message toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
toReturn = node2Item.getMessageItem(messageNode);
checkRights(currentUser, toReturn);
@ -131,28 +126,25 @@ public class MessageManager extends Impersonable{
@DELETE
@Path("{id}")
public void deleteById(){
InnerMethodName.set("deleteMessageById");
InnerMethodName.instance.set("deleteMessageById");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message message = node2Item.getMessageItem(messageNode);
Node personalNode = checkRights(currentUser, message);
if (countSharedSet(messageNode)>1) {
log.debug("removing node message "+personalNode.getPath());
personalNode.remove();
}else {
if (countSharedSet(messageNode)>1)
personalNode.removeShare();
else {
if (message.isWithAttachments()) {
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, itemPredicate);
List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
trashHandler.removeOnlyNodesContent(ses, attachments);
}
messageNode.removeSharedSet();
}
ses.save();
log.debug("removing node message saved");
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -172,17 +164,16 @@ public class MessageManager extends Impersonable{
@Path("{id}/attachments")
@Produces(MediaType.APPLICATION_JSON)
public ItemList getAttachments(){
InnerMethodName.set("getAttachmentsByMessageId");
InnerMethodName.instance.set("getAttachmentsByMessageId");
Session ses = null;
List<Item> attachments = new ArrayList<>();
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem);
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
ItemTypePredicate itemPredicate = new IncludeTypePredicate(AbstractFileItem.class);
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, itemPredicate);
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
@ -204,11 +195,11 @@ public class MessageManager extends Impersonable{
@Path("inbox")
@Produces(MediaType.APPLICATION_JSON)
public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.set("getReceivedMessages");
InnerMethodName.instance.set("getReceivedMessages");
Session ses = null;
List<Message> toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath());
@ -229,11 +220,11 @@ public class MessageManager extends Impersonable{
@Path("sent")
@Produces(MediaType.APPLICATION_JSON)
public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.set("getSentMessages");
InnerMethodName.instance.set("getSentMessages");
Session ses = null;
List<Message> toReturn = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
@ -253,10 +244,10 @@ public class MessageManager extends Impersonable{
@Path("{id}/{prop}")
@Consumes(MediaType.APPLICATION_JSON)
public void setProperty(@PathParam("prop") String property,Object value){
InnerMethodName.set("setPropertyOnMessage("+property+")");
InnerMethodName.instance.set("setPropertyOnMessage("+property+")");
Session ses = null;
try{
ses = repository.getRepository().login(Constants.JCR_CREDENTIALS);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem);
@ -286,7 +277,7 @@ public class MessageManager extends Impersonable{
public String sendMessage(@FormParam("to[]") List<String> addresses,
@FormParam("subject") String subject, @FormParam("body") String body,
@FormParam("attachments[]") List<String> attachments){
InnerMethodName.set("sendMessage");
InnerMethodName.instance.set("sendMessage");
JackrabbitSession ses = null;
String messageId = null;
try{
@ -295,7 +286,7 @@ public class MessageManager extends Impersonable{
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.setAddresses(addresses.toArray(new String[0]));
@ -303,9 +294,6 @@ public class MessageManager extends Impersonable{
message.setBody(body);
message.setName(UUID.randomUUID().toString());
User user = ses.getUserManager().getAuthorizable(currentUser, User.class);
if (user ==null)
throw new InvalidCallParameters("invalid storagehub user: "+currentUser);
Owner owner = new Owner();
owner.setUserId(user.getID());
owner.setUserName(user.getPrincipal().getName());
@ -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);
for (String itemId: attachments) {
@ -363,7 +351,7 @@ public class MessageManager extends Impersonable{
NodeIterator nodeIt = node.getNodes();
while(nodeIt.hasNext()) {
Node child = nodeIt.nextNode();
log.trace("message type "+child.getPrimaryNodeType().getName());
log.info("message type "+child.getPrimaryNodeType().getName());
Message message = node2Item.getMessageItem(child);
if (message == null) {
log.info("message discarded");
@ -408,8 +396,10 @@ public class MessageManager extends Impersonable{
return personalNode== null ? messageNode : personalNode;
}
private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, StorageHubException{
//TODO: move in a common place
@Inject FolderPluginHandler folderPluginHandler;
private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, BackendGenericError{
//it needs to be locked ??
Node nodeToCopy = ((Node)itemToCopy.getRelatedNode());
String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() );
@ -419,15 +409,9 @@ public class MessageManager extends Impersonable{
if (itemToCopy instanceof AbstractFileItem) {
AbstractFileItem newNodeItem = node2Item.getItem(newNode, Excludes.EXCLUDE_ACCOUNTING);
Content contentToCopy = newNodeItem.getContent();
StorageBackendFactory sbf = storageBackendHandler.get(contentToCopy.getPayloadBackend());
StorageBackend sb = sbf.create(contentToCopy.getPayloadBackend());
MetaInfo contentInfo = sb.onCopy(contentToCopy, destination.getPath(), uniqueName);
Utils.setContentFromMetaInfo(newNodeItem, contentInfo);
newNodeItem.getContent().setRemotePath(newPath);
String newStorageID = folderPluginHandler.getDefault().getStorageBackend().onCopy(newNodeItem);
newNodeItem.getContent().setStorageId(newStorageID);
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;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
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.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.Query;
import org.apache.jackrabbit.api.security.user.QueryBuilder;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.service.UsersList;
import org.gcube.common.storagehub.model.types.SHUBUser;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.StorageHubApplicationManager;
import org.gcube.data.access.storagehub.repository.StoragehubRepository;
import org.gcube.data.access.storagehub.services.delegates.UserManagerDelegate;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
@ -25,73 +61,103 @@ import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
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")
@ManagedBy(StorageHubApplicationManager.class)
@ManagedBy(StorageHubAppllicationManager.class)
@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 {
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
@Context ServletContext context;
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
private final StoragehubRepository repository = StoragehubRepository.repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
UserManagerDelegate userHandler;
UnshareHandler unshareHandler;
@Inject
AuthorizationChecker authChecker;
@Inject
TrashHandler trashHandler;
@Inject
GroupHandler groupHandler;
@Inject
PathUtil pathUtil;
@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public UsersList getUsers() {
InnerMethodName.set("getUsers");
public List<String> getUsers(){
InnerMethodName.instance.set("getUsers");
JackrabbitSession session = null;
List<String> users = null;
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
return new UsersList(userHandler.getAllUsers(session));
} catch (Throwable e) {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(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);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (session != null)
if (session!=null)
session.logout();
}
return null;
return users;
}
@GET
@Path("{user}")
@Produces(MediaType.APPLICATION_JSON)
public SHUBUser getUser(@PathParam("user") String user) {
InnerMethodName.set("getUser");
public String getUser(@PathParam("user") String user){
InnerMethodName.instance.set("getUser");
JackrabbitSession session = null;
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
return userHandler.getUser(session, user);
} catch (StorageHubException se) {
log.error("error getting user", se);
GXOutboundErrorResponse.throwException(se);
} catch (Exception e) {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Authorizable authorizable = usrManager.getAuthorizable(user);
if (authorizable != null && !authorizable.isGroup())
return authorizable.getPrincipal().getName();
log.debug("user {} not found", user);
}catch(Exception e) {
log.error("jcr error getting user", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (session != null)
if (session!=null)
session.logout();
}
@ -103,114 +169,201 @@ public class UserManager {
@POST
@Path("")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE })
public String createUser(@FormParam("user") String user, @FormParam("password") String password) {
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
InnerMethodName.set("createUser");
InnerMethodName.instance.set("createUser");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
userId = userHandler.createUser(session, user, password);
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();
}
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
return userId;
}
User createdUser = usrManager.createUser(user, password);
userId = createdUser.getID();
@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);
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();
} catch (StorageHubException she) {
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) {
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session != null)
if (session!=null)
session.logout();
}
return userId;
}
@DELETE
@Path("{user}")
@AuthorizationControl(allowedRoles = { INFRASTRUCTURE_MANAGER_ROLE })
public String deleteUser(@PathParam("user") final String user) {
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteUser(@PathParam("user") final String user){
InnerMethodName.set("deleteUser");
InnerMethodName.instance.set("deleteUser");
JackrabbitSession session = null;
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();
} catch (StorageHubException she) {
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) {
log.error("jcr error removing item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing item", re));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session != null)
if (session!=null)
session.logout();
}
return user;
}
@GET
@Path("{user}/groups")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getGroupsPerUser(@PathParam("user") final String user) {
private void removeUserFromBelongingGroup(JackrabbitSession session, User authorizable, org.apache.jackrabbit.api.security.user.UserManager usrManager) throws RepositoryException, StorageHubException {
Iterator<Authorizable> groups = session.getUserManager().findAuthorizables(new Query() {
InnerMethodName.set("getGroupsPerUser");
JackrabbitSession session = null;
List<String> groups = new ArrayList<>();
try {
session = (JackrabbitSession) repository.getRepository().login(Constants.JCR_CREDENTIALS);
userHandler.getGroupsPerUser(session, user);
} 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();
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(Group.class);
}
});
String user = authorizable.getPrincipal().getName();
while(groups.hasNext()) {
Authorizable group = groups.next();
log.info("group found {}", group.getPrincipal().getName() );
if (group.isGroup() && ((Group)group).isMember(authorizable)) {
boolean success = groupHandler.removeUserFromGroup(group.getPrincipal().getName(), user, session);
log.warn("user {} {} removed from vre {}",user,success?"":"not" ,group.getPrincipal().getName());
}
}
}
private void unshareUsersFolders(JackrabbitSession session, String user){
try {
Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH);
Predicate<Node> sharedWithUserChecker = new Predicate<Node>() {
@Override
public boolean test(Node t) {
try {
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
return true;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
List<SharedFolder> items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class);
log.debug(" Shared folder to unshare found are {}", items.size());
for (SharedFolder item: items) {
String title = item.getTitle();
log.debug("in list folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue;
if (item.isVreFolder()) continue;
log.info("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
String owner = item.getOwner();
Set<String> usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user);
try {
unshareHandler.unshareForRemoval(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user);
}catch (Throwable e) {
log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e);
}
}
} catch (Throwable t) {
log.warn("error getting folder shared with {}",user, t);
}
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