Compare commits

...

131 Commits

Author SHA1 Message Date
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
lucio.lelii 7f88e20a88 first message shown twice for new user issue solved 2021-10-13 13:48:37 +02:00
lucio.lelii 08f0160d8d changed vre recents parameter 2021-10-13 11:48:03 +02:00
lucio.lelii 2a46ac3aa2 solved error on vre recents 2021-10-13 11:35:19 +02:00
lucio.lelii 882f849e2f pom and changelog updated 2021-10-12 14:01:21 +02:00
lucio.lelii 8c934a138e Merge remote-tracking branch 'origin/vreQueryRemoval'
Conflicts:
	CHANGELOG.md
	pom.xml
2021-10-12 13:40:06 +02:00
lucio.lelii 20390e3147 incident https://support.d4science.org/issues/22184 solved 2021-10-12 13:12:02 +02:00
lucio.lelii 47bf9b57d2 pom and changelog update 2021-10-07 10:38:35 +02:00
lucio.lelii 27c6f2d3e1 scriptManager accept different names 2021-10-06 19:41:18 +02:00
lucio.lelii 586d9df939 removed a part of query to retrieve recents 2021-10-06 19:18:34 +02:00
lucio.lelii 7ebd1ae629 fix updated 2021-10-06 11:56:57 +02:00
lucio.lelii 51cbd0776a solved bug https://support.d4science.org/issues/22147 2021-10-06 11:44:23 +02:00
lucio.lelii f30029c052 - using groupHandler method to retrieve VRE
- added logs to ScriptManager error
2021-10-06 10:37:14 +02:00
Lucio Lelii 68eb65e168 removing query for retreiving VRE root Folder 2021-10-04 17:11:43 +02:00
lucio.lelii 8fd9bb5ac2 Merge branch 'master' of https://code-repo.d4science.org/gCubeSystem/storagehub.git 2021-09-28 13:37:32 +02:00
lucio.lelii 147e8a8961 solved bug on instantiation error for types that are not in the model 2021-09-28 13:36:56 +02:00
Roberto Cirillo 933009f8ab Update 'pom.xml' 2021-09-28 12:53:47 +02:00
Roberto Cirillo 0222d27a5e Update 'CHANGELOG.md' 2021-09-28 12:53:29 +02:00
Roberto Cirillo 082b49ebc6 Update 'CHANGELOG.md' 2021-09-28 12:40:39 +02:00
Roberto Cirillo e255a2ff5d Update 'pom.xml'
update to 1.3.2-SNAPSHOT
2021-09-28 12:39:36 +02:00
lucio.lelii 24576cd30f solved bug on messages attachments 2021-09-10 10:59:07 +02:00
Lucio Lelii f68588e05c solved issue on specific version download 2021-07-26 16:07:40 +02:00
Lucio Lelii cb609cf51c solved issue on deleting version content on empty trash 2021-07-26 10:40:05 +02:00
Lucio Lelii 8929ff579c storagebackends takes ids on delete 2021-07-21 17:36:27 +02:00
Lucio Lelii aeb434dd06 solved issue executing force delete on folder 2021-07-21 15:31:23 +02:00
lucio.lelii 470cc28035 solved issue on attachemnts 2021-07-02 13:17:25 +02:00
lucio.lelii 13016497f1 fixed a bug on Excludes 2021-05-04 18:26:30 +02:00
lucio.lelii eab7dc19b4 commit for release 2021-05-04 12:35:39 +02:00
lucio.lelii 3723ac730c script utils dep added 2021-05-04 12:30:03 +02:00
lucio.lelii 2aadb9cce7 - External Folder imporvements - Inbox and Outbox creation 2021-05-04 11:42:02 +02:00
lucio.lelii bcbe97f547 - ACLManager Delegate Added 2021-04-07 12:38:18 +02:00
lucio.lelii a2613dc1a7 - possibility to impersonate people added 2021-03-31 14:49:47 +02:00
lucio.lelii 64952442ed unshareAll fixed 2021-03-16 15:37:18 +01:00
lucio.lelii e271e9fe78 removing also ACL on already unshared folder 2021-03-16 13:54:34 +01:00
lucio.lelii 7566a3cf9f issue on home folder removal fixed 2021-03-16 13:03:27 +01:00
lucio.lelii 8c677df64e NodeAdmin resource added 2021-03-16 10:01:07 +01:00
lucio.lelii 61c84fbb11 reverted chenage 2021-03-16 00:04:54 +01:00
lucio.lelii 31751ca11e solved an issue on versioning 2021-03-15 16:52:19 +01:00
lucio.lelii 7591536a69 removing old not versioned node 2021-03-15 16:01:14 +01:00
lucio.lelii 6b690caf56 users list ordering added 2021-03-15 11:57:46 +01:00
lucio.lelii 288e8d4254 smartgear bom version fixed 2021-03-12 11:22:46 +01:00
lucio.lelii b68d30cd53 removed snapshot for release 2021-03-12 10:27:38 +01:00
lucio.lelii 7df7afecd3 use of query (indexes are not working well in jackrabbit) to retrieve
shared folder removed on delete user
2021-03-12 10:24:45 +01:00
lucio.lelii 1e916b21b6 added method to check user existence 2021-02-08 12:30:58 +01:00
lucio.lelii 56e01e91f8 Merge branch 'master' of https://code-repo.d4science.org/gCubeSystem/storagehub.git 2021-01-13 10:48:00 +01:00
lucio.lelii 94cb6e4cd3 added catch of all exception on unshare during delete 2021-01-13 10:46:58 +01:00
Roberto Cirillo 5760a44220 Update 'pom.xml'
removed snapshot from gcube-smartgears-bom version
2021-01-12 09:36:07 +01:00
lucio.lelii cbb77864c5 mimetype set also on non parsable pdf
method add and remove admin on a VREFolder enabled also for admin role

fixed bug on unsharing folder on user removal
2021-01-11 18:07:57 +01:00
user1 effbb513a7 ObjectMapper import changed to thegcube embedded jackson 2020-11-10 15:18:11 +01:00
user1 953cec03ee removed an unused session 2020-10-13 16:27:31 +02:00
user1 0d499d6c88 acl error message changed 2020-10-13 15:53:27 +02:00
user1 79f755dc13 pom cleaned from warnings 2020-10-08 12:02:11 +02:00
user1 8b494440af changelog modified 2020-10-07 18:30:46 +02:00
user1 d57647a714 mimetype set also on non parasble pdf 2020-10-07 18:28:34 +02:00
Fabio Sinibaldi cb57512174 adoption of gcube-smartgears-bom.2.0.0-SNAPSHOT 2020-10-07 16:34:00 +02:00
Lucio Lelii 2732b05426 SNAPSHOT removed from version 2020-09-16 12:28:38 +02:00
Lucio Lelii 432859d9bb descriptor removed 2020-09-16 12:27:20 +02:00
Lucio Lelii dcf1a614b4 commit for release 2020-09-16 12:11:52 +02:00
Lucio Lelii 84cec8aa76 changelog added 2020-05-26 16:31:23 +02:00
Lucio Lelii 52df23f2a9 changelog added 2020-05-26 16:30:50 +02:00
Lucio Lelii ce8a1e744f commit for release 4.23
resolves a bug on Archive upload
2020-05-22 17:31:40 +02:00
Lucio Lelii 70ae49e28d update for test issue 2020-04-23 16:09:13 +02:00
Lucio Lelii f2742ce0e0 solved bug with getAnchestors and public folders 2020-04-17 17:03:06 +02:00
Lucio Lelii 7ed01ecc4e ItemAction for restore set to MOVED 2020-04-15 17:40:02 +02:00
Lucio Lelii 1db74cc4df solved bugs on restore item and authorization 2020-04-15 17:36:11 +02:00
Lucio Lelii aae84a27d6 pom updated for release 4.22 2020-04-15 10:42:02 +02:00
Lucio Lelii b80f1ccb0d changelog updated 2020-04-15 10:31:09 +02:00
Lucio Lelii ea438888c8 added a todo 2020-04-14 19:49:04 +02:00
Lucio Lelii 01b74ae117 added a servlet for administration 2020-04-14 19:48:28 +02:00
Lucio Lelii 94d9307b4c refactoring of some classes 2020-04-14 18:52:59 +02:00
Lucio Lelii e82d695bbf setting owner of an full unshared folder to caller 2020-04-14 18:52:20 +02:00
Lucio Lelii 458b8a72ea allows moving shared item outside the shared folder 2020-04-14 18:46:44 +02:00
Lucio Lelii 487eae33e2 refactoring 2020-04-09 13:31:17 +02:00
Lucio Lelii 08351b2005 public folder check added on Authorization Checker 2020-04-09 09:44:40 +02:00
Lucio Lelii 4c13f4098e moved classes in differen packages 2020-04-08 21:11:43 +02:00
lucio 6e69de91d0 solved an error on authorization for deleted user 2020-04-05 11:37:15 +02:00
lucio 62fe5a77a0 removes duplicate nodes in search 2020-03-17 13:58:37 +01:00
lucio acbd780dff pom updated for release 2020-03-17 13:41:46 +01:00
lucio a7ee9afb76 search excludes not authorized node from the results 2020-03-17 13:40:41 +01:00
lucio 9e3b5f08e0 pom updated for release 2020-03-16 16:56:57 +01:00
lucio 133d71f14f search exludes hidden 2020-03-16 16:55:26 +01:00
Lucio Lelii 9d895f0adf pom updated 2020-03-11 15:14:20 +01:00
lucio 177888e1b4 - openByPath added
- replaced some warning log with debug
2020-03-11 15:00:40 +01:00
lucio 868eadfdaa complete remove of file on user and group deletion 2020-03-05 15:39:34 +01:00
lucio 6c9aaa9489 pom updated 2020-03-05 15:18:47 +01:00
lucio 774e2b4bfb getByPath method added 2020-03-05 15:18:20 +01:00
lucio fae5173b17 diaplyName bug with root scope containing dashes fixed 2020-01-31 15:22:54 +01:00
lucio ddbac93245 VRE ACl can be changed using setAcl method 2020-01-30 17:14:46 +01:00
lucio 8a84c93c18 fixed bug on administrator check 2020-01-30 17:02:13 +01:00
lucio 2033af4572 bug on vre folder displayName on folder containing - in the name solved 2020-01-30 16:13:23 +01:00
lucio 0711d8a702 control on invalid group id and user added on addAdmin 2020-01-30 11:18:35 +01:00
lucio b9d62994f9 bug on group creation fixed 2020-01-29 17:14:44 +01:00
lucio 8f725d46c0 group creation logs added 2020-01-29 15:25:24 +01:00
lucio eb3daa0a26 added vre folder to group creator workspace 2020-01-29 12:24:30 +01:00
lucio e08984af23 On Grup creation the user creator is automatically added to the gruop 2020-01-29 11:37:50 +01:00
lucio 067f487f8b search made case insensitive 2020-01-24 12:30:05 +01:00
lucio df1956c08d accounting on serach method fixed 2020-01-24 11:59:01 +01:00
Lucio Lelii 4ebc3ce222 Update pom.xml 2020-01-23 15:37:30 +01:00
Lucio Lelii abc2e16cde SNAPSHOT removed on dependency ranges 2020-01-23 12:51:05 +01:00
Lucio Lelii 0311d9782d Update pom.xml 2020-01-23 12:26:11 +01:00
lucio 1bcaa47d48 Merge remote-tracking branch 'origin/rolesmanaging'
Conflicts:
	src/main/webapp/WEB-INF/README
	src/main/webapp/WEB-INF/gcube-app.xml
2020-01-22 17:14:22 +01:00
lucio 0f645fdde7 commit for release 2020-01-22 16:41:12 +01:00
lucio 8ac4752ca7 pom committed 2020-01-22 12:45:19 +01:00
lucio a4dc3cff54 My ApplicationListener added 2020-01-22 12:40:35 +01:00
lucio de91f86daf version changed for release 2020-01-22 12:40:01 +01:00
lucio 188d11ff70 Application Listener add to correctly shutdown the jackrabbit repository 2020-01-22 12:32:49 +01:00
lucio c1ab8333b8 solved error on group creation 2020-01-16 18:11:23 +01:00
lucio 67fe556a4f methdo for administrator management added 2020-01-15 19:11:07 +01:00
lucio 2dc02aa194 unshared accounting added 2020-01-07 18:25:52 +01:00
lucio 4802a0542e Corrected a Authorization message error 2020-01-07 17:05:51 +01:00
lucio 0f156c6637 gcube-app file updated 2019-10-25 14:58:09 +02:00
lucio 0508aa0e3a added inner method name to GroupManager 2019-10-10 19:09:30 +02:00
lucio 18cba6c067 added client method for User and Group management 2019-10-10 18:15:38 +02:00
81 changed files with 6975 additions and 2280 deletions

View File

@ -13,15 +13,15 @@
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
@ -35,5 +35,6 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -1,14 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

View File

@ -1,16 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="storagehub">
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<dependent-module archiveName="authorization-control-library-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/authorization-control-library/authorization-control-library">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="storagehub-model-1.0.5.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
<dependency-type>uses</dependency-type>
</dependent-module>
<property name="context-root" value="storagehub"/>
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
</wb-module>
</project-modules>

78
CHANGELOG.md Normal file
View File

@ -0,0 +1,78 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.4.2] - [2023-05-22]
- added enunciate libraries for documentation
## [v1.4.1] - [2022-11-14]
- added libraries to manage different image format
## [v1.4.0] - [2021-10-07]
- slow query removed from VRE retrieving and recents
- incident #22184 solved
## [v1.3.2] - [2021-09-28]
- fix 22087
## [v1.3.1] - [2021-09-08]
- solved bug on attachment rights
## [v1.3.0] - [2021-03-31]
- possibility to impersonate people added
## [v1.2.5] - [2021-03-11]
use of query (indexes are not working well in jackrabbit) to retrieve shared folder removed on delete user
## [v1.2.4] - [2021-01-11]
mimetype set also on non parsable pdf
method add and remove admin on a VREFolder enabled also for admin role
fixed bug on unsharing folder on user removal
added method exist user
## [v1.2.2] - [2020-10-12]
method for description update added
## [v1.2.1] - [2020-06-20]
bug on Archive uploader solved
## [v1.2.0] - [2020-04-15]
trash items changes owner on restore
restore with new destination folder added
move between shared and private or different shared folder enabled
## [v1.0.8] - [2019-09-20]
Bug on ushare owner fixed
## [v1.0.5] - [2019-04-04]
Active wait for lock in case of item creation added
## [v1.0.0] - [2015-07-01]
First commit

26
FUNDING.md Normal file
View File

@ -0,0 +1,26 @@
# Acknowledgments
The projects leading to this software have received funding from a series of European Union programmes including:
- the Sixth Framework Programme for Research and Technological Development
- [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
- the Seventh Framework Programme for research, technological development and demonstration
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
- the H2020 research and innovation programme
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);

View File

@ -1,4 +1,4 @@
#European Union Public Licence V.1.1
#European Union Public Licence V.1.2
##*EUPL © the European Community 2007*
@ -12,7 +12,7 @@ The Original Work is provided under the terms of this Licence when the Licensor
(as defined below) has placed the following notice immediately following the
copyright notice for the Original Work:
**Licensed under the EUPL V.1.1**
**Licensed under the EUPL V.1.2**
or has expressed by any other mean his willingness to license under the EUPL.

View File

@ -1,14 +0,0 @@
<ReleaseNotes>
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.8"
date="2019-09-20">
<Change>Bug on ushare owner fixed</Change>
</Changeset>
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.5"
date="2019-04-04">
<Change>Active wait for lock in case of item creation added</Change>
</Changeset>
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.0"
date="2015-07-01">
<Change>First commit</Change>
</Changeset>
</ReleaseNotes>

View File

@ -1,32 +0,0 @@
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>servicearchive</id>
<formats>
<format>tar.gz</format>
</formats>
<baseDirectory>/</baseDirectory>
<fileSets>
<fileSet>
<directory>.</directory>
<outputDirectory>/</outputDirectory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>README.md</include>
<include>LICENSE.md</include>
<include>changelog.xml</include>
<include>profile.xml</include>
</includes>
<fileMode>755</fileMode>
<filtered>true</filtered>
</fileSet>
</fileSets>
<files>
<file>
<source>target/${build.finalName}.war</source>
<outputDirectory>/${artifactId}</outputDirectory>
</file>
</files>
</assembly>

View File

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

View File

24
enunciate.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<enunciate
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.14.0.xsd">
<api-classes>
<!-- Use patterns to exclude classes... e.g. for URI-Resolver <exclude
pattern="org.gcube.datatransfer.resolver.services.DocsGenerator" /> -->
</api-classes>
<modules>
<gwt-json-overlay disabled="true" />
<php-json-client disabled="true" />
<ruby-json-client disabled="true" />
<java-json-client disabled="true" />
<javascript-client disabled="true" />
<docs docsDir="${project.build.directory}" docsSubdir="api-docs" />
<docs
freemarkerTemplate="${project.basedir}/src/main/resources/META-INF/enunciate/d4science_docs.fmt">
<additional-css
file="css/d4science_enunciate_custom.css" />
</docs>
<swagger basePath="/workspace" />
</modules>
</enunciate>

280
pom.xml
View File

@ -1,53 +1,44 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>maven-parent</artifactId>
<groupId>org.gcube.tools</groupId>
<version>1.1.0</version>
<relativePath />
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.gcube.data.access</groupId>
<artifactId>storagehub</artifactId>
<version>1.0.8</version>
<version>1.4.2</version>
<name>storagehub</name>
<scm>
<connection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</connection>
<developerConnection>scm:git:https://code-repo.d4science.org/gCubeSystem/storagehub.git</developerConnection>
<url>https://code-repo.d4science.org/gCubeSystem/storagehub</url>
</scm>
<packaging>war</packaging>
<properties>
<webappDirectory>${project.basedir}/src/main/webapp/WEB-INF</webappDirectory>
<jackrabbit.version>2.16.0</jackrabbit.version>
<jackrabbit.version>2.20.2</jackrabbit.version>
<jackson.version>2.8.11</jackson.version>
<slf4j.version>1.7.4</slf4j.version>
<tomcat.version>7.0.40</tomcat.version>
<jetty.version>6.1.26</jetty.version>
<tika.version>1.21</tika.version>
<slf4j.api.version>1.6.6</slf4j.api.version>
<slf4j.version>1.7.4</slf4j.version> <!-- sync with logback version -->
<logback.version>1.0.12</logback.version>
<distroDirectory>${project.basedir}/distro</distroDirectory>
<description>REST web service for Jackrabbit</description>
<warname>storagehub</warname>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<enunciate.version>2.14.0</enunciate.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>maven-smartgears-bom</artifactId>
<version>LATEST</version>
<artifactId>gcube-smartgears-bom</artifactId>
<version>2.1.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -58,82 +49,85 @@
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears-app</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-control-library</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
<version>[1.0.0,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>common-authorization</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope-maps</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-scope</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-encryption</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>storagehub-model</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.data.access</groupId>
<artifactId>storagehub-script-utils</artifactId>
<version>[1.0.0, 2.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
<version>5.5.13.2</version>
</dependency>
<!-- needed to manage strange image types -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-bmp</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-core</artifactId>
<version>3.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>gxJRS</artifactId>
<version>[1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT)</version>
</dependency>
<!-- JCR dependencies -->
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
@ -142,7 +136,7 @@
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-api</artifactId>
<version>${jackrabbit.version}</version>
<version>2.19.3</version>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
@ -154,139 +148,159 @@
<artifactId>jackrabbit-jcr-server</artifactId>
<version>${jackrabbit.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-core -->
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.21</version>
</dependency>
<!-- jersey -->
<!-- https://mvnrepository.com/artifact/net.bull.javamelody/javamelody-core -->
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
<groupId>net.bull.javamelody</groupId>
<artifactId>javamelody-core</artifactId>
<version>1.82.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
<!-- jersey & weld -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- weld -->
<!-- https://mvnrepository.com/artifact/javax.interceptor/javax.interceptor-api -->
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>1.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.enterprise/cdi-api -->
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.1</version>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.30.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.2.10.Final</version>
<artifactId>weld-servlet-core</artifactId>
<version>3.1.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss/jandex -->
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>1.2.2.Final</version>
<version>2.2.2.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.0</version>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
<scope>runtime</scope>
</dependency>
<!-- Storage dependencies -->
<dependency>
<groupId>org.gcube.contentmanagement</groupId>
<artifactId>storage-manager-core</artifactId>
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.contentmanagement</groupId>
<artifactId>storage-manager-wrapper</artifactId>
<version>[2.0.0-SNAPSHOT,3.0.0-SNAPSHOT)</version>
<version>[3.0.0-SNAPSHOT,4.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-simple</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
@ -299,7 +313,6 @@
<version>10.8.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.jeeunit</groupId>
<artifactId>jeeunit</artifactId>
@ -312,21 +325,29 @@
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
<groupId>com.vlkan.rfos</groupId>
<artifactId>rotating-fos</artifactId>
<version>0.9.2</version>
</dependency>
<!-- enunciate deps -->
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
<version>${enunciate.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-rt-util</artifactId>
<version>${enunciate.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
@ -334,14 +355,11 @@
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se</artifactId>
@ -354,24 +372,19 @@
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${artifactId}</finalName>
<finalName>${project.artifactId}</finalName>
<pluginManagement>
<plugins>
<plugin>
@ -385,7 +398,6 @@
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<versionRange>[1.0,)</versionRange>
<goals>
<goal>test-compile</goal>
@ -403,7 +415,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<version>1.14.0</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
@ -433,7 +445,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
@ -461,25 +472,46 @@
</execution>
</executions>
</plugin>
<!-- Enunciate Maven plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>descriptor.xml</descriptor>
</descriptors>
</configuration>
<groupId>com.webcohesion.enunciate</groupId>
<artifactId>enunciate-maven-plugin</artifactId>
<version>${enunciate.version}</version>
<configuration></configuration>
<executions>
<execution>
<id>servicearchive</id>
<phase>install</phase>
<id>assemble</id>
<goals>
<goal>single</goal>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Copy Enunciate Documentation from your-application/docs to your-application.war -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-enunciate-docs</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>target</outputDirectory>
<resources>
<resource>
<targetPath>${project.build.directory}/${project.artifactId}/api-docs</targetPath>
<directory>${project.build.directory}/api-docs</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID></ID>
<Type>Service</Type>
<Profile>
<Description>Storage Hub Webapp</Description>
<Class>DataAccess</Class>
<Name>${artifactId}</Name>
<Version>1.0.0</Version>
<Packages>
<Software>
<Name>${artifactId}</Name>
<Version>${version}</Version>
<MavenCoordinates>
<groupId>${groupId}</groupId>
<artifactId>${artifactId}</artifactId>
<version>${version}</version>
</MavenCoordinates>
<Files>
<File>${build.finalName}.jar</File>
</Files>
</Software>
</Packages>
</Profile>
</Resource>

View File

@ -1,34 +1,39 @@
package org.gcube.data.access.storagehub;
import org.apache.jackrabbit.api.security.user.Group;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.Privilege;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.acls.ACL;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.java.Log;
import lombok.extern.log4j.Log4j;
/**
*
*
* the caller must be authorized, so i'm not passing the login also if it works on behalf of an user
*
*
*/
@Singleton
public class AuthorizationChecker {
@ -37,76 +42,113 @@ public class AuthorizationChecker {
@Inject
Node2ItemConverter node2Item;
public void checkReadAuthorizationControl(Session session, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
Node node = session.getNodeByIdentifier(id);
@Inject
PathUtil pathUtil;
String login = AuthorizationProvider.instance.get().getClient().getId();
@Inject
ACLManagerInterface aclManager;
public void checkReadAuthorizationControl(Session session, String userToCheck, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
Node node = session.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id+": it's not a valid StorageHub node");
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id+": it's not a valid StorageHub node");
//checking if the item is in the owner trash folder
if(item instanceof TrashItem && item.getParentPath().equals(pathUtil.getTrashPath(userToCheck, session).toPath()))
return;
if (!item.isShared() && item.getOwner()!=null && item.getOwner().equals(userToCheck)) return;
if (hasParentPublicFolder(session, item)) return;
//TODO: remove when messages will be passed to a new system
String parentPath = item.getParentPath();
if (parentPath.endsWith("hl:attachments") && (parentPath.contains("/OutBox/") || parentPath.contains("/InBox/"))) {
return ;
}
if (item.isShared()) {
SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
if (parentShared.getUsers().getMap().keySet().contains(login)) return;
//SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
//if (parentShared.getUsers().getMap().keySet().contains(userToCheck)) return;
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentShared.getPath());
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
Authorizable userAuthorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(login);
for (AccessControlEntry entry: entries) {
log.debug("checking access right for {} with compared with {}",login, entry.getPrincipal());
Authorizable authorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(entry.getPrincipal());
//TODO; check why sometimes the next line gets a nullpointer
if (!authorizable.isGroup() && entry.getPrincipal().getName().equals(login)) return;
List<ACL> acls = aclManager.get(item, session);
UserManager userManager = ((JackrabbitSession) session).getUserManager();
Authorizable userAuthorizable = userManager.getAuthorizable(userToCheck);
for (ACL entry: acls) {
log.debug("checking access right for {} with compared with {}",userToCheck, entry.getPricipal());
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
if (authorizable==null) {
log.warn("{} doesn't have a correspondant auhtorizable object, check it ", entry.getPricipal());
continue;
}
try {
if (!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) return;
if (authorizable.isGroup() && ((Group) authorizable).isMember(userAuthorizable)) return;
}catch (Throwable e) {
log.warn("someting went wrong checking authorizations",e);
}
}
}
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
} else if (item.getOwner()==null || !item.getOwner().equals(login))
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to read node with id "+id);
}
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
private boolean hasParentPublicFolder(Session session, Item item) {
if(item==null || item.getParentPath()==null) return false;
if (item.getParentPath().replaceAll("/Home/[^/]*/"+Constants.WORKSPACE_ROOT_FOLDER_NAME,"").isEmpty() || item.getParentPath().replaceAll(Constants.SHARED_FOLDER_PATH, "").isEmpty()) {
if (item instanceof FolderItem)
return ((FolderItem) item).isPublicItem();
else return false;
} else {
if (item instanceof FolderItem)
try {
return ((FolderItem) item).isPublicItem() || hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
}catch (Throwable e) {
log.warn("error checking public parents",e);
return false;
}
else
return retrieveSharedFolderParent(node.getParent(), session);
try {
return hasParentPublicFolder(session, node2Item.getItem(item.getParentId(), session, Excludes.ALL));
}catch (Throwable e) {
log.warn("error checking public parents",e);
return false;
}
}
}
public void checkWriteAuthorizationControl(Session session, String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
//in case of newItem the id is the parent otherwise the old node to replace
Node node = session.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
String login = AuthorizationProvider.instance.get().getClient().getId();
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's not a valid StorageHub node");
//newItem means that a new item will be created and id is the destination directory
public void checkWriteAuthorizationControl(Session session, String userToCheck, Item item, Node node, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
if (item==null) throw new UserNotAuthorizedException("Not valid StorageHub node");
if (Constants.WRITE_PROTECTED_FOLDER.contains(item.getName()) || Constants.WRITE_PROTECTED_FOLDER.contains(item.getTitle()))
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's a protected folder");
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId()+": it's a protected folder");
if (item.isShared()) {
Node parentSharedNode = retrieveSharedFolderParent(node, session);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
Authorizable UserAuthorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(login);
//CHECKING ACL FOR VREFOLDER AND SHARED FOLDER
List<ACL> acls = aclManager.get(item, session);
UserManager userManager = ((JackrabbitSession) session).getUserManager();
Authorizable UserAuthorizable = userManager.getAuthorizable(userToCheck);
//put it in a different method
for (AccessControlEntry entry: entries) {
Authorizable authorizable = ((JackrabbitSession) session).getUserManager().getAuthorizable(entry.getPrincipal());
if ((!authorizable.isGroup() && entry.getPrincipal().getName().equals(login)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
for (Privilege privilege : entry.getPrivileges()){
AccessType access = AccessType.fromValue(privilege.getName());
if (isNewItem && access!=AccessType.READ_ONLY)
for (ACL entry: acls) {
Authorizable authorizable = userManager.getAuthorizable(entry.getPricipal());
if ((!authorizable.isGroup() && entry.getPricipal().equals(userToCheck)) || (authorizable.isGroup() && ((Group) authorizable).isMember(UserAuthorizable))){
for (AccessType privilege : entry.getAccessTypes()){
if (isNewItem && privilege!=AccessType.READ_ONLY)
return;
else
if (!isNewItem &&
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(login))))
(privilege==AccessType.ADMINISTRATOR || privilege==AccessType.WRITE_ALL || (privilege==AccessType.WRITE_OWNER && item.getOwner().equals(userToCheck))))
return;
}
@ -114,72 +156,56 @@ public class AuthorizationChecker {
}
}
} else
if(item.getOwner().equals(login))
if(item.getOwner().equals(userToCheck))
return;
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id);
throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+" to write into node with id "+item.getId());
}
//newItem means that a new item will be created and id is the destination directory
public void checkWriteAuthorizationControl(Session session, String userToCheck , String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
//in case of newItem the id is the parent otherwise the old node to replace
Node node = session.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
checkWriteAuthorizationControl(session, userToCheck, item, node, isNewItem);
}
/**
*
* checks if item with {id} can be moved
*
*/
public void checkMoveOpsForProtectedFolders(Session session, String id) throws InvalidCallParameters, BackendGenericError, RepositoryException {
Node node = session.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
throw new InvalidCallParameters("protected folder cannot be moved or deleted");
}
public void checkAdministratorControl(Session session, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
//TODO: riguardare questo pezzo di codice
String login = AuthorizationProvider.instance.get().getClient().getId();
/**
*
* checks if {userToCheck} is an admin for {item}
*
*/
public void checkAdministratorControl(Session session, String userToCheck, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+": it's not a valid StorageHub node");
Node node = session.getNodeByIdentifier(item.getId());
if (item==null) throw new UserNotAuthorizedException("Insufficent Privileges for user "+userToCheck+": it's not a valid StorageHub node");
if (item.isShared()) {
Node parentSharedNode = retrieveSharedFolderParent(node, session);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
//put it in a different method
List<ACL> acls = aclManager.get(item, session);
SharedFolder parentShared = node2Item.getItem(parentSharedNode, Excludes.EXCLUDE_ACCOUNTING);
for (AccessControlEntry entry: entries) {
if (entry.getPrincipal().getName().equals(login) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
for (Privilege privilege : entry.getPrivileges()){
AccessType access = AccessType.fromValue(privilege.getName());
if (access==AccessType.ADMINISTRATOR)
for (ACL entry: acls) {
if (entry.getPricipal().equals(userToCheck)) {
for (AccessType privilege : entry.getAccessTypes()){
if (privilege==AccessType.ADMINISTRATOR)
return;
}
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
}
}
}
throw new UserNotAuthorizedException("The user "+userToCheck+" is not an administrator of node with id "+item.getId());
}
}
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
}
/*
private String retrieveOwner(Node node) {
Node nodeOwner;
//get Owner
try{
return node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString();
}catch (Exception e) {
try {
nodeOwner = node.getNode(NodeProperty.OWNER.toString());
return nodeOwner.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString();
// this.userId = nodeOwner.getProperty(USER_ID).getString();
// this.portalLogin = nodeOwner.getProperty(PORTAL_LOGIN).getString();
// node.getSession().save();
} catch (Exception e1) {
throw new RuntimeException(e1);
}
}
}
*/
}

View File

@ -5,7 +5,17 @@ import java.util.List;
public class Constants {
public static final String VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
public static final String OLD_VRE_FOLDER_PARENT_NAME = "MySpecialFolders";
public static final String PERSONAL_VRES_FOLDER_PARENT_NAME = "VREs";
public static final String INBOX_FOLDER_NAME = "InBox";
public static final String OUTBOX_FOLDER_NAME = "OutBox";
public static final String ATTACHMENTNODE_NAME = "hl:attachments";
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe";
public static final String SHARED_FOLDER_PATH = "/Share";
@ -19,9 +29,11 @@ public class Constants {
public static final String ADMIN_PARAM_PWD ="admin-pwd";
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final String HOME_VERSION_PROP = "hl:version";
public static final List<String> WRITE_PROTECTED_FOLDER = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.WORKSPACE_ROOT_FOLDER_NAME, Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final List<String> WRITE_PROTECTED_FOLDER = Arrays.asList(Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.WORKSPACE_ROOT_FOLDER_NAME, Constants.OLD_VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
}

View File

@ -5,6 +5,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

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

View File

@ -0,0 +1,51 @@
package org.gcube.data.access.storagehub;
import java.util.Iterator;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
public class NodeChildrenFilterIterator implements Iterator<Node> {
private NodeIterator it;
public NodeChildrenFilterIterator(Node node) throws BackendGenericError{
super();
try {
it = node.getNodes();
} catch (RepositoryException e) {
throw new BackendGenericError(e);
}
}
public NodeChildrenFilterIterator(NodeIterator iterator) throws BackendGenericError{
it = iterator;
}
private Node currentNode = null;
@Override
public boolean hasNext() {
try {
while (it.hasNext()) {
currentNode=it.nextNode();
if (ClassHandler.instance().get(currentNode.getPrimaryNodeType().getName())!=null)
return true;
}
return false;
}catch (RepositoryException e) {
throw new RuntimeException(e);
}
}
@Override
public Node next() {
return currentNode;
}
}

View File

@ -0,0 +1,70 @@
package org.gcube.data.access.storagehub;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.Path;
import org.gcube.common.storagehub.model.Paths;
@Singleton
public class PathUtil {
public Path getWorkspacePath(String login){
return Paths.getPath(String.format("/Home/%s/%s",login,Constants.WORKSPACE_ROOT_FOLDER_NAME));
}
public Path getHome(String login){
return Paths.getPath(String.format("/Home/%s",login));
}
public Path getInboxPath(String login) {
return Paths.append(getHome(login),Constants.INBOX_FOLDER_NAME);
}
public Path getOutboxPath(String login) {
return Paths.append(getHome(login),Constants.OUTBOX_FOLDER_NAME);
}
@Deprecated
private Path getOldTrashPath(String login){
return Paths.append(getWorkspacePath(login),Constants.TRASH_ROOT_FOLDER_NAME);
}
private Path getNewTrashPath(String login){
return Paths.append(getHome(login), Constants.TRASH_ROOT_FOLDER_NAME);
}
@Deprecated
private Path getOldVREsPath(String login){
return Paths.append(getWorkspacePath(login),Constants.OLD_VRE_FOLDER_PARENT_NAME);
}
private Path getNewVREsPath(String login){
return Paths.append(getHome(login),Constants.PERSONAL_VRES_FOLDER_PARENT_NAME);
}
public Path getSharedWithMePath(String login){
return Paths.append(getWorkspacePath(login),Constants.SHARED_WITH_ME_PARENT_NAME);
}
public Path getVREsPath(String login, Session session) throws RepositoryException {
Path home = getHome(login);
Node node = session.getNode(home.toPath());
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
return getNewVREsPath(login);
else
return getOldVREsPath(login);
}
public Path getTrashPath(String login, Session session) throws RepositoryException {
Path home = getHome(login);
Node node = session.getNode(home.toPath());
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
return getNewTrashPath(login);
else
return getOldTrashPath(login);
}
}

View File

@ -5,6 +5,7 @@ import javax.jcr.Repository;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.jackrabbit.api.JackrabbitRepository;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
@Singleton
@ -12,19 +13,22 @@ public class RepositoryInitializerImpl implements RepositoryInitializer{
private Repository repository;
@Override
public Repository getRepository(){
public synchronized Repository getRepository(){
return repository;
}
public RepositoryInitializerImpl() throws Exception{
protected RepositoryInitializerImpl() throws Exception{
InitialContext context = new InitialContext();
Context environment = (Context) context.lookup("java:comp/env");
repository = (Repository) environment.lookup("jcr/repository");
}
public void shutdown() {
((JackrabbitRepository)repository).shutdown();
}

View File

@ -0,0 +1,7 @@
package org.gcube.data.access.storagehub;
public class Roles {
public static final String VREMANAGER_ROLE = "VRE-Manager";
public static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
}

View File

@ -8,12 +8,16 @@ import javax.ws.rs.core.Application;
import org.gcube.common.gxrest.response.entity.SerializableErrorEntityTextWriter;
import org.gcube.data.access.storagehub.services.ACLManager;
import org.gcube.data.access.storagehub.services.DocManager;
import org.gcube.data.access.storagehub.services.GroupManager;
import org.gcube.data.access.storagehub.services.Impersonable;
import org.gcube.data.access.storagehub.services.ItemSharing;
import org.gcube.data.access.storagehub.services.ItemsCreator;
import org.gcube.data.access.storagehub.services.ItemsManager;
import org.gcube.data.access.storagehub.services.MessageManager;
import org.gcube.data.access.storagehub.services.UserManager;
import org.gcube.data.access.storagehub.services.WorkspaceManager;
import org.gcube.data.access.storagehub.services.admin.ScriptManager;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
@Path("workspace")
@ -23,7 +27,7 @@ public class StorageHub extends Application {
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<Class<?>>();
// register resources and features
classes.add(MultiPartFeature.class);
classes.add(Impersonable.class);
classes.add(WorkspaceManager.class);
classes.add(ItemsManager.class);
classes.add(ItemsCreator.class);
@ -31,7 +35,12 @@ public class StorageHub extends Application {
classes.add(ItemSharing.class);
classes.add(UserManager.class);
classes.add(GroupManager.class);
classes.add(ScriptManager.class);
classes.add(MessageManager.class);
classes.add(MultiPartFeature.class);
classes.add(SerializableErrorEntityTextWriter.class);
classes.add(MyApplicationListener.class);
classes.add(DocManager.class);
return classes;
}

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

@ -1,6 +1,5 @@
package org.gcube.data.access.storagehub;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -8,12 +7,10 @@ import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Deque;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.util.function.Predicate;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
@ -22,32 +19,29 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.version.Version;
import javax.jcr.query.Query;
import org.apache.commons.io.FilenameUtils;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.util.Text;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.ExternalLink;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.contentmanager.storageclient.wrapper.AccessType;
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -78,7 +72,7 @@ public class Utils {
return digest;
}
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
}
@ -107,36 +101,82 @@ public class Utils {
}
public static <T extends Item> List<T> searchByNameOnFolder(Session ses, String user, AuthorizationChecker authChecker, Node parent, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude, String nameParam) throws RepositoryException, BackendGenericError{
String xpath = String.format("/jcr:root%s//element(*,nthl:workspaceItem)[jcr:like(fn:lower-case(@jcr:title), '%s')]",ISO9075.encodePath(parent.getPath()), nameParam.toLowerCase());
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
logger.debug("getting children of node {}", parent.getIdentifier());
List<T> returnList = new ArrayList<T>();
//String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
logger.trace("query for search is {}",xpath);
long start = System.currentTimeMillis();
NodeIterator iterator = parent.getNodes();
@SuppressWarnings("deprecation")
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(xpath, Query.XPATH);
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(jcrQuery.execute().getNodes());
logger.trace("[SEARCH] real search took {} millis",(System.currentTimeMillis()-start));
Predicate<Node> checker = new Predicate<Node>() {
@Override
public boolean test(Node t) {
try {
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
return true;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
return getItemListFromNodeIterator(checker, iterator , excludes, range, showHidden, excludeTrashed, nodeTypeToInclude);
}
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
return getItemList(null, parent, excludes, range, showHidden, nodeTypeToInclude);
}
public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
logger.trace("getting children of node {}", parent.getIdentifier());
long start = System.currentTimeMillis();
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent);
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, nodeTypeToInclude);
}
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
List<T> returnList = new ArrayList<T>();
logger.trace("nodeType is {}",nodeTypeToInclude);
int count =0;
logger.trace("selected range is {}", range);
Node2ItemConverter node2Item= new Node2ItemConverter();
Set<String> duplicateId = new HashSet<String>();
while (iterator.hasNext()){
Node current = iterator.nextNode();
Node current = iterator.next();
logger.trace("[SEARCH] evaluating node {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
//REMOVE duplicate nodes, in case the indexes are not working
if (duplicateId.contains(current.getIdentifier())) {
logger.warn("duplicated node found");
continue;
}
//EXCLUDES node from predicate
if (checker!=null && !checker.test(current))
continue;
logger.debug("current node "+current.getName());
if (isToExclude(current, showHidden))
continue;
logger.debug("current node not excluded "+current.getName());
logger.trace("[SEARCH] current node not excluded {} ",current.hasProperty(NodeProperty.TITLE.toString())? current.getProperty(NodeProperty.TITLE.toString()):current.getName());
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
if (item==null) continue;
if (item==null || (item.isTrashed() && excludeTrashed)) continue;
returnList.add(item);
}
count++;
duplicateId.add(current.getIdentifier());
}
return returnList;
}
@ -147,83 +187,10 @@ public class Utils {
(node.getPrimaryNodeType().getName().equals(FOLDERS_TYPE) && Constants.FOLDERS_TO_EXLUDE.contains(node.getName())));
}
public static org.gcube.common.storagehub.model.Path getWorkspacePath(){
return Paths.getPath(String.format("/Home/%s/Workspace",AuthorizationProvider.instance.get().getClient().getId()));
}
public static org.gcube.common.storagehub.model.Path getWorkspacePath(String login){
return Paths.getPath(String.format("/Home/%s/Workspace",login));
}
public static org.gcube.common.storagehub.model.Path getHome(String login){
return Paths.getPath(String.format("/Home/%s",login));
}
public static Deque<Item> getAllNodesForZip(FolderItem directory, Session session, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
Deque<Item> queue = new LinkedList<Item>();
Node currentNode = session.getNodeByIdentifier(directory.getId());
queue.push(directory);
Deque<Item> tempQueue = new LinkedList<Item>();
logger.debug("adding directory {}",currentNode.getPath());
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
if (excludes.contains(item.getId())) continue;
if (item instanceof FolderItem)
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler, excludes));
else if (item instanceof AbstractFileItem){
logger.debug("adding file {}",item.getPath());
AbstractFileItem fileItem = (AbstractFileItem) item;
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), false);
queue.addLast(item);
}
}
queue.addAll(tempQueue);
return queue;
}
public static void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath, StorageBackendHandler storageHandler) throws Exception{
logger.trace("originalPath is {}",originalPath.toPath());
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
while (!queue.isEmpty()) {
Item item = queue.pop();
if (item instanceof FolderItem) {
actualPath = Paths.getPath(item.getPath());
logger.debug("actualPath is {}",actualPath.toPath());
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
logger.debug("writing dir {}",name);
if (name.isEmpty()) continue;
try {
zos.putNextEntry(new ZipEntry(name));
}finally {
zos.closeEntry();
}
} else if (item instanceof AbstractFileItem){
try {
InputStream streamToWrite = storageHandler.download(((AbstractFileItem)item).getContent().getStorageId());
if (streamToWrite == null){
logger.warn("discarding item {} ",item.getName());
continue;
}
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
logger.debug("writing file {}",name);
zos.putNextEntry(new ZipEntry(name));
copyStream(is, zos);
}catch (Exception e) {
logger.warn("error writing item {}", item.getName(),e);
} finally{
zos.closeEntry();
}
zos.flush();
}catch (Throwable e) {
logger.warn("error reading content for item {}", item.getPath(),e);
}
}
}
zos.close();
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[2048];
int readcount = 0;
while ((readcount=in.read(buffer))!=-1) {
@ -234,39 +201,16 @@ public class Utils {
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
Node2ItemConverter node2Item = new Node2ItemConverter();
NodeIterator children = node.getNodes();
NodeChildrenFilterIterator children = new NodeChildrenFilterIterator(node);
while (children.hasNext()) {
Node child= children.nextNode();
Node child= children.next();
if (node2Item.checkNodeType(child, SharedFolder.class)) return true;
if (node2Item.checkNodeType(child, FolderItem.class) && hasSharedChildren(child)) return true;
}
return false;
}
public static void getAllContentIds(Session ses, Set<String> idsToDelete, Item itemToDelete, VersionHandler versionHandler) throws Exception{
if (itemToDelete instanceof AbstractFileItem) {
List<Version> versions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(itemToDelete.getId()), ses);
versions.forEach(v -> {
try {
String storageId =v.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
idsToDelete.add(storageId);
logger.info("retrieved StorageId {} for version {}", storageId, v.getName());
} catch (Exception e) {
logger.warn("error retreiving sotrageId version for item with id {}",itemToDelete.getId(),e);
}
});
idsToDelete.add(((AbstractFileItem) itemToDelete).getContent().getStorageId());
}else if (itemToDelete instanceof FolderItem) {
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(itemToDelete.getId()), Excludes.GET_ONLY_CONTENT , null, true, null);
for (Item item: items)
getAllContentIds(ses, idsToDelete, item, versionHandler);
}
}
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
try {
@ -283,7 +227,7 @@ public class Utils {
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
logger.debug("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
logger.trace("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
NodeIterator ni = destination.getNodes(nameTocheck);
int maxval = 0;
@ -302,29 +246,43 @@ public class Utils {
}
}
public static Node createFolderInternally(Session ses, Node destinationNode, String name, String description, boolean hidden, String login, AccountingHandler accountingHandler) throws BackendGenericError {
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
public static Node createFolderInternally(FolderCreationParameters params, AccountingHandler accountingHandler) throws StorageHubException {
logger.debug("creating folder {} in {}", params.getName(), params.getParentId());
Node destinationNode;
try {
destinationNode = params.getSession().getNodeByIdentifier(params.getParentId());
}catch (RepositoryException e) {
throw new IdNotFoundException(params.getParentId());
}
String uniqueName = Utils.checkExistanceAndGetUniqueName(params.getSession(), destinationNode, params.getName());
FolderItem item = new FolderItem();
Calendar now = Calendar.getInstance();
item.setName(uniqueName);
item.setTitle(uniqueName);
item.setDescription(description);
item.setDescription(params.getDescription());
//TODO: item.setExternalStorage();
//item.setCreationTime(now);
item.setHidden(hidden);
boolean hiddenDestNode= false;
try {
hiddenDestNode = destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean();
}catch (Throwable e) {}
item.setHidden(params.isHidden() || hiddenDestNode);
item.setLastAction(ItemAction.CREATED);
item.setLastModificationTime(now);
item.setLastModifiedBy(login);
item.setOwner(login);
item.setLastModifiedBy(params.getUser());
item.setOwner(params.getUser());
item.setPublicItem(false);
//to inherit hidden property
//item.setHidden(destinationItem.isHidden());
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
if (accountingHandler!=null)
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
if (accountingHandler!=null) {
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), null, params.getSession(), params.getUser(), destinationNode, false);
accountingHandler.createEntryCreate(item.getTitle(), params.getSession(), newNode, params.getUser(), false);
}
return newNode;
}
@ -345,12 +303,19 @@ public class Utils {
item.setPublicItem(false);
item.setValue(value);
//to inherit hidden property
//item.setHidden(destinationItem.isHidden());
try {
item.setHidden(destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean());
} catch (Throwable e) {
item.setHidden(false);
}
Node newNode = new Item2NodeConverter().getNode(destinationNode, item);
if (accountingHandler!=null)
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
if (accountingHandler!=null) {
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, login, destinationNode, false);
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode,login, false);
}
return newNode;
}
@ -380,4 +345,6 @@ public class Utils {
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), login);
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
}
}

View File

@ -14,7 +14,6 @@ import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.slf4j.Logger;
@ -37,7 +36,7 @@ public class AccountingHandler {
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
public void createReadObj(String title, Session ses, Node node, boolean saveHistory ) {
public void createReadObj(String title, Session ses, Node node, String login, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -47,7 +46,7 @@ public class AccountingHandler {
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.READ.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
@ -70,7 +69,26 @@ public class AccountingHandler {
}
}
public void createFileUpdated(String title, Session ses, Node node, boolean saveHistory ) {
public void createEntryCreate(String title, Session ses, Node node, String login, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
node.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
}
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.CREATE.getNodeTypeDefinition());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
if (saveHistory) ses.save();
} catch (RepositoryException e) {
logger.warn("error trying to retrieve accountign node",e);
}
}
public void createFileUpdated(String title, Session ses, Node node, String login, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -80,7 +98,7 @@ public class AccountingHandler {
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UPDATE.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
@ -107,17 +125,17 @@ public class AccountingHandler {
}
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, Node node, boolean saveHistory ) {
public void createFolderAddObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
try {
Node directoryNode = node.getParent();
if (!directoryNode.hasNode(NodeProperty.ACCOUNTING.toString())){
directoryNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
parentNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
}
Node accountingNodeParent = directoryNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.ADD.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(ITEM_TYPE, itemType);
@ -130,7 +148,7 @@ public class AccountingHandler {
}
}
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, Node parentNode, boolean saveHistory ) {
public void createFolderRemoveObj(String title, String itemType, String mimeType, Session ses, String login, Node parentNode, boolean saveHistory ) {
try {
if (!parentNode.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -139,7 +157,7 @@ public class AccountingHandler {
Node accountingNodeParent = parentNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.REMOVAL.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(ITEM_TYPE, itemType);
@ -152,7 +170,7 @@ public class AccountingHandler {
}
}
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, boolean saveHistory ) {
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, String login, boolean saveHistory ) {
try {
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -161,7 +179,7 @@ public class AccountingHandler {
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(MEMBERS, users.toArray(new String[users.size()]));
@ -172,7 +190,7 @@ public class AccountingHandler {
}
}
public void createUnshareFolder(String title, Session ses, Node sharedNode, boolean saveHistory ) {
public void createUnshareFolder(String title, Session ses, String user, Node sharedNode, boolean saveHistory ) {
try {
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -180,8 +198,8 @@ public class AccountingHandler {
}
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.UNSHARE.getNodeTypeDefinition());
accountingNode.setProperty(USER, user);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
@ -191,7 +209,7 @@ public class AccountingHandler {
}
}
public void createRename(String oldTitle, String newTitle, Node node, Session ses, boolean saveHistory ) {
public void createRename(String oldTitle, String newTitle, Node node, String login, Session ses, boolean saveHistory ) {
try {
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -200,7 +218,7 @@ public class AccountingHandler {
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.RENAMING.getNodeTypeDefinition());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(USER, login);
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(OLD_ITEM_NAME, oldTitle);
accountingNode.setProperty(NEW_ITEM_NAME, newTitle);

View File

@ -1,11 +1,14 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.gcube.common.storagehub.model.annotations.RootNode;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,31 +27,37 @@ public class ClassHandler {
private Reflections reflection = new Reflections();
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
private List<String> deprecatedNode = Arrays.asList("nthl:query", "nthl:aquamapsItem", "nthl:timeSeriesItem", "nthl:report", "nthl:reportTemplate", "nthl:workflowReport",
"nthl:workflowTemplate", "nthl:gCubeMetadata", "nthl:gCubeDocument", "nthl:gCubeDocumentLink", "nthl:gCubeImageDocumentLink", "nthl:gCubePDFDocumentLink",
"nthl:gCubeImageDocument", "nthl:gCubePDFDocument", "nthl:gCubeURLDocument", "nthl:gCubeAnnotation", "nthl:externalResourceLink", "nthl:tabularDataLink");
private Map<String, Class<? extends RootItem>> classMap = new HashMap<String, Class<? extends RootItem>>();
private Map<Class<? extends RootItem>, String> typeMap = new HashMap<Class<? extends RootItem>, String>();
@SuppressWarnings("unchecked")
private ClassHandler() {
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
for (Class<?> clazz: classesAnnotated ){
if (Item.class.isAssignableFrom(clazz)) {
if (RootItem.class.isAssignableFrom(clazz)) {
String value = clazz.getAnnotation(RootNode.class).value();
log.debug("loading class {} with value {} ", clazz, value );
classMap.put(value, (Class<? extends Item>) clazz);
typeMap.put((Class<? extends Item>) clazz, value);
classMap.put(value, (Class<? extends RootItem>) clazz);
typeMap.put((Class<? extends RootItem>) clazz, value);
}
}
}
public Class<? extends Item> get(String nodeType){
public Class<? extends RootItem> get(String nodeType){
if (classMap.containsKey(nodeType)) return classMap.get(nodeType);
else return Item.class;
if (deprecatedNode.contains(nodeType)) return Item.class;
return null;
//throw new RuntimeException("mapping not found for nodetype "+ nodeType);
}
public String getNodeType(Class<? extends Item> clazz){
public String getNodeType(Class<? extends RootItem> clazz){
if (typeMap.containsKey(clazz)) return typeMap.get(clazz);
throw new RuntimeException("mapping not found for nodetype "+ clazz.getSimpleName());
}

View File

@ -0,0 +1,101 @@
package org.gcube.data.access.storagehub.handlers;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CompressHandler {
private Logger logger = LoggerFactory.getLogger(CompressHandler.class);
@Inject
FolderPluginHandler pluginHandler;
public Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
Deque<Item> queue = new LinkedList<Item>();
Node currentNode = session.getNodeByIdentifier(directory.getId());
queue.push(directory);
Deque<Item> tempQueue = new LinkedList<Item>();
logger.trace("adding directory {}",currentNode.getPath());
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
if (excludes.contains(item.getId())) continue;
if (item instanceof FolderItem)
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, login, accountingHandler, excludes));
else if (item instanceof AbstractFileItem){
logger.trace("adding file {}",item.getPath());
AbstractFileItem fileItem = (AbstractFileItem) item;
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
queue.addLast(item);
}
}
queue.addAll(tempQueue);
return queue;
}
public void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath) throws Exception{
logger.trace("originalPath is {}",originalPath.toPath());
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
while (!queue.isEmpty()) {
Item item = queue.pop();
if (item instanceof FolderItem) {
actualPath = Paths.getPath(item.getPath());
logger.trace("actualPath is {}",actualPath.toPath());
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
logger.trace("writing dir {}",name);
if (name.isEmpty()) continue;
try {
zos.putNextEntry(new ZipEntry(name));
}finally {
zos.closeEntry();
}
} else if (item instanceof AbstractFileItem){
try {
AbstractFileItem fileItem = (AbstractFileItem)item;
FolderManager manager = pluginHandler.getFolderManager(fileItem);
InputStream streamToWrite = manager.getStorageBackend().download(fileItem.getContent());
if (streamToWrite == null){
logger.warn("discarding item {} ",item.getName());
continue;
}
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
logger.trace("writing file {}",name);
zos.putNextEntry(new ZipEntry(name));
Utils.copyStream(is, zos);
}catch (Exception e) {
logger.warn("error writing item {}", item.getName(),e);
} finally{
zos.closeEntry();
}
zos.flush();
}catch (Throwable e) {
logger.warn("error reading content for item {}", item.getPath(),e);
}
}
}
zos.close();
}
}

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,51 +0,0 @@
package org.gcube.data.access.storagehub.handlers;
import java.io.InputStream;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
@Singleton
public class StorageBackendHandler {
@Inject
private GCubeStorageBackend defaultBackend;
public String move(Item item, FolderItem destination) {
//if item is a folder we have to move everything
return defaultBackend.move(((AbstractFileItem) item).getContent().getStorageId());
}
public String copy(AbstractFileItem item) {
return defaultBackend.copy(item.getContent().getStorageId(), item.getContent().getRemotePath());
}
public MetaInfo upload(InputStream stream, String itemPath) {
return defaultBackend.upload(stream, itemPath);
}
public InputStream download(String id) {
return defaultBackend.getContent(id);
}
public void delete(String id) {
defaultBackend.delete(id);
}
public String getTotalVolume() {
return defaultBackend.getTotalSizeStored();
}
public String getTotalItemsCount() {
return defaultBackend.getTotalItemsCount();
}
}

View File

@ -1,35 +1,45 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.version.Version;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.contentmanagement.blobstorage.service.IClient;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.types.ContentPair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -38,64 +48,127 @@ public class TrashHandler {
private static Logger log = LoggerFactory.getLogger(TrashHandler.class);
@Inject
VersionHandler versionHandler;
ExecutorService executor = Executors.newFixedThreadPool(100);
@Inject
AccountingHandler accountingHandler;
VersionHandler versionHandler;
@Inject
AuthorizationChecker authChecker;
@Inject
AccountingHandler accountingHandler;
@Inject
Item2NodeConverter item2Node;
@Inject
StorageBackendHandler storageHandler;
Node2ItemConverter node2Item;
@Inject
PathUtil pathUtil;
@Inject FolderPluginHandler managerHandler;
@Inject
FolderPluginHandler folderHandler;
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
for (Item item: itemsToDelete) {
removeNodesInternally(ses, item);
removeNodesInternally(ses, item, false);
}
}
private void removeNodesInternally(Session ses, Item itemToDelete) throws RepositoryException, StorageHubException {
public void removeOnlyNodesContent(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
for (Item item: itemsToDelete) {
removeNodesInternally(ses, item, true);
}
}
private void retrieveItemsToDelete(Set<AbstractFileItem> itemsToDelete, Item itemToDelete) throws Exception{
if (itemToDelete instanceof AbstractFileItem) {
itemsToDelete.add(((AbstractFileItem) itemToDelete));
}else if (itemToDelete instanceof FolderItem) {
//only to be sure to not delete shared content
if (itemToDelete.isShared()) return;
List<Item> items = Utils.getItemList((Node) itemToDelete.getRelatedNode(), Excludes.GET_ONLY_CONTENT , null, true, null);
for (Item item: items)
retrieveItemsToDelete(itemsToDelete, item);
}
}
private Set<ContentPair> retrieveContentToDelete(Collection<AbstractFileItem> itemsToDelete) {
Set<ContentPair> contentSet = new HashSet<ContentPair>();
for (AbstractFileItem item: itemsToDelete) {
if (item.getContent()== null || item.getContent().getStorageId()==null) {
log.warn("item with id {} contains null content",item.getId());
continue;
}
try {
Set<String> contentIdsToDelete = new HashSet<>();
FolderManager manager = folderHandler.getFolderManager(item);
contentSet.add(new ContentPair(item.getContent(), manager.getStorageBackend()));
Node nodeToDelete = ses.getNodeByIdentifier(itemToDelete.getId());
List<Version> versions = versionHandler.getContentVersionHistory((Node)item.getRelatedNode());
for (Version version: versions) {
try {
Content content = node2Item.getContentFromVersion(version);
if (content!= null && content.getStorageId()!=null)
contentSet.add(new ContentPair(content, manager.getStorageBackend()));
else log.warn("invalid version {}",version.getName());
}catch (Throwable t) {
log.warn("error retrieving version content for {}",version.getName(),t);
}
}
}catch (Exception e) {
log.warn("item with id {} cannot be deleted",item.getId(),e);
}
}
return contentSet;
}
private void removeNodesInternally(Session ses, Item itemToDelete, boolean onlyContent) throws RepositoryException, StorageHubException {
try {
Set<AbstractFileItem> itemsToDelete = new HashSet<>();
Node nodeToDelete = (Node) itemToDelete.getRelatedNode();
if (itemToDelete instanceof TrashItem) {
List<Item> trashChildren = Utils.getItemList(nodeToDelete, Excludes.GET_ONLY_CONTENT, null, true, null);
for (Item itemContentToRetrieve: trashChildren)
Utils.getAllContentIds(ses, contentIdsToDelete, itemContentToRetrieve, versionHandler);
} else {
Utils.getAllContentIds(ses, contentIdsToDelete, itemToDelete, versionHandler);
}
retrieveItemsToDelete(itemsToDelete, itemContentToRetrieve);
} else
retrieveItemsToDelete(itemsToDelete, itemToDelete);
if (!onlyContent)
nodeToDelete.remove();
log.debug("content ids to remove are {}",contentIdsToDelete);
String ids = itemsToDelete.stream().map((i) -> i.getId()).collect(Collectors.joining(","));
log.debug("content ids to remove are {}",ids);
Set<ContentPair> contentToDelete = retrieveContentToDelete(itemsToDelete);
String user = AuthorizationProvider.instance.get().getClient().getId();
Runnable deleteFromStorageRunnable = AuthorizedTasks.bind(new Runnable() {
@Override
public void run() {
for (String id: contentIdsToDelete) {
for (ContentPair cp: contentToDelete ) {
try {
storageHandler.delete(id);
log.debug("file with id {} correctly removed on storage",id);
cp.getStorageBackend().onDelete(cp.getContent());
log.debug("file with id {} correctly removed from storage {}",cp.getContent().getStorageId(),cp.getStorageBackend().getClass().getSimpleName());
}catch(Throwable t) {
log.warn("error removing file on storage with id {}",id, t);
log.warn("error removing file with id {} from storage {}",cp.getContent().getStorageId(), cp.getStorageBackend().getClass().getSimpleName(), t);
}
}
}
});
new Thread(deleteFromStorageRunnable).start();
executor.execute(deleteFromStorageRunnable);
if (!onlyContent)
ses.save();
}catch (LockException e) {
throw new ItemLockedException("the selected node or his parent is locked", e);
@ -104,20 +177,20 @@ public class TrashHandler {
}
}
public void moveToTrash(Session ses, Node nodeToDelete, Item item) throws RepositoryException, BackendGenericError{
public void moveToTrash(Session ses, Node nodeToDelete, Item item, String login) throws RepositoryException, BackendGenericError{
log.debug("moving node {} to trash ",item.getId());
final Node trashFolder = ses.getNode(Paths.append(Utils.getWorkspacePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
final String login = AuthorizationProvider.instance.get().getClient().getId();
final Node trashFolder = ses.getNode(pathUtil.getTrashPath(login, ses).toPath());
try {
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
log.debug("preparing thrash item");
TrashItem trashItem = new TrashItem();
trashItem.setDeletedBy(AuthorizationProvider.instance.get().getClient().getId());
trashItem.setDeletedBy(login);
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
Calendar now = Calendar.getInstance();
trashItem.setDeletedTime(now);
@ -131,7 +204,7 @@ public class TrashHandler {
trashItem.setName(item.getId());
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
trashItem.setOwner(item.getOwner());
trashItem.setOwner(login);
trashItem.setLastModificationTime(item.getLastModificationTime());
trashItem.setLastModifiedBy(item.getLastModifiedBy());
@ -161,7 +234,7 @@ public class TrashHandler {
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
}
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, ses.getNodeByIdentifier(item.getParentId()), true);
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, login, (Node) item.getRelatedNode(), true);
}catch(Throwable t) {
log.error("error exceuting move to trash",t);
throw new BackendGenericError(t);
@ -172,27 +245,69 @@ public class TrashHandler {
}
public String restoreItem(Session ses, TrashItem item) throws RepositoryException, BackendGenericError, UserNotAuthorizedException{
log.debug("restoring node from trash");
final String login = AuthorizationProvider.instance.get().getClient().getId();
public String restoreItem(Session ses, TrashItem item, FolderItem destination, String login) throws RepositoryException, StorageHubException, BackendGenericError{
log.debug("restoring node from trash with user ");
//final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
Node originalParent = ses.getNodeByIdentifier(item.getOriginalParentId());
authChecker.checkWriteAuthorizationControl(ses, originalParent.getIdentifier(), false );
ses.getWorkspace().getLockManager().lock(originalParent.getPath(), true, true, 0,login);
Node destinationNode= null;
if (destination==null) {
boolean originalParentExists = true;
boolean originalParentTrashed = false;
Node originalParent = null;
try {
originalParent = ses.getNodeByIdentifier(item.getOriginalParentId());
}catch (ItemNotFoundException e) {
originalParentExists = false;
}
Item originalParentItem = null;
if (originalParentExists) {
originalParentItem = node2Item.getItem(originalParent, Excludes.ALL);
originalParentTrashed = originalParentItem.isTrashed();
}
if(originalParentExists && !originalParentTrashed) {
destinationNode = originalParent;
}else {
String homeWS = pathUtil.getWorkspacePath(login).toPath();
Node node = ses.getNode(homeWS);
destinationNode = node;
}
} else {
Node node = (Node)destination.getRelatedNode();
if (!node2Item.checkNodeType(node, FolderItem.class))
throw new InvalidCallParameters("destination Node is not a folder");
destinationNode = node;
}
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true );
ses.getWorkspace().getLockManager().lock(destinationNode.getPath(), true, true, 0,login);
String newNodePath = null;
try {
//the real node is a child of the Trash node
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(item.getId()), Excludes.ALL, null, false, null);
if (items.size()!=1) {
log.warn("a problem occurred restoring item from trash");
throw new BackendGenericError("An error occurred on trash item");
}
Item itemToMove = items.get(0);
String newNodePath = Paths.append(Paths.getPath(originalParent.getPath()), itemToMove.getName()).toPath();
item2Node.updateOwnerOnSubTree(ses.getNodeByIdentifier(itemToMove.getId()), login);
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, itemToMove.getName());
newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()),uniqueName).toPath();
ses.move(itemToMove.getPath(), newNodePath);
Utils.setPropertyOnChangeNode(ses.getNode(newNodePath), login, ItemAction.MOVED);
ses.removeItem(item.getPath());
ses.save();
}catch (Exception e) {
if (ses.getWorkspace().getLockManager().isLocked(destinationNode.getPath()))
ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
}
return ses.getNode(newNodePath).getIdentifier();
}
}

View File

@ -8,6 +8,7 @@ import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
@ -27,9 +28,13 @@ import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -48,25 +53,38 @@ public class UnshareHandler {
@Inject
AuthorizationChecker authChecker;
@Inject
PathUtil pathUtil;
@Inject
Item2NodeConverter item2Node;
public String unshare(Session ses, Set<String> users, Node sharedNode, String login) throws RepositoryException, StorageHubException{
return _unshare(ses, users, sharedNode, login, true);
}
public String unshareForRemoval(Session ses, Set<String> users, Node sharedNode, String login) throws RepositoryException, StorageHubException{
return _unshare(ses, users, sharedNode, login, false);
}
private String _unshare(Session ses, Set<String> users, Node sharedNode, String login, boolean withCopyOnUnshare) throws RepositoryException, StorageHubException{
Item item = node2Item.getItem(sharedNode, Excludes.ALL);
if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder())
if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder()) {
log.warn("this item type cannot be unshared {}",item.getClass().getSimpleName());
return null;
}
SharedFolder sharedItem =(SharedFolder) item;
Set<String> usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getMap().keySet());
usersInSharedFolder.removeAll(users);
if (users==null || users.size()==0)
return unshareAll(login, ses, sharedItem);
return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
if (usersInSharedFolder.size()<=1) {
if (users.size()==1 && users.contains(login))
return unshareAll(sharedItem.getOwner(), ses , sharedItem);
else return unshareAll(login, ses, sharedItem);
return unshareAll(sharedItem.getOwner(), ses , sharedItem, withCopyOnUnshare);
else return unshareAll(login, ses, sharedItem, withCopyOnUnshare);
}
try {
@ -85,7 +103,8 @@ public class UnshareHandler {
}
private String unshareAll(String login, Session ses, SharedFolder item) throws StorageHubException, BackendGenericError, RepositoryException{
private String unshareAll(String login, Session ses, SharedFolder item, boolean withCopyCreation) throws StorageHubException, BackendGenericError, RepositoryException{
log.info("unshare all called");
if (!login.equals(item.getOwner()))
@ -99,21 +118,31 @@ public class UnshareHandler {
throw new ItemLockedException(e);
}
Node unsharedNode;
String unsharedNodeIdentifier =null;
try {
log.debug("user list is empty, I'm going to remove also the shared dir");
//take the admin folder and remove his clone then move the shared folder from share to the user home and change the folder type
String adminDirPath = (String)item.getUsers().getMap().get(login);
String[] splitString = adminDirPath.split("/");
String parentDirectoryId = splitString[0];
String directoryName = splitString[1];
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
log.debug("parent node path is {}/{}",parentNode.getPath(), directoryName);
Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
adminNode.removeShare();
if (withCopyCreation) {
unsharedNode = createUnsharedFolder(ses, parentNode, directoryName, item.getDescription(), login);
Node sharedOwnerNode = null;
NodeIterator it = sharedItemNode.getSharedSet();
while(it.hasNext()) {
Node node = it.nextNode();
log.info("[UNSHARE] checking node {} starts with {} ",node.getPath(),pathUtil.getHome(login).toPath());
if (node.getPath().startsWith(pathUtil.getHome(login).toPath())) {
sharedOwnerNode =node;
break;
}
}
Node shareParent = sharedOwnerNode.getParent();
sharedOwnerNode.removeShare();
Node unsharedNode = createUnsharedFolder(ses, shareParent , item.getTitle() , item.getDescription(), login);
List<Item> itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null);
@ -122,14 +151,33 @@ public class UnshareHandler {
log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath());
ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName()));
}
unsharedNode.getNode(NodeProperty.ACCOUNTING.toString()).remove();
ses.move(sharedItemNode.getNode(NodeProperty.ACCOUNTING.toString()).getPath(), String.format("%s/%s",unsharedNode.getPath(), NodeProperty.ACCOUNTING.toString()));
//set owner of all the unshared items to the caller
item2Node.updateOwnerOnSubTree(unsharedNode, login);
accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), ses, "ALL", unsharedNode, false);
unsharedNodeIdentifier = unsharedNode.getIdentifier();
log.info("[UNSHARE] unshared node id {}",unsharedNodeIdentifier);
ses.save();
}
log.debug("all the users have been removed, the folder is totally unshared");
}catch(Throwable t) {
log.error("erro unsharing all",t);
throw t;
}finally {
ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath());
}
sharedItemNode.removeSharedSet();
ses.save();
log.debug("all the users have been removed, the folder is totally unshared");
return unsharedNode.getIdentifier();
return unsharedNodeIdentifier;
}
@ -137,16 +185,29 @@ public class UnshareHandler {
private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{
log.info("unshare caller");
if (login.equals(item.getOwner()))
throw new InvalidCallParameters("the caller is the owner, the folder cannot be unshared");
if (item.getUsers().getMap().get(login)==null)
throw new InvalidCallParameters("the folder is not shared with user "+login);
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
if (item.getUsers().getMap().get(login)!=null) {
Node usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
usersNode.remove();
Node newUsersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
String parentId = removeSharingForUser(login, ses, item);
item.getUsers().getMap().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try {
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
} catch (Exception e) {
log.error("error adding property to shared node users node under {}",item.getId());
}});
}
Node shareNode = getUserSharingNode(login, ses, item);
String parentId = shareNode.getParent().getIdentifier();
//not returning an error to correct all the old ACL
if (shareNode != null)
shareNode.removeShare();
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
@ -162,20 +223,12 @@ public class UnshareHandler {
if (entryToDelete!=null)
acls.removeAccessControlEntry(entryToDelete);
log.debug("removed Access control entry for user {}",login);
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
usersNode.remove();
Node newUsersNode = sharedItemNode.addNode(NodeConstants.USERS_NAME);
item.getUsers().getMap().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try {
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
} catch (Exception e) {
log.error("error adding property to shared node users node under {}",item.getId());
}});
acm.setPolicy(sharedFolderNode.getPath(), acls);
log.debug("removed Access control entry for user {}",login);
accountingHandler.createUnshareFolder(item.getTitle(), ses, login, sharedFolderNode, false);
ses.save();
return parentId;
@ -183,10 +236,9 @@ public class UnshareHandler {
}
private String unsharePartial(Set<String> usersToUnshare, String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException {
authChecker.checkAdministratorControl(ses, (SharedFolder)item);
log.info("unshare partial");
authChecker.checkAdministratorControl(ses, login, (SharedFolder)item);
if (usersToUnshare.contains(item.getOwner()))
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare owner");
@ -196,7 +248,11 @@ public class UnshareHandler {
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
for (String user : usersToUnshare) {
removeSharingForUser(user, ses, item);
Node userShareNode = getUserSharingNode(user, ses, item);
//not returning an error to correct all the old ACL
if (userShareNode != null)
userShareNode.removeShare();
AccessControlEntry entryToDelete= null;
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
@ -226,6 +282,10 @@ public class UnshareHandler {
acm.setPolicy(sharedFolderNode.getPath(), acls);
for (String user: usersToUnshare) {
accountingHandler.createUnshareFolder(sharedItemNode.getProperty(NodeProperty.TITLE.toString()).getString(), ses, user, sharedItemNode, false);
}
ses.save();
return item.getId();
@ -233,18 +293,34 @@ public class UnshareHandler {
}
private String removeSharingForUser(String user, Session ses, SharedFolder item) throws RepositoryException {
private Node getUserSharingNode(String user, Session ses, SharedFolder item) throws RepositoryException {
Node shareNode = null;
try {
String userDirPath = (String)item.getUsers().getMap().get(user);
if (userDirPath==null) return null;
String[] splitString = userDirPath.split("/");
String parentDirectoryId = splitString[0];
String directoryName = splitString[1];
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
Node userNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
userNode.removeShare();
accountingHandler.createUnshareFolder(directoryName, ses, parentNode, false);
log.debug("directory removed for user {}",user);
return parentDirectoryId;
Node parentNode = null;
parentNode = ses.getNodeByIdentifier(parentDirectoryId);
shareNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
}catch (Throwable e) {
log.warn("users map is not containing a valid value");
}
Node sharedFolderNode = ses.getNodeByIdentifier(item.getId());
if (shareNode==null) {
NodeIterator it = sharedFolderNode.getSharedSet();
while(it.hasNext()) {
Node node = it.nextNode();
if (node.getPath().startsWith(pathUtil.getHome(user).toPath())) {
shareNode =node;
break;
}
}
}
return shareNode;
}

View File

@ -1,59 +0,0 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.SimpleCredentials;
import javax.servlet.ServletContext;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class VREManager {
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
private Map<String, VRE> vreMap = new HashMap<>();
@Inject
RepositoryInitializer repository;
ExecutorService executor = Executors.newFixedThreadPool(5);
SimpleCredentials credentials;
@Inject
public VREManager(ServletContext context) {
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
}
public synchronized VRE getVRE(String completeName) {
logger.trace("requesting VRE {}",completeName);
if (vreMap.containsKey(completeName))
return vreMap.get(completeName);
else
return null;
}
public synchronized VRE putVRE(Item vreFolder) {
logger.trace("inserting VRE {}",vreFolder.getTitle());
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
else {
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, executor);
vreMap.put(vreFolder.getTitle(), toReturn);
return toReturn;
}
}
}

View File

@ -1,192 +0,0 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventJournal;
import javax.jcr.query.Query;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VREQueryRetriever implements Callable<List<Item>> {
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
private static final int CACHE_DIMENSION = 50;
private Repository repository;
private Credentials credentials;
private Item vreFolder;
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
long lastTimestamp =0;
private Node2ItemConverter node2Item = new Node2ItemConverter();
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
super();
this.repository = repository;
this.credentials = credentials;
this.vreFolder = vreFolder;
}
public List<Item> call() {
logger.trace("executing recents task");
Session ses = null;
if (lastTimestamp==0) {
try {
long start = System.currentTimeMillis();
ses = repository.login(credentials);
String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
logger.trace("query for recents is {}",query);
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
jcrQuery.setLimit(CACHE_DIMENSION);
lastTimestamp = System.currentTimeMillis();
NodeIterator it = jcrQuery.execute().getNodes();
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
while (it.hasNext()) {
Node node = it.nextNode();
Item item =node2Item.getItem(node, Excludes.EXCLUDE_ACCOUNTING);
cachedList.add(item);
logger.trace("adding item {} with node {}",item.getTitle(), node.getName());
}
logger.trace("creating objects took {}",System.currentTimeMillis()-start);
if (cachedList.size()<=10) return cachedList;
else return cachedList.subList(0, 10);
} catch (Exception e) {
logger.error("error querying vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}finally{
if (ses!=null)
ses.logout();
logger.trace("recents task finished");
}
} else {
try {
long timestampToUse = lastTimestamp;
lastTimestamp = System.currentTimeMillis();
long start = System.currentTimeMillis();
ses = repository.login(credentials);
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
journalChanged.skipTo(timestampToUse);
logger.trace("getting the journal took {}",System.currentTimeMillis()-start);
int events = 0;
while (journalChanged.hasNext()) {
events++;
Event event = journalChanged.nextEvent();
switch(event.getType()) {
case Event.NODE_ADDED:
if (ses.nodeExists(event.getPath())) {
Node nodeAdded = ses.getNode(event.getPath());
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
logger.trace("node added event received with name {}", nodeAdded.getName());
Item item = node2Item.getItem(nodeAdded, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
insertItemInTheRightPlace(item);
}
}
break;
case Event.PROPERTY_CHANGED:
if (ses.propertyExists(event.getPath())) {
Property property = ses.getProperty(event.getPath());
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
String identifier = property.getParent().getIdentifier();
cachedList.removeIf(i -> i.getId().equals(identifier));
Item item = node2Item.getItem(property.getParent(), Excludes.EXCLUDE_ACCOUNTING);
insertItemInTheRightPlace(item);
}
}
break;
case Event.NODE_REMOVED:
logger.trace("node removed event received with type {}", event.getIdentifier());
cachedList.removeIf(i -> {
try {
return i.getId().equals(event.getIdentifier()) && i.getLastModificationTime().getTime().getTime()<event.getDate();
} catch (RepositoryException e) {
return false;
}
});
break;
case Event.NODE_MOVED:
Node nodeMoved = ses.getNode(event.getPath());
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
logger.trace("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
String identifier = nodeMoved.getIdentifier();
cachedList.removeIf(i -> i.getId().equals(identifier) && !i.getPath().startsWith(vreFolder.getPath()));
}
break;
default:
throw new Exception("error in event handling");
}
}
if (cachedList.size()>CACHE_DIMENSION)
cachedList.subList(51, cachedList.size()).clear();
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
if (cachedList.size()<=10) return cachedList;
else return cachedList.subList(0, 10);
} catch (Exception e) {
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}finally{
if (ses!=null)
ses.logout();
}
}
}
private void insertItemInTheRightPlace(Item item) {
Iterator<Item> it = cachedList.iterator();
int index =0;
while (it.hasNext()) {
Item inListItem = it.next();
if (item.getLastModificationTime().getTime().getTime()>=inListItem.getLastModificationTime().getTime().getTime()) break;
index++;
}
if (index<CACHE_DIMENSION)
cachedList.add(index, item);
}
/* @Override
public void onEvent(EventIterator events) {
logger.trace("on event called");
while (events.hasNext()) {
Event event = events.nextEvent();
try {
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
} catch (RepositoryException e) {
logger.error("error reading event",e);
}
}
}*/
}

View File

@ -22,7 +22,7 @@ public class VersionHandler {
private static final Logger logger = LoggerFactory.getLogger(VersionHandler.class);
public void makeVersionableContent(Node node, Session session){
public void makeVersionableContent(Node node){
try {
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
contentNode.addMixin(JcrConstants.MIX_VERSIONABLE);
@ -31,8 +31,9 @@ public class VersionHandler {
}
}
public void checkinContentNode(Node node, Session session){
public void checkinContentNode(Node node){
try {
Session session = node.getSession();
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
VersionManager versionManager = session.getWorkspace().getVersionManager();
versionManager.checkin(contentNode.getPath());
@ -41,8 +42,9 @@ public class VersionHandler {
}
}
public void checkoutContentNode(Node node, Session session){
public void checkoutContentNode(Node node){
try {
Session session = node.getSession();
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
VersionManager versionManager = session.getWorkspace().getVersionManager();
versionManager.checkout(contentNode.getPath());
@ -51,8 +53,9 @@ public class VersionHandler {
}
}
public List<Version> getContentVersionHistory(Node node, Session session) {
public List<Version> getContentVersionHistory(Node node) {
try {
Session session = node.getSession();
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
VersionManager versionManager = session.getWorkspace().getVersionManager();
VersionHistory history = versionManager.getVersionHistory(contentNode.getPath());

View File

@ -3,6 +3,7 @@ package org.gcube.data.access.storagehub.handlers.content;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;

View File

@ -7,7 +7,6 @@ import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser;
import org.apache.tika.sax.BodyContentHandler;
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
import org.gcube.common.storagehub.model.items.GenericFileItem;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.types.ItemAction;

View File

@ -8,6 +8,8 @@ import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
import org.gcube.common.storagehub.model.items.PDFFileItem;
import org.gcube.common.storagehub.model.items.nodes.PDFContent;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.pdf.PdfReader;
@ -22,9 +24,11 @@ public class PdfHandler implements ContentHandler {
PDFContent content = new PDFContent();
private static final Logger logger = LoggerFactory.getLogger(PdfHandler.class);
@Override
public void initiliseSpecificContent(InputStream is, String fileName, String mimeType) throws Exception {
try {
PdfReader reader = new PdfReader(is);
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
content.setVersion(String.valueOf(reader.getPdfVersion()));
@ -32,10 +36,11 @@ public class PdfHandler implements ContentHandler {
content.setAuthor(fileInfo.containsKey(AUTHOR)?fileInfo.get(AUTHOR):"n/a");
content.setProducer(fileInfo.containsKey(PRODUCER)?fileInfo.get(PRODUCER):"n/a");
content.setTitle(fileInfo.containsKey(TITLE)?fileInfo.get(TITLE):"n/a");
content.setMimeType(mimeType);
} catch (Exception e) {
logger.warn("{} is not a valid pdf", fileName, e);
}
@Override
content.setMimeType(mimeType);
} @Override
public PDFContent getContent() {
return content;
}

View File

@ -1,4 +1,4 @@
package org.gcube.data.access.storagehub.handlers;
package org.gcube.data.access.storagehub.handlers.items;
import java.lang.reflect.Field;
import java.net.URL;
@ -31,11 +31,16 @@ import org.gcube.common.storagehub.model.annotations.ListNodes;
import org.gcube.common.storagehub.model.annotations.MapAttribute;
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
import org.gcube.common.storagehub.model.annotations.RootNode;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.NodeChildrenFilterIterator;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -44,7 +49,7 @@ public class Item2NodeConverter {
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
public <T extends Item> Node getNode(Node parentNode, T item){
public <T extends RootItem> Node getNode(Node parentNode, T item){
try {
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
@ -56,7 +61,7 @@ public class Item2NodeConverter {
field.setAccessible(true);
try{
//Class<?> returnType = field.getType();
logger.debug("creating node - added field {}",field.getName());
logger.trace("creating node - added field {}",field.getName());
Values values = getObjectValue(field.getType(), field.get(item));
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue());
@ -67,14 +72,14 @@ public class Item2NodeConverter {
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
if (nodeAttribute.isReadOnly()) continue;
String nodeName = nodeAttribute.value();
logger.debug("retrieving field node "+field.getName());
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Object obj = field.get(item);
if (obj!=null)
iterateItemNodeAttributeFields(obj, newNode, nodeName);
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.debug("error setting value",e);
}
@ -113,7 +118,7 @@ public class Item2NodeConverter {
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
else newNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.debug("error setting value",e);
}
} else if (field.isAnnotationPresent(MapAttribute.class)){
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
@ -125,11 +130,11 @@ public class Item2NodeConverter {
if (values.isMulti()) newNode.setProperty(entry.getKey(), values.getValues());
else newNode.setProperty(entry.getKey(), values.getValue());
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.debug("error setting value",e);
}
} else if (field.isAnnotationPresent(ListNodes.class)){
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
logger.trace("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
field.setAccessible(true);
List<Object> toSetList = (List<Object>) field.get(object);
@ -145,7 +150,7 @@ public class Item2NodeConverter {
}
@SuppressWarnings({ "rawtypes" })
private Values getObjectValue(Class returnType, Object value) throws Exception{
public static Values getObjectValue(Class returnType, Object value) throws Exception{
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
@ -204,7 +209,7 @@ public class Item2NodeConverter {
else contentNode.setProperty(attribute.value(), values.getValue());
} catch (Exception e ) {
logger.warn("error setting value for attribute "+attribute.value(),e);
logger.debug("error setting value for attribute "+attribute.value(),e);
}
}
}
@ -216,11 +221,41 @@ public class Item2NodeConverter {
}
public void updateHidden(Node node, Boolean hidden,String login) throws RepositoryException {
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
node.setProperty(NodeProperty.HIDDEN.toString(), hidden);
}
public void updateDescription(Node node, String description,String login) throws RepositoryException {
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
node.setProperty(NodeProperty.DESCRIPTION.toString(), description);
}
public void updateOwnerOnSubTree(Node node, String owner) throws RepositoryException, BackendGenericError {
Class<? extends Item> classToHandle = (Class<? extends Item>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return;
if (classToHandle.isAssignableFrom(FolderItem.class)) {
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(node);
while (iterator.hasNext()) {
Node nextNode = iterator.next();
updateOwnerOnSubTree(nextNode, owner);
}
}
updateOwner(node, owner);
}
public void updateOwner(Node node, String owner) throws RepositoryException {
//Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
if (node.hasProperty(NodeProperty.PORTAL_LOGIN.toString()))
node.setProperty(NodeProperty.PORTAL_LOGIN.toString(), owner);
else logger.debug("cannot set new owner to {} "+node.getPath());
}
public <I extends Item> void updateMetadataNode(Node node, Map<String, Object> meta, String login){
try {
//TODO: make a method to update item not only metadata, check if the new metadata has an intersection with the old one to remove properties not needed
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
Node metadataNode;
@ -246,7 +281,7 @@ public class Item2NodeConverter {
}
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.debug("error setting value",e);
}
}

View File

@ -0,0 +1,400 @@
package org.gcube.data.access.storagehub.handlers.items;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.storages.StorageBackend;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.MultipleOutputStream;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
import org.gcube.data.access.storagehub.handlers.items.builders.CreateParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ItemHandler {
@Inject
AccountingHandler accountingHandler;
@Inject
ContentHandlerFactory contenthandlerFactory;
@Inject
AuthorizationChecker authChecker;
@Inject
VersionHandler versionHandler;
@Inject
FolderPluginHandler pluginHandler;
private static ExecutorService executor = Executors.newFixedThreadPool(100);
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
private static Logger log = LoggerFactory.getLogger(ItemHandler.class);
public <T extends CreateParameters> String create(T parameters) throws Exception{
Session ses = parameters.getSession();
Node destination;
try {
destination = ses.getNodeByIdentifier(parameters.getParentId());
}catch(RepositoryException inf) {
throw new IdNotFoundException(parameters.getParentId());
}
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, parameters.getUser(), destination.getIdentifier(), true);
try {
Node newNode = null;
switch (parameters.getMangedType()) {
case FILE:
newNode = create((FileCreationParameters)parameters, destination);
break;
case FOLDER:
newNode = create((FolderCreationParameters)parameters, destination);
break;
case ARCHIVE:
newNode = create((ArchiveStructureCreationParameter)parameters, destination);
break;
case URL:
newNode = create((URLCreationParameters) parameters, destination);
break;
case GCUBEITEM:
newNode = create((GCubeItemCreationParameters) parameters, destination);
break;
default:
throw new InvalidCallParameters("Item not supported");
}
log.debug("item with id {} correctly created",newNode.getIdentifier());
return newNode.getIdentifier();
} finally {
if (parameters.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
parameters.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
}
}
private Node create(FolderCreationParameters params, Node destination) throws Exception{
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createFolderInternally(params, accountingHandler);
params.getSession().save();
return newNode;
}
private Node create(FileCreationParameters params, Node destination) throws Exception{
Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(), params.getDescription(), params.getUser(), true);
params.getSession().save();
versionHandler.checkinContentNode(newNode);
log.info("file with id {} correctly created",newNode.getIdentifier());
return newNode;
}
private Node create(URLCreationParameters params, Node destination) throws Exception{
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createURLInternally(params.getSession(), destination, params.getName(), params.getUrl(), params.getDescription(), params.getUser(), accountingHandler);
params.getSession().save();
return newNode;
}
private Node create(ArchiveStructureCreationParameter params, Node destination) throws Exception{
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(params.getParentFolderName()).author(params.getUser()).on(destination.getIdentifier()).with(params.getSession()).build();
Node parentDirectoryNode = Utils.createFolderInternally(folderParameters, accountingHandler);
params.getSession().save();
try {
if (params.getSession().getWorkspace().getLockManager().isLocked(destination.getPath()))
params.getSession().getWorkspace().getLockManager().unlock(destination.getPath());
} catch (Throwable t){
log.warn("error unlocking {}", destination.getPath(), t);
}
Set<Node> fileNodes = new HashSet<>();
HashMap<String, Node> directoryNodeMap = new HashMap<>();
try (ArchiveInputStream input = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(params.getStream(), 1024*64))){
ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {
String entirePath = entry.getName();
if (entry.isDirectory()) {
log.debug("creating directory with entire path {} ", entirePath);
createPath(entirePath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
continue;
} else {
try {
String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2");
String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1");
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
Node fileNode = null;
if (parentPath.isEmpty())
fileNode = createFileItemInternally(params.getSession(), parentDirectoryNode, input, name, "", params.getUser(), false);
else {
Node parentNode = directoryNodeMap.get(parentPath);
if (parentNode ==null)
parentNode = createPath(parentPath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
fileNode = createFileItemInternally(params.getSession(), parentNode, input, name, "", params.getUser(), false);
}
fileNodes.add(fileNode);
}catch(Exception e) {
log.warn("error getting file {}",entry.getName(),e);
}
}
}
}
params.getSession().save();
for (Node node : fileNodes)
versionHandler.checkinContentNode(node);
return parentDirectoryNode;
}
private Node createPath(String parentPath, Map<String, Node> directoryNodeMap, Node rootNode, Session ses, String user) throws StorageHubException, RepositoryException{
String[] parentPathSplit = parentPath.split("/");
String name = parentPathSplit[parentPathSplit.length-1];
StringBuilder relParentPath = new StringBuilder();
for (int i = 0 ; i<=parentPathSplit.length-2; i++)
relParentPath.append(parentPathSplit[i]).append("/");
if (relParentPath.toString().isEmpty()) {
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(rootNode.getIdentifier()).with(ses).build();
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
directoryNodeMap.put(name+"/", createdNode);
return createdNode;
}else {
Node relParentNode = directoryNodeMap.get(relParentPath.toString());
if (relParentNode==null) {
relParentNode = createPath(relParentPath.toString(), directoryNodeMap, rootNode, ses, user);
}
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).author(user).on(relParentNode.getIdentifier()).with(ses).build();
Node createdNode = Utils.createFolderInternally(folderParameters, accountingHandler);
directoryNodeMap.put(relParentPath.append(name).append("/").toString(), createdNode);
return createdNode;
}
}
private Node create(GCubeItemCreationParameters params, Node destination) throws Exception{
Utils.acquireLockWithWait(params.getSession(), destination.getPath(), false, params.getUser(), 10);
Node newNode = Utils.createGcubeItemInternally(params.getSession(), destination, params.getItem().getName(), params.getItem().getDescription(), params.getUser(), params.getItem(), accountingHandler);
params.getSession().save();
return newNode;
}
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, StorageHubException{
Node newNode;
FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL);
FolderManager folderManager = pluginHandler.getFolderManager(destinationItem);
StorageBackend storageBackend = folderManager.getStorageBackend();
String relativePath = destinationNode.getPath();
if (destinationItem.isExternalManaged())
relativePath = relativePath.replace(folderManager.getRootFolder().getPath(), "");
String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath();
if (ses.nodeExists(newNodePath)) {
if (!folderManager.manageVersion())
throw new InvalidCallParameters("storage for plugin "+folderManager.getClass().getName()+" doesn't support versioning");
newNode = ses.getNode(newNodePath);
authChecker.checkWriteAuthorizationControl(ses, login, newNode.getIdentifier(), false);
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath,login);
if (withLock) {
try {
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
}catch (LockException le) {
throw new ItemLockedException(le);
}
}
try {
versionHandler.checkoutContentNode(newNode);
log.trace("replacing content of class {}",item.getContent().getClass());
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, login, false);
ses.save();
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
}
}
else {
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true);
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath, login);
if (withLock) {
try {
log.debug("trying to acquire lock");
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
}catch (LockException le) {
throw new ItemLockedException(le);
}
}
try {
newNode = item2Node.getNode(destinationNode, item);
accountingHandler.createEntryCreate(item.getTitle(), ses, newNode, login, false);
ses.save();
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
}
versionHandler.makeVersionableContent(newNode);
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, login, destinationNode, false);
}
return newNode;
}
private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name, String description, String relPath, String login) throws BackendGenericError{
ContentHandler handler = getContentHandler(stream, storageBackend, name, relPath, login);
AbstractFileItem item =handler.buildItem(name, description, login);
return item ;
}
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError {
final MultipleOutputStream mos;
try{
mos = new MultipleOutputStream(stream, 2);
}catch (IOException e) {
throw new BackendGenericError(e);
}
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
@Override
public ContentHandler call() throws Exception {
ContentHandler handler =null;
long start = System.currentTimeMillis();
log.debug("TIMING: reading the mimetype - start");
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
org.apache.tika.mime.MediaType mediaType = null;
TikaConfig config = TikaConfig.getDefaultConfig();
Detector detector = config.getDetector();
TikaInputStream stream = TikaInputStream.get(is1);
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, name);
mediaType = detector.detect(stream, metadata);
String mimeType = mediaType.getBaseType().toString();
handler = contenthandlerFactory.create(mimeType);
is1.reset();
handler.initiliseSpecificContent(is1, name, mimeType);
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
} catch (Throwable e) {
log.error("error retrieving mimeType",e);
throw new RuntimeException(e);
}
return handler;
}
};
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
@Override
public MetaInfo call() throws Exception {
try(InputStream is1 = mos.get()){
MetaInfo info = storageBackend.upload(is1, relPath, name);
return info;
}catch (Throwable e) {
log.error("error writing content",e );
throw e;
}
}
};
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
long start = System.currentTimeMillis();
log.debug("TIMING: writing the stream - start");
try {
mos.startWriting();
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
ContentHandler handler = detectorF.get();
MetaInfo info = uploaderF.get();
handler.getContent().setData(NodeConstants.CONTENT_NAME);
handler.getContent().setStorageId(info.getStorageId());
handler.getContent().setSize(info.getSize());
handler.getContent().setRemotePath(info.getRemotePath());
return handler;
}catch (Exception e) {
throw new BackendGenericError(e);
}
}
}

View File

@ -1,4 +1,4 @@
package org.gcube.data.access.storagehub.handlers;
package org.gcube.data.access.storagehub.handlers.items;
import java.lang.reflect.Field;
import java.net.URI;
@ -21,21 +21,27 @@ import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.version.Version;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.annotations.Attribute;
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
import org.gcube.common.storagehub.model.annotations.ListNodes;
import org.gcube.common.storagehub.model.annotations.MapAttribute;
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.ExternalFolder;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.reflections.Configuration;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
@ -43,34 +49,55 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
@SuppressWarnings("rawtypes")
public class Node2ItemConverter {
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
private static HashMap<Class, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
@SuppressWarnings("unchecked")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return null;
if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
else return retrieveItem(node, excludes, classToHandle);
}
public <T extends Item> T getItem(String nodeIdentifier, Session session, List<String> excludes) throws RepositoryException, BackendGenericError{
Node node = session.getNodeByIdentifier(nodeIdentifier);
return getItem(node, excludes);
}
public <T extends Item> T getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError{
@SuppressWarnings("unchecked")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
/*Node nodeToRetrieve= node;
if (SharedFolder.class.isAssignableFrom(classToHandle)) {
NodeIterator it= node.getSharedSet();
while (it.hasNext()) {
Node sharedNode = it.nextNode();
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath().toPath())) {
nodeToRetrieve = sharedNode;
if (classToHandle==null) return null;
T item = retrieveItem(node, excludes, classToHandle);
return item;
}
public Content getContentFromVersion(Version node) throws RepositoryException, BackendGenericError{
Content content = new Content();
setGenericFields(node.getFrozenNode(), Content.class, null, content);
return content;
}
}*/
return retrieveItem(node, excludes, classToHandle);
public Message getMessageItem(Node node) throws RepositoryException{
if (!(node.getPrimaryNodeType().getName().equals("nthl:itemSentRequest")
|| node.getPrimaryNodeType().getName().equals("nthl:itemSentRequestSH")))
return null;
Message msg = new Message();
try {
Node attachmentNode = node.getNode(Constants.ATTACHMENTNODE_NAME);
msg.setWithAttachments(attachmentNode.hasNodes());
}catch (Throwable e) {
msg.setWithAttachments(false);
}
setRootItemCommonFields(node, Collections.emptyList(), Message.class, msg);
return msg;
}
@ -81,79 +108,99 @@ public class Node2ItemConverter {
}catch (Exception e) {
throw new BackendGenericError(e);
}
item.setId(node.getIdentifier());
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
item.setLocked(node.isLocked());
item.setPrimaryType(node.getPrimaryNodeType().getName());
Item parent = null ;
if (item instanceof SharedFolder) {
logger.trace("I'm in a Shared Folder");
item.setShared(true);
}else {
try {
parent = getItem(node.getParent(), Excludes.ALL);
item.setShared(parent.isShared());
item.setShared(SharedFolder.class.isInstance(item) ||
hasTypedParent(node, SharedFolder.class));
}catch (Exception e) {
item.setShared(false);
}
}
if (item instanceof TrashItem)
item.setTrashed(true);
else {
try {
if (parent==null)
parent = getItem(node.getParent(), Excludes.ALL);
item.setTrashed(parent.isTrashed());
item.setTrashed(TrashItem.class.isInstance(item) ||
hasTypedParent(node, TrashItem.class));
}catch (Exception e) {
item.setTrashed(false);
}
}
try {
item.setParentId(node.getParent().getIdentifier());
item.setParentPath(node.getParent().getPath());
item.setExternalManaged(hasTypedParent(node, ExternalFolder.class));
}catch (Exception e) {
item.setExternalManaged(false);
}
item.setLocked(node.isLocked());
setRootItemCommonFields(node, excludes, classToHandle, item);
return item;
}
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
if(node==null) return false;
return checkNodeType(node, parentType) || hasTypedParent(node.getParent(), parentType);
}
private <T extends RootItem> void setRootItemCommonFields(Node node, List<String> excludes, Class<T> classToHandle, T instance) throws RepositoryException{
try{
instance.setParentId(node.getParent().getIdentifier());
instance.setParentPath(node.getParent().getPath());
}catch (Throwable e) {
logger.trace("Root node doesn't have a parent");
}
instance.setRelatedNode(node);
instance.setId(node.getIdentifier());
instance.setName(Text.unescapeIllegalJcrChars(node.getName()));
instance.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
instance.setPrimaryType(node.getPrimaryNodeType().getName());
setGenericFields(node, classToHandle, excludes, instance);
}
private <T> void setGenericFields(Node node, Class<T> classToHandle,List<String> excludes, T instance){
for (Field field : retrieveAllFields(classToHandle)){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
field.setAccessible(true);
try{
Class<?> returnType = field.getType();
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
logger.debug("retrieve item - added field {}",field.getName());
field.set(instance, getPropertyValue(returnType, node.getProperty(attribute.value())));
logger.trace("retrieve item - added field {}",field.getName());
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) {
logger.warn("error setting value for property {} ",attribute.value());
logger.debug("error setting value for property {} ",attribute.value());
}
} else if (field.isAnnotationPresent(NodeAttribute.class)){
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
//for now it excludes only first level node
if (excludes!=null && excludes.contains(fieldNodeName)) continue;
//for now it excludes only first level node
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Node fieldNode = node.getNode(fieldNodeName);
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
field.set(item, iterateNodeAttributeFields(field.getType(), fieldNode));
field.set(instance, iterateNodeAttributeFields(field.getType(), fieldNode));
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} node",fieldNodeName);
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.debug("error setting value",e);
}
}
}
return item;
}
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
@ -163,13 +210,12 @@ public class Node2ItemConverter {
Attribute attribute = field.getAnnotation(Attribute.class);
field.setAccessible(true);
try{
@SuppressWarnings("rawtypes")
Class returnType = field.getType();
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) {
logger.warn("error setting value {}",e.getMessage());
logger.debug("error setting value {}",e.getMessage());
}
} else if (field.isAnnotationPresent(MapAttribute.class)){
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
@ -188,7 +234,7 @@ public class Node2ItemConverter {
}catch(PathNotFoundException e){
logger.warn("the property {} is not mapped",prop.getName());
} catch (Exception e ) {
logger.warn("error setting value {}",e.getMessage());
logger.debug("error setting value {}",e.getMessage());
}
}
}
@ -252,7 +298,7 @@ public class Node2ItemConverter {
return obj;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({ "unchecked" })
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
if (returnType.equals(String.class)) return prop.getString();
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
@ -317,10 +363,11 @@ public class Node2ItemConverter {
return values;
}
//Checks if a node is a subtype of classToCompare
public boolean checkNodeType(Node node, Class<? extends Item> classToCompare) throws BackendGenericError{
try {
logger.info("class from nodetype is {} and class to compare is {}",ClassHandler.instance().get(node.getPrimaryNodeType().getName()), classToCompare);
logger.trace("class from nodetype is {} and class to compare is {}",ClassHandler.instance().get(node.getPrimaryNodeType().getName()), classToCompare);
return classToCompare.isAssignableFrom(ClassHandler.instance().get(node.getPrimaryNodeType().getName()));

View File

@ -0,0 +1,75 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.io.InputStream;
import java.util.Objects;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
public class ArchiveStructureCreationParameter extends CreateParameters {
String parentFolderName;
FormDataContentDisposition fileDetails;
InputStream stream;
protected ArchiveStructureCreationParameter() {}
public String getParentFolderName() {
return parentFolderName;
}
public FormDataContentDisposition getFileDetails() {
return fileDetails;
}
public InputStream getStream() {
return stream;
}
@Override
protected boolean isValid() {
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream) && Objects.nonNull(fileDetails);
}
@Override
public String toString() {
return "FileCreationParameters [parentFolder=" + parentFolderName + ", fileDetails=" + fileDetails
+ ", parentId=" + parentId + ", user=" + user + "]";
}
public static ArchiveCreationBuilder builder() {
return new ArchiveCreationBuilder();
}
public static class ArchiveCreationBuilder extends ItemsParameterBuilder<ArchiveStructureCreationParameter>{
private ArchiveCreationBuilder() {
super(new ArchiveStructureCreationParameter());
}
public ArchiveCreationBuilder parentName(String name) {
parameters.parentFolderName = name;
return this;
}
public ArchiveCreationBuilder stream(InputStream stream) {
parameters.stream = stream;
return this;
}
public ArchiveCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
parameters.fileDetails = fileDetails;
return this;
}
}
@Override
public ManagedType getMangedType() {
return ManagedType.ARCHIVE;
}
}

View File

@ -0,0 +1,38 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import javax.jcr.Session;
public abstract class CreateParameters {
public enum ManagedType {
FILE,
FOLDER,
ARCHIVE,
URL,
GCUBEITEM;
}
String parentId;
Session session;
String user;
protected CreateParameters() {}
public abstract ManagedType getMangedType();
public String getParentId() {
return parentId;
}
public Session getSession() {
return session;
}
public String getUser() {
return user;
}
protected abstract boolean isValid();
public abstract String toString();
}

View File

@ -0,0 +1,82 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.io.InputStream;
import java.util.Objects;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
public class FileCreationParameters extends CreateParameters {
String name;
String description;
FormDataContentDisposition fileDetails;
InputStream stream;
protected FileCreationParameters() {}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public FormDataContentDisposition getFileDetails() {
return fileDetails;
}
public InputStream getStream() {
return stream;
}
@Override
protected boolean isValid() {
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(stream);
}
@Override
public String toString() {
return "FileCreationParameters [name=" + name + ", description=" + description + ", fileDetails=" + fileDetails
+ ", parentId=" + parentId + ", user=" + user + "]";
}
public static FileCreationBuilder builder() {
return new FileCreationBuilder();
}
public static class FileCreationBuilder extends ItemsParameterBuilder<FileCreationParameters>{
private FileCreationBuilder() {
super(new FileCreationParameters());
}
public FileCreationBuilder name(String name) {
parameters.name = name;
return this;
}
public FileCreationBuilder description(String description) {
parameters.description = description;
return this;
}
public FileCreationBuilder stream(InputStream stream) {
parameters.stream = stream;
return this;
}
public FileCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
parameters.fileDetails = fileDetails;
return this;
}
}
@Override
public ManagedType getMangedType() {
return ManagedType.FILE;
}
}

View File

@ -0,0 +1,105 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.util.Objects;
import org.gcube.common.storagehub.model.plugins.PluginParameters;
public class FolderCreationParameters extends CreateParameters {
private String name;
private String description="";
private boolean hidden = false;
private String externalPluginName = null;
private PluginParameters externalPluginParameters = null;
protected FolderCreationParameters() {}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public boolean isHidden() {
return hidden;
}
public boolean isExternal() {
return externalPluginName!=null;
}
public String getPluginName(String name) {
return this.externalPluginName;
}
public PluginParameters getPluginParameters() {
return externalPluginParameters;
}
@Override
protected boolean isValid() {
return Objects.nonNull(name) && Objects.nonNull(description);
}
@Override
public String toString() {
return "FolderCreationParameters [name=" + name + ", description=" + description + ", hidden=" + hidden
+ ", parentId=" + parentId + ", session=" + session + ", user=" + user + "]";
}
public static FolderCreationBuilder builder() {
return new FolderCreationBuilder();
}
public static class FolderCreationBuilder extends ItemsParameterBuilder<FolderCreationParameters>{
private FolderCreationBuilder() {
super(new FolderCreationParameters());
}
public FolderCreationBuilder name(String name) {
parameters.name = name;
return this;
}
public FolderCreationBuilder description(String description) {
parameters.description = description;
return this;
}
public ExternalFolderCreationBuilder onRepository(String pluginName) {
return new ExternalFolderCreationBuilder(pluginName, this);
}
public FolderCreationBuilder hidden(boolean hidden) {
parameters.hidden = hidden;
return this;
}
}
public static class ExternalFolderCreationBuilder {
FolderCreationBuilder cb;
protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
this.cb.parameters.externalPluginName = pluginName;
}
public FolderCreationBuilder withParameters(PluginParameters params){
this.cb.parameters.externalPluginParameters = params;
return this.cb;
}
}
@Override
public ManagedType getMangedType() {
return ManagedType.FOLDER;
}
}

View File

@ -0,0 +1,49 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.util.Objects;
import org.gcube.common.storagehub.model.items.GCubeItem;
public class GCubeItemCreationParameters extends CreateParameters{
GCubeItem item;
protected GCubeItemCreationParameters() {}
public GCubeItem getItem() {
return item;
}
@Override
protected boolean isValid() {
return Objects.nonNull(item);
}
@Override
public String toString() {
return "GCubeItemCreationParameters [item=" + item + ", parentId=" + parentId + ", user=" + user + "]";
}
public static GCubeItemCreationBuilder builder() {
return new GCubeItemCreationBuilder();
}
public static class GCubeItemCreationBuilder extends ItemsParameterBuilder<GCubeItemCreationParameters>{
private GCubeItemCreationBuilder() {
super(new GCubeItemCreationParameters());
}
public GCubeItemCreationBuilder item(GCubeItem item) {
parameters.item = item;
return this;
}
}
@Override
public ManagedType getMangedType() {
return ManagedType.GCUBEITEM;
}
}

View File

@ -0,0 +1,39 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.util.Objects;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
public abstract class ItemsParameterBuilder<T extends CreateParameters> {
T parameters;
protected ItemsParameterBuilder(T parameters) {
super();
this.parameters = parameters;
}
public ItemsParameterBuilder<T> on(String parentId) {
parameters.parentId = parentId;
return this;
}
public ItemsParameterBuilder<T> author(String author) {
parameters.user = author;
return this;
}
public ItemsParameterBuilder<T> with(Session session){
parameters.session = session;
return this;
}
public T build() throws InvalidCallParameters {
if (!(parameters.isValid() && Objects.nonNull(parameters.parentId)))
throw new InvalidCallParameters("invalid call");
return parameters;
}
}

View File

@ -0,0 +1,69 @@
package org.gcube.data.access.storagehub.handlers.items.builders;
import java.net.URL;
import java.util.Objects;
public class URLCreationParameters extends CreateParameters {
String name;
String description;
URL url;
protected URLCreationParameters() {}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public URL getUrl() {
return url;
}
@Override
protected boolean isValid() {
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(url);
}
@Override
public String toString() {
return "URLCreationParameters [name=" + name + ", description=" + description + ", url=" + url + ", parentId="
+ parentId + ", user=" + user + "]";
}
public static URLCreationBuilder builder() {
return new URLCreationBuilder();
}
public static class URLCreationBuilder extends ItemsParameterBuilder<URLCreationParameters>{
private URLCreationBuilder() {
super(new URLCreationParameters());
}
public URLCreationBuilder name(String name) {
parameters.name = name;
return this;
}
public URLCreationBuilder description(String description) {
parameters.description = description;
return this;
}
public URLCreationBuilder url(URL url) {
parameters.url = url;
return this;
}
}
@Override
public ManagedType getMangedType() {
return ManagedType.URL;
}
}

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,4 +1,4 @@
package org.gcube.data.access.storagehub.handlers;
package org.gcube.data.access.storagehub.handlers.vres;
import java.util.List;
import java.util.concurrent.ExecutorService;
@ -9,6 +9,7 @@ import javax.jcr.SimpleCredentials;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -21,11 +22,11 @@ public class VRE {
private VREQueryRetriever vreQueryRetriever;
private ExecutorService executor;
public VRE(Item item, Repository repository, SimpleCredentials credentials, ExecutorService executor) {
protected VRE(Item item, Repository repository, SimpleCredentials credentials, Node2ItemConverter node2Item, ExecutorService executor) {
super();
this.vreFolder = item;
this.executor = executor;
vreQueryRetriever = new VREQueryRetriever(repository, credentials, vreFolder);
vreQueryRetriever = new VREQueryRetriever(repository, credentials, node2Item, vreFolder);
result = executor.submit(vreQueryRetriever);
}

View File

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

View File

@ -0,0 +1,274 @@
package org.gcube.data.access.storagehub.handlers.vres;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventJournal;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VREQueryRetriever implements Callable<List<Item>> {
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
private static final int CACHE_DIMENSION = 50;
private Repository repository;
private Credentials credentials;
private Item vreFolder;
Map<String, Long> cachedMap = new HashMap<>(CACHE_DIMENSION);
long lastTimestamp =0;
long doTime= 0;
boolean underRedo = false;
Node2ItemConverter node2Item;
private static int TIME_MEASURE = Calendar.MINUTE;
private static int VALUE_TIME_BEFORE = 30;
public VREQueryRetriever(Repository repository, Credentials credentials, Node2ItemConverter node2Item, Item vreFolder) {
super();
this.repository = repository;
this.credentials = credentials;
this.vreFolder = vreFolder;
this.node2Item = node2Item;
}
public List<Item> call() {
Session ses = null;
try {
ses = repository.login(credentials);
Calendar now = Calendar.getInstance();
now.add(TIME_MEASURE, -1*Math.abs(VALUE_TIME_BEFORE));
if (doTime> now.getTimeInMillis() || underRedo) {
logger.debug("executing recents task for {} (cahced result)",vreFolder.getTitle());
return correctValues(ses, cachedMap);
}else {
logger.debug("executing recents task for {} (redoing it)",vreFolder.getTitle());
List<Item> toReturn = redo(ses);
doTime = System.currentTimeMillis();
return toReturn;
}
}catch (Exception e) {
logger.error("error preparing recents for folder {}", vreFolder.getTitle(),e);
return Collections.emptyList();
}finally{
if (ses!=null)
ses.logout();
logger.debug("recents task finished");
}
}
public synchronized List<Item> redo(Session ses) {
underRedo = true;
try {
Map<String, Long> tempCachedMap = new HashMap<>(cachedMap);
if (cachedMap.isEmpty())
init(ses, tempCachedMap);
else {
logger.debug("redoing recents for {}",vreFolder.getTitle());
update(ses, tempCachedMap);
}
cachedMap = tempCachedMap;
return correctValues(ses, tempCachedMap);
}finally{
underRedo = false;
}
}
private List<Item> correctValues(Session ses, Map<String, Long> tempCachedMap){
logger.debug("preparing returning values for {}",vreFolder.getTitle());
long start = System.currentTimeMillis();
List<Map.Entry<String, Long>> list = new LinkedList<>(tempCachedMap.entrySet());
list.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue())*-1);
if (list.size()>CACHE_DIMENSION)
for (int index = CACHE_DIMENSION-1; index< list.size() ; index++)
tempCachedMap.remove(list.get(index).getKey());
List<String> cachedIds = list.stream().map(m -> m.getKey()).collect(Collectors.toList());
if (cachedIds.size()>10)
cachedIds = cachedIds.subList(0, 10);
List<Item> result = new ArrayList<>(10);
for (String id: cachedIds) {
try {
Item item = node2Item.getItem(id, ses, Excludes.EXCLUDE_ACCOUNTING);
if (item!=null)
result.add(item);
else logger.warn("item with id {} is null",id);
} catch (BackendGenericError | RepositoryException e) { }
}
logger.debug("returning values prepared in {} for {}",System.currentTimeMillis()-start,vreFolder.getTitle());
return result;
}
private void insertItemInTheRightPlace(Item item, Map<String, Long> tempCachedMap) {
long lastModifiedTime = item.getLastModificationTime().getTimeInMillis();
if (tempCachedMap.size()<CACHE_DIMENSION || lastModifiedTime>Collections.min(tempCachedMap.values()))
tempCachedMap.put(item.getId(), lastModifiedTime);
}
private void init(Session ses,Map<String, Long> tempCachedMap){
try {
long start = System.currentTimeMillis();
lastTimestamp = System.currentTimeMillis();
Node vreFolderNode = ses.getNodeByIdentifier(vreFolder.getId());
logger.debug("starting visiting children for {}",vreFolder.getTitle());
visitChildren(vreFolderNode, tempCachedMap);
logger.debug("initializing recents for {} took {}",vreFolder.getTitle(),System.currentTimeMillis()-start);
} catch (Exception e) {
logger.error("error querying vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}
}
private void update(Session ses, Map<String, Long> tempCachedMap) {
try {
long timestampToUse = lastTimestamp;
lastTimestamp = System.currentTimeMillis();
long start = System.currentTimeMillis();
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
journalChanged.skipTo(timestampToUse);
logger.debug("getting the journal took {}",System.currentTimeMillis()-start);
int events = 0;
//TODO: manage hidden nodes
while (journalChanged.hasNext()) {
events++;
Event event = journalChanged.nextEvent();
try {
switch(event.getType()) {
case Event.NODE_ADDED:
if (ses.nodeExists(event.getPath())) {
Node nodeAdded = ses.getNode(event.getPath());
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
logger.debug("node added event received with name {}", nodeAdded.getName());
Item item = node2Item.getItem(nodeAdded, Excludes.ALL);
if (tempCachedMap.get(event.getIdentifier())!=null)
tempCachedMap.remove(event.getIdentifier());
if (item.isHidden())
break;
insertItemInTheRightPlace(item,tempCachedMap);
}
}
break;
case Event.PROPERTY_CHANGED:
if (ses.propertyExists(event.getPath())) {
Property property = ses.getProperty(event.getPath());
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
logger.debug("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
String identifier = property.getParent().getIdentifier();
tempCachedMap.remove(identifier);
Item item = node2Item.getItem(property.getParent(), Excludes.ALL);
if (item.isHidden())
break;
insertItemInTheRightPlace(item, tempCachedMap);
}
}
break;
case Event.NODE_REMOVED:
logger.trace("node removed event received with type {}", event.getIdentifier());
if (tempCachedMap.get(event.getIdentifier())!=null &&
tempCachedMap.get(event.getIdentifier())<event.getDate())
tempCachedMap.remove(event.getIdentifier());
break;
case Event.NODE_MOVED:
Node nodeMoved = ses.getNode(event.getPath());
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
logger.debug("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
String identifier = nodeMoved.getIdentifier();
String nodePath = ses.getNode(identifier).getPath();
if (tempCachedMap.get(event.getIdentifier())!=null &&
!nodePath.startsWith(vreFolder.getPath()))
tempCachedMap.remove(event.getIdentifier());
}
break;
default:
break;
}
}catch (Exception e) {
logger.warn("error handling event {}",event.getType(),e);
}
}
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
} catch (Exception e) {
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}
}
private void visitChildren(Node node, Map<String, Long> tempCachedMap) throws Exception{
NodeIterator nodeIt = node.getNodes();
while(nodeIt.hasNext()) {
Node child = nodeIt.nextNode();
Item item = node2Item.getItem(child, Excludes.ALL);
if (item==null || item.isHidden()) continue;
if (item instanceof FolderItem)
visitChildren(child,tempCachedMap);
else if(item instanceof AbstractFileItem)
insertItemInTheRightPlace(item,tempCachedMap);
}
}
/* @Override
public void onEvent(EventIterator events) {
logger.trace("on event called");
while (events.hasNext()) {
Event event = events.nextEvent();
try {
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
} catch (RepositoryException e) {
logger.error("error reading event",e);
}
}
}*/
}

View File

@ -1,9 +1,6 @@
package org.gcube.data.access.storagehub.services;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
@ -11,9 +8,6 @@ import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -22,19 +16,13 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.acls.ACL;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
@ -47,34 +35,50 @@ import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.VreFolder;
import org.gcube.common.storagehub.model.types.ACLList;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("items")
public class ACLManager {
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class ACLManager extends Impersonable {
private static final Logger log = LoggerFactory.getLogger(ACLManager.class);
@Inject
RepositoryInitializer repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@RequestScoped
@PathParam("id")
String id;
@Inject
AuthorizationChecker authChecker;
@Inject
PathUtil pathUtil;
@Context
ServletContext context;
@Inject Node2ItemConverter node2Item;
@Inject
AuthorizationChecker authChecker;
@Inject UnshareHandler unshareHandler;
@Inject ACLManagerInterface aclManagerDelegate;
/**
* returns the AccessType for all the users in a shared folder
@ -88,38 +92,21 @@ public class ACLManager {
public ACLList getACL() {
InnerMethodName.instance.set("getACLById");
Session ses = null;
List<ACL> acls = new ArrayList<>();
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
String path = ses.getNodeByIdentifier(id).getPath();
log.info("checking acces for path {}",path);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(ses, path );
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
ACL acl = new ACL();
acl.setPricipal(aclEntry.getPrincipal().getName());
List<AccessType> types = new ArrayList<>();
for (Privilege priv : aclEntry.getPrivileges())
try {
types.add(AccessType.fromValue(priv.getName()));
}catch (Exception e) {
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
}
acl.setAccessTypes(types);
acls.add(acl);
}
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
return new ACLList(aclManagerDelegate.get(item, ses));
}catch(RepositoryException re){
log.error("jcr error getting acl", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting acl", re));
throw new WebApplicationException(new BackendGenericError("jcr error getting acl", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return new ACLList(acls);
}
@ -139,13 +126,14 @@ public class ACLManager {
@PUT
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("{id}/acls")
public void setACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
public void updateACL(@FormDataParam("user") String user, @FormDataParam("access") AccessType accessType) {
InnerMethodName.instance.set("setACLById");
Session ses = null;
try {
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
if (user==currentUser) throw new InvalidCallParameters("own ACLs cannot be modified");
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(node, Excludes.ALL);
@ -156,72 +144,35 @@ public class ACLManager {
if (item.getOwner().equals(user))
throw new UserNotAuthorizedException("owner acl cannot be changed");
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
SharedFolder folder = (SharedFolder) item;
SharedFolder folder = ((SharedFolder)item);
authChecker.checkAdministratorControl(ses, currentUser, folder);
if (folder.isVreFolder()) {
if (accessType!=AccessType.ADMINISTRATOR)
throw new InvalidCallParameters("acls in vreFolder cannot be changed, only new admin can be set");
if (accessType==AccessType.ADMINISTRATOR) throw new InvalidCallParameters("a VRE admin cannot be changed with this method");
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)ses).getUserManager();
String groupId = folder.getTitle();
Group group = (Group)usrManager.getAuthorizable(groupId);
User authUser = (User)usrManager.getAuthorizable(user);
if (!group.isMember(authUser))
throw new InvalidCallParameters("user "+user+" is not in the group "+groupId);
String path = node.getPath();
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path);
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
Principal principal = AccessControlUtils.getPrincipal(ses, user);
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(path, acls);
ses.save();
if (!user.equals(folder.getTitle())) throw new InvalidCallParameters("the groupId in the argument is different to the one of the VREFolder");
} else {
NodeIterator sharedSet = node.getSharedSet();
boolean found = false;
while (sharedSet.hasNext() && !found) {
Node current = sharedSet.nextNode();
if (current.getPath().startsWith(Utils.getWorkspacePath(user).toPath()))
if (current.getPath().startsWith(pathUtil.getWorkspacePath(user).toPath()))
found = true;
}
if (!found)
throw new InvalidCallParameters("shared folder with id "+item.getId()+" is not shared with user "+user);
String path = node.getPath();
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, path);
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
AccessControlEntry aceToDelete = null;;
Principal principal = AccessControlUtils.getPrincipal(ses, user);
for (AccessControlEntry ace : acls.getAccessControlEntries())
if (ace.getPrincipal().equals(principal)) {
aceToDelete = ace;
break;
throw new InvalidCallParameters("shared folder with id "+folder.getId()+" is not shared with user "+user);
}
if (aceToDelete!= null)
acls.removeAccessControlEntry(aceToDelete);
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(path, acls);
ses.save();
}
aclManagerDelegate.update(user, folder, accessType, ses);
}catch(RepositoryException re){
log.error("jcr error extracting archive", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
throw new WebApplicationException(new BackendGenericError("jcr error setting acl", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
throw new WebApplicationException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
@ -230,18 +181,19 @@ public class ACLManager {
}
/**
* remove right for a user only on VRE folder
* remove right for a user only on Shared folder
*
*
* @param String user
* @param accessType accessType
*
*
* @exception {@link RepositoryException} when a generic jcr error occurs
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
* @exception {@link InvalidItemException} when the folder is not share
*/
/*@DELETE
//TODO: is this method correct? can ACL be removed, is correct that this means an unshare operation?
@DELETE
@Consumes(MediaType.TEXT_PLAIN)
@Path("{id}/acls/{user}")
public void removeACL(@PathParam("user") String user) {
@ -257,36 +209,16 @@ public class ACLManager {
if (!(item instanceof SharedFolder))
throw new InvalidItemException("the item is not a shared folder");
authChecker.checkAdministratorControl(ses, (SharedFolder) item);
if (item instanceof VreFolder || ((SharedFolder) item).isVreFolder())
throw new InvalidCallParameters("acls in vreFolder cannot be removed with this method");
SharedFolder folder = ((SharedFolder)item);
authChecker.checkAdministratorControl(ses, currentUser, (SharedFolder) item);
if (folder.isVreFolder()) {
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
AccessControlEntry entryToDelete= null;
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
if (ace.getPrincipal().getName().equals(user)) {
entryToDelete = ace;
break;
}
}
if (entryToDelete!=null)
acls.removeAccessControlEntry(entryToDelete);
else return;
acm.setPolicy(folder.getPath(), acls);
ses.save();
log.debug("removed Access control entry for user {}",user);
} else throw new InvalidCallParameters("remove acl can be called only on VRE folder");
unshareHandler.unshare(ses, Collections.singleton(user), node, currentUser);
}catch(RepositoryException re){
log.error("jcr error extracting archive", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error setting acl", re));
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing acl", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
@ -294,7 +226,7 @@ public class ACLManager {
if (ses!=null)
ses.logout();
}
}*/
}
@GET
@Path("{id}/acls/write")
@ -310,7 +242,7 @@ public class ACLManager {
throw new InvalidItemException("this method can be applied only to folder");
try {
authChecker.checkWriteAuthorizationControl(ses, id, true);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, true);
}catch (UserNotAuthorizedException e) {
return false;
}

View File

@ -0,0 +1,47 @@
package org.gcube.data.access.storagehub.services;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("api-docs")
public class DocManager {
private static Logger logger = LoggerFactory.getLogger(DocManager.class);
@GET
@Path("/{any: .*}")
public InputStream toDoc(@Context HttpServletRequest req) throws WebApplicationException {
logger.info(DocManager.class.getSimpleName() + " toDoc called");
String pathInfo = req.getPathInfo();
logger.debug("pathInfo {}", pathInfo);
try {
if (pathInfo.endsWith("/api-docs")) {
pathInfo += "index.html";
}
if (pathInfo.endsWith("/api-docs/")) {
pathInfo += "index.html";
}
logger.info("going to {}", pathInfo);
String realPath = req.getServletContext().getRealPath(pathInfo);
return new FileInputStream(new File(realPath));
} catch (Exception e) {
throw new WebApplicationException("error getting docs",e);
}
}
}

View File

@ -1,13 +1,19 @@
package org.gcube.data.access.storagehub.services;
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
import static org.gcube.data.access.storagehub.Roles.VREMANAGER_ROLE;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
@ -22,6 +28,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
@ -34,34 +41,82 @@ import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.vres.VRE;
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("groups")
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class GroupManager {
@Context ServletContext context;
@Inject
TrashHandler trashHandler;
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
RepositoryInitializer repository;
VREManager vreManager;
@Inject
GroupHandler groupHandler;
@Inject
Node2ItemConverter node2Item;
@Inject
PathUtil pathUtil;
@Inject
AuthorizationChecker authChecker;
@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
public List<String> getGroups(){
InnerMethodName.instance.set("getGroups");
JackrabbitSession session = null;
List<String> groups= new ArrayList<>();
try {
@ -80,9 +135,9 @@ public class GroupManager {
log.info("group {} found",group.getPrincipal().getName());
groups.add(group.getPrincipal().getName());
}
}catch(Exception e) {
log.error("jcr error getting groups", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
@ -92,13 +147,18 @@ public class GroupManager {
@POST
@Path("")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
public String createGroup(@FormParam("group") String group, @FormParam("accessType") AccessType accessType){
@Consumes(MediaType.MULTIPART_FORM_DATA)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createGroup(@FormDataParam("group") String group, @FormDataParam("accessType") AccessType accessType, @FormDataParam("folderOwner") String folderOwner){
InnerMethodName.instance.set("createGroup");
JackrabbitSession session = null;
String groupId = null;
try {
log.info("create group called with groupid {} , accessType {} and folderOwner {}",group, accessType, folderOwner);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
@ -106,10 +166,19 @@ public class GroupManager {
Group createdGroup = usrManager.createGroup(group);
groupId = createdGroup.getID();
createVreFolder(groupId, session, accessType!=null?accessType:AccessType.WRITE_OWNER);
User user = (User)usrManager.getAuthorizable(folderOwner);
createVreFolder(groupId, session, accessType!=null?accessType:AccessType.WRITE_OWNER, folderOwner);
boolean success = this.internalAddUserToGroup(session, createdGroup, user);
if (!success) log.warn("the user have not been added to the group");
else log.debug("the user have been added to the group");
session.save();
}catch(Exception e) {
}catch(StorageHubException se) {
log.error("error creating group {}", group, se);
GXOutboundErrorResponse.throwException(se);
}catch(Throwable e) {
log.error("jcr error creating group {}", group, e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
@ -122,44 +191,207 @@ public class GroupManager {
@DELETE
@Path("{group}")
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteGroup(@PathParam("group") String group){
InnerMethodName.instance.set("deleteGroup");
JackrabbitSession session = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Authorizable authorizable = usrManager.getAuthorizable(group);
if (authorizable!=null && authorizable.isGroup())
authorizable.remove();
try {
getVreFolderNode(session, group).removeSharedSet();
Node node = groupHandler.getFolderNodeRelatedToGroup(session, group);
List<Item> workspaceItems = Utils.getItemList(node, Excludes.GET_ONLY_CONTENT, null, true, null);
trashHandler.removeOnlyNodesContent(session, workspaceItems);
node.removeSharedSet();
}catch (Exception e) {
log.warn("vreFolder {} not found, removing only the group", group);
}
Authorizable authorizable = usrManager.getAuthorizable(group);
if (authorizable.isGroup())
authorizable.remove();
session.save();
}catch(Exception e) {
log.error("jcr error getting users", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
}
return group;
}
public boolean isInfraManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE); }
public boolean isVREManager() { return AuthorizationProvider.instance.get().getClient().getRoles().contains(VREMANAGER_ROLE); }
@PUT
@Path("{id}/admins")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void addAdmin(@PathParam("id") String groupId, @FormParam("userId") String userId){
InnerMethodName.instance.set("addAdmin");
JackrabbitSession session = null;
try {
Objects.nonNull(groupId);
Objects.nonNull(userId);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
org.apache.jackrabbit.api.security.user.UserManager usrManager = ((JackrabbitSession)session).getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User authUser = (User)usrManager.getAuthorizable(userId);
if (group ==null)
throw new InvalidCallParameters("invalid group "+groupId);
if (authUser ==null)
throw new InvalidCallParameters("invalid user "+userId);
if (!group.isMember(authUser))
throw new InvalidCallParameters("user "+userId+" is not in the group "+groupId);
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
Principal principal = AccessControlUtils.getPrincipal(session, userId);
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(vreFolder.getPath(), acls);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable re ){
log.error("adding admin to VREFolder", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error adding admin to VREFolder", re));
} finally {
if (session!=null)
session.logout();
}
}
@DELETE
@Path("{id}/admins/{userId}")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void removeAdmin(@PathParam("id") String groupId, @PathParam("userId") String userId){
InnerMethodName.instance.set("removeAdmin");
JackrabbitSession session = null;
try {
Objects.nonNull(groupId);
Objects.nonNull(userId);
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node vreFolder = groupHandler.getFolderNodeRelatedToGroup(session, groupId);
String currentUser = AuthorizationProvider.instance.get().getClient().getId();
if (!isInfraManager() && !(isVREManager() && isValidGroupForContext(groupId) ))
authChecker.checkAdministratorControl(session, currentUser, node2Item.getItem(vreFolder, Excludes.ALL));
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, vreFolder.getPath());
AccessControlEntry toRemove = null;
for (AccessControlEntry acl: acls.getAccessControlEntries())
if (acl.getPrincipal().getName().equals(userId)) {
toRemove = acl;
break;
}
acls.removeAccessControlEntry(toRemove);
acm.setPolicy(vreFolder.getPath(), acls);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Throwable re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error removing admin to VREFolder", re));
}finally {
if (session!=null)
session.logout();
}
}
@GET
@Path("{groupId}/admins")
@Produces(MediaType.APPLICATION_JSON)
public List<String> getAdmins(@PathParam("groupId") String groupId){
InnerMethodName.instance.set("getAdmins");
String login = AuthorizationProvider.instance.get().getClient().getId();
JackrabbitSession session = null;
List<String> users = new ArrayList<>();
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
VRE vreFolder = vreManager.getVreFolderItemByGroupName(session, groupId, login, Excludes.ALL);
AccessControlManager acm = session.getAccessControlManager();
//authChecker.checkAdministratorControl(session, (VreFolder)vreFolder.getVreFolder());
Node node = session.getNodeByIdentifier(vreFolder.getVreFolder().getId());
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, node.getPath());
for (AccessControlEntry acl: acls.getAccessControlEntries())
for (Privilege pr: acl.getPrivileges()) {
if (pr.getName().equals(AccessType.ADMINISTRATOR.getValue())){
users.add(acl.getPrincipal().getName());
}
}
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(Exception re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
}
return group;
return users;
}
@PUT
@Path("{id}")
@Path("{id}/users")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public boolean addUserToGroup(@PathParam("id") String groupId, @FormParam("userId") String userId){
InnerMethodName.instance.set("addUserToGroup");
JackrabbitSession session = null;
boolean success = false;
try {
if (!isInfraManager() && !isValidGroupForContext(groupId))
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
@ -167,19 +399,21 @@ public class GroupManager {
Group group = (Group)usrManager.getAuthorizable(groupId);
User user = (User)usrManager.getAuthorizable(userId);
success = group.addMember(user);
if (user==null)
throw new InvalidCallParameters("user "+userId+" not exists");
String folderName = group.getPrincipal().getName();
Node folder = getVreFolderNode(session, folderName);
if (group.isMember(user))
throw new InvalidCallParameters("user "+userId+" is already member of group "+groupId);
String userPath = String.format("%s%s/%s",Utils.getWorkspacePath(user.getPrincipal().getName()).toPath(),Constants.VRE_FOLDER_PARENT_NAME, folderName);
log.debug("creating folder in user path {}", userPath );
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
this.internalAddUserToGroup(session, group, user);
session.save();
}catch(Exception e) {
log.error("jcr error adding user {} to group {}", userId, groupId, e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
@ -188,40 +422,51 @@ public class GroupManager {
return success;
}
private boolean internalAddUserToGroup(JackrabbitSession session, Group group, User user) throws RepositoryException, StorageHubException {
boolean success = group.addMember(user);
session.save();
String folderName = group.getPrincipal().getName();
Node folder = groupHandler.getFolderNodeRelatedToGroup(session, folderName);
String userPath = Paths.append(pathUtil.getVREsPath(user.getPrincipal().getName(), session), folderName).toPath();
log.debug("creating folder in user path {} from {}", userPath, folder.getPath() );
session.getWorkspace().clone(session.getWorkspace().getName(), folder.getPath(),userPath , false);
try {
session.getNode(userPath);
log.debug("the new folder exists ({}) ", userPath );
}catch (PathNotFoundException e) {
log.debug("the new folder doesn't exists ({}) ", userPath );
}
return success;
}
@DELETE
@Path("{groupId}/users/{userId}")
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public boolean removeUserFromGroup(@PathParam("groupId") String groupId, @PathParam("userId") String userId){
InnerMethodName.instance.set("removeUserFromGroup");
JackrabbitSession session = null;
boolean success = false;
try {
if (!isValidGroupForContext(groupId) && !isInfraManager())
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Group group = (Group)usrManager.getAuthorizable(groupId);
User user = (User)usrManager.getAuthorizable(userId);
//delete folder on user
String folderName = group.getPrincipal().getName();
Node folder = getVreFolderNode(session, folderName);
NodeIterator ni = folder.getSharedSet();
while (ni.hasNext()) {
Node node = ni.nextNode();
if (node.getPath().startsWith(Utils.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
node.removeShare();
break;
}
}
success = group.removeMember(user);
success = groupHandler.removeUserFromGroup(groupId, userId, session);
session.save();
}catch(Exception e) {
log.error("jcr error adding user {} to group {}", userId, groupId, e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
@ -233,12 +478,18 @@ public class GroupManager {
@GET
@Path("{groupId}/users")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
@AuthorizationControl(allowedRoles={VREMANAGER_ROLE, INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public List<String> getUsersOfGroup(@PathParam("groupId") String groupId){
InnerMethodName.instance.set("getUsersOfGroup");
JackrabbitSession session = null;
List<String> users = new ArrayList<>();
try {
if (!isValidGroupForContext(groupId) && !isInfraManager())
throw new UserNotAuthorizedException("only VREManager of the selected VRE can execute this operation");
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
@ -253,9 +504,12 @@ public class GroupManager {
}
}catch(Exception e) {
log.error("jcr error getting users of group {}", groupId, e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
}finally {
if (session!=null)
session.logout();
@ -264,53 +518,53 @@ public class GroupManager {
return users;
}
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType) throws Exception{
private void createVreFolder(String groupId, JackrabbitSession session, AccessType defaultAccessType, String owner ) throws Exception{
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
String name = groupId;
String title = groupId.substring(groupId.lastIndexOf("-")+1);
String currentScope = ScopeProvider.instance.get();
ScopeBean bean = new ScopeBean(currentScope);
while (!bean.is(Type.INFRASTRUCTURE)) {
bean = bean.enclosingScope();
}
String root = bean.toString().replaceAll("/", "");
Node folder= Utils.createFolderInternally(session, sharedRootNode, name, "VREFolder for "+groupId, false, AuthorizationProvider.instance.get().getClient().getId(), null);
String displayName = groupId.replaceAll(root+"-[^\\-]*\\-(.*)", "$1");
log.info("creating vreFolder with name {} and title {} and owner {}", name, displayName, owner);
FolderCreationParameters folderParameters = FolderCreationParameters.builder().name(name).description( "VREFolder for "+groupId).author(owner).on(sharedRootNode.getIdentifier()).with(session).build();
Node folder= Utils.createFolderInternally(folderParameters, null);
folder.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
folder.setProperty(NodeProperty.IS_VRE_FOLDER.toString(), true);
folder.setProperty(NodeProperty.TITLE.toString(), name);
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), title);
folder.setProperty(NodeProperty.DISPLAY_NAME.toString(), displayName);
session.save();
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
/*Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session, AuthorizationProvider.instance.get().getClient().getId()), adminPrivileges );
*/
Privilege[] usersPrivileges = new Privilege[] { acm.privilegeFromName(defaultAccessType.getValue()) };
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(session,groupId), usersPrivileges );
acm.setPolicy(folder.getPath(), acls);
log.debug("vrefolder created with id {}",folder.getIdentifier());
}
private Node getVreFolderNode(JackrabbitSession session, String name) throws InvalidItemException, Exception {
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
Node vreFolder = null;
try {
vreFolder = sharedRootNode.getNode(name);
}catch (PathNotFoundException e) {
log.debug("is an old HL VRE");
}
NodeIterator nodes = sharedRootNode.getNodes();
while (nodes.hasNext()) {
Node node = nodes.nextNode();
if (node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
vreFolder= node;
break;
}
}
if (vreFolder==null) throw new InvalidItemException("vre folder not found");
return vreFolder;
private boolean isValidGroupForContext(String group){
String currentContext = ScopeProvider.instance.get();
String expectedGroupId= currentContext.replace("/", "-").substring(1);
return group.equals(expectedGroupId);
}
}

View File

@ -0,0 +1,38 @@
package org.gcube.data.access.storagehub.services;
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.ClientInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("")
public abstract class Impersonable {
Logger log = LoggerFactory.getLogger(Impersonable.class);
String currentUser;
@RequestScoped
@Inject
public void setCurrentUser(@Context final HttpServletRequest request) {
String impersonate = request!=null ? request.getParameter("impersonate") : null ;
ClientInfo info = AuthorizationProvider.instance.get().getClient();
if(impersonate!=null && info.getRoles().contains(INFRASTRUCTURE_MANAGER_ROLE)) {
this.currentUser = impersonate;
} else
this.currentUser = info.getId();
log.info("called with login {} and impersonate {}",info.getId(), impersonate);
}
}

View File

@ -1,5 +1,7 @@
package org.gcube.data.access.storagehub.services;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import javax.enterprise.context.RequestScoped;
@ -12,17 +14,18 @@ import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
@ -39,24 +42,33 @@ import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("items")
public class ItemSharing {
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class ItemSharing extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemSharing.class);
@Inject
RepositoryInitializer repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@ -71,23 +83,131 @@ public class ItemSharing {
@Inject
AuthorizationChecker authChecker;
@Inject
PathUtil pathUtil;
@Inject
UnshareHandler unshareHandler;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@SuppressWarnings("unchecked")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@POST
@Path("{id}/share")
public String shareWithMap(@FormParam("mapUserPermission") String mapUserPermissionString, @FormParam("defaultAccessType") String defaultAccessTypeString){
InnerMethodName.instance.set("shareFolder");
HashMap<String,String> mapUserPermission;
Session ses = null;
String toReturn = null;
try{
try {
mapUserPermission = (HashMap<String,String>)new ObjectMapper().readValue(mapUserPermissionString, HashMap.class);
}catch (Exception e) {
throw new InvalidCallParameters("invalid map passed");
}
AccessType defaultAccessType;
try {
defaultAccessType = AccessType.fromValue(defaultAccessTypeString);
}catch (IllegalArgumentException e) {
throw new InvalidCallParameters("invalid default accessType");
}
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
if (mapUserPermission==null || mapUserPermission.isEmpty())
throw new InvalidCallParameters("users is empty");
Node nodeToShare = ses.getNodeByIdentifier(id);
boolean alreadyShared = false;
Node sharedFolderNode;
if (!node2Item.checkNodeType(nodeToShare, SharedFolder.class))
sharedFolderNode= shareFolder(nodeToShare, ses);
else {
sharedFolderNode = nodeToShare;
alreadyShared = true;
}
ses.save();
try {
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
if (!alreadyShared) {
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
addUserToSharing(sharedFolderNode, ses, currentUser, item, adminPrivileges, acls);
mapUserPermission.remove(currentUser);
}
for (Entry<String, String> entry: mapUserPermission.entrySet() )
try {
AccessType accessType = defaultAccessType;
try {
if (entry.getValue()!=null)
accessType = AccessType.fromValue(entry.getValue());
}catch (IllegalArgumentException e) { log.warn("an illegal accessType passed to sharing ({})", entry.getValue());}
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
addUserToSharing(sharedFolderNode, ses, entry.getKey(), null, userPrivileges, acls);
}catch(Exception e){
log.warn("error adding user {} to sharing of folder {}", entry.getKey(), sharedFolderNode.getName());
}
acm.setPolicy(sharedFolderNode.getPath(), acls);
String title = sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString();
accountingHandler.createShareFolder(title, mapUserPermission.keySet(), ses, sharedFolderNode, currentUser, false);
ses.save();
toReturn = sharedFolderNode.getIdentifier();
} finally {
if (!ses.hasPendingChanges())
ses.getWorkspace().getLockManager().unlock(sharedFolderNode.getPath());
}
}catch(RepositoryException re){
log.error("jcr sharing", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error sharing folder", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return toReturn;
}
@PUT
@Path("{id}/share")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Deprecated
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
InnerMethodName.instance.set("shareFolder");
Session ses = null;
String toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, id, false);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
@ -111,7 +231,7 @@ public class ItemSharing {
ses.save();
try {
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
@ -122,8 +242,8 @@ public class ItemSharing {
if (!alreadyShared) {
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
addUserToSharing(sharedFolderNode, ses, login, item, adminPrivileges, acls);
users.remove(login);
addUserToSharing(sharedFolderNode, ses, currentUser, item, adminPrivileges, acls);
users.remove(currentUser);
}
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
@ -137,7 +257,7 @@ public class ItemSharing {
acm.setPolicy(sharedFolderNode.getPath(), acls);
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, false);
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, currentUser, false);
ses.save();
@ -164,9 +284,8 @@ public class ItemSharing {
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
String login = AuthorizationProvider.instance.get().getClient().getId();
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(login))
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.PORTAL_LOGIN.toString()).getString().equals(currentUser))
throw new InvalidItemException("item with id "+id+" cannot be shared");
String sharedFolderName = node.getIdentifier();
@ -186,7 +305,7 @@ public class ItemSharing {
String userRootWSId;
String userPath;
if (itemToShare==null) {
String userRootWS = Utils.getWorkspacePath(user).toPath();
String userRootWS = pathUtil.getWorkspacePath(user).toPath();
userRootWSId = ses.getNode(userRootWS).getIdentifier();
userPath = String.format("%s%s",userRootWS,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString());
}
@ -215,13 +334,13 @@ public class ItemSharing {
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String unshare(@FormDataParam("users") Set<String> users){
InnerMethodName.instance.set("unshareFolder");
String login = AuthorizationProvider.instance.get().getClient().getId();
Session ses = null;
String toReturn = null;
try {
log.debug("unsharing folder with id {} with users {}", id, users);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node sharedNode = ses.getNodeByIdentifier(id);
toReturn = unshareHandler.unshare(ses, users, sharedNode, login);
toReturn = unshareHandler.unshare(ses, users, sharedNode, currentUser);
if(toReturn == null ) throw new InvalidItemException("item with id "+id+" cannot be unshared");
}catch(RepositoryException re){
log.error("jcr unsharing", re);

View File

@ -1,25 +1,12 @@
package org.gcube.data.access.storagehub.services;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
@ -30,123 +17,103 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.MultipleOutputStream;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.ArchiveStructureCreationParameter;
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("items")
public class ItemsCreator {
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"), })
public class ItemsCreator extends Impersonable {
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
private static ExecutorService executor = Executors.newFixedThreadPool(100);
@Context
ServletContext context;
@Context ServletContext context;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
RepositoryInitializer repository;
ItemHandler itemHandler;
@Inject
ContentHandlerFactory contenthandlerFactory;
@Inject
VersionHandler versionHandler;
@Inject
AuthorizationChecker authChecker;
@Inject
AccountingHandler accountingHandler;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject StorageBackendHandler storageBackend;
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/FOLDER")
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("hidden") boolean hidden) {
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden) {
InnerMethodName.instance.set("createItem(FOLDER)");
log.info("create folder item called");
Session ses = null;
String toReturn = null;
try {
final String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node destination;
try {
destination = ses.getNodeByIdentifier(id);
}catch(RepositoryException inf) {
throw new IdNotFoundException(id);
}
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
Node newNode;
try {
newNode = Utils.createFolderInternally(ses, destination, name, description, hidden, login, accountingHandler);
ses.save();
} finally {
ses.getWorkspace().getLockManager().unlock(destination.getPath());
}
log.info("item with id {} correctly created",newNode.getIdentifier());
toReturn = newNode.getIdentifier();
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) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (ses != null)
ses.logout();
}
return Response.ok(toReturn).build();
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/EXTERNALFOLDER")
public Response createExternalFolder(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("hidden") boolean hidden,
@FormParam("pluginName") String pluginName, @FormParam("parameters") String pluginParameters) {
InnerMethodName.instance.set("createItem(EXTERNALFOLDER)");
log.info("create folder item called");
Session ses = null;
String toReturn = null;
try {
// TODO
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FolderCreationParameters> builder = FolderCreationParameters.builder().name(name)
.description(description).onRepository(pluginName).withParameters(null).hidden(hidden).on(id)
.with(ses).author(currentUser);
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (ses != null)
ses.logout();
@ -158,48 +125,28 @@ public class ItemsCreator {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/URL")
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) {
public Response createURL(@PathParam("id") String id, @FormParam("name") String name,
@FormParam("description") String description, @FormParam("value") URL value) {
InnerMethodName.instance.set("createItem(URL)");
log.info("create url called");
Session ses = null;
String toReturn = null;
try {
final String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
ItemsParameterBuilder<URLCreationParameters> builder = URLCreationParameters.builder().name(name)
.description(description).url(value).on(id).with(ses).author(currentUser);
Node destination;
try {
destination = ses.getNodeByIdentifier(id);
}catch(RepositoryException inf) {
throw new IdNotFoundException(id);
}
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
Node newNode;
try {
newNode = Utils.createURLInternally(ses, destination, name, value, description, login, accountingHandler);
ses.save();
} finally {
ses.getWorkspace().getLockManager().unlock(destination.getPath());
}
log.info("item with id {} correctly created",newNode.getIdentifier());
toReturn = newNode.getIdentifier();
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (ses != null)
ses.logout();
@ -208,7 +155,6 @@ public class ItemsCreator {
return Response.ok(toReturn).build();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/create/GCUBEITEM")
@ -219,40 +165,20 @@ public class ItemsCreator {
String toReturn = null;
try {
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<GCubeItemCreationParameters> builder = GCubeItemCreationParameters.builder()
.item(item).on(id).with(ses).author(currentUser);
Node destination;
try {
destination = ses.getNodeByIdentifier(id);
}catch(ItemNotFoundException inf) {
throw new IdNotFoundException(id);
}
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
Node newNode;
try {
newNode = Utils.createGcubeItemInternally(ses, destination, item.getName(), item.getDescription(), login, item, accountingHandler);
ses.save();
} finally {
ses.getWorkspace().getLockManager().unlock(destination.getPath());
}
log.info("item with id {} correctly created",newNode.getIdentifier());
toReturn = newNode.getIdentifier();
toReturn = itemHandler.create(builder.build());
} catch (StorageHubException she) {
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
} catch (RepositoryException re) {
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} catch (Throwable e) {
log.error("unexpected error", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (ses != null)
ses.logout();
@ -260,40 +186,25 @@ public class ItemsCreator {
return toReturn;
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/FILE")
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
@FormDataParam("description") String description,
@FormDataParam("file") InputStream stream,
@FormDataParam("description") String description, @FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {
InnerMethodName.instance.set("createItem(FILE)");
Session ses = null;
String toReturn = null;
try {
if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null or empty");
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name)
.description(description).stream(stream).fileDetails(fileDetail).on(id).with(ses)
.author(currentUser);
Node destination = ses.getNodeByIdentifier(id);
toReturn = itemHandler.create(builder.build());
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
log.info("session: {}",ses.toString());
Node newNode = createFileItemInternally(ses, destination, stream, name, description, login, true);
ses.save();
versionHandler.checkinContentNode(newNode, ses);
log.info("file with id {} correctly created",newNode.getIdentifier());
toReturn = newNode.getIdentifier();
} catch (RepositoryException re) {
log.error("jcr error creating file item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
@ -313,154 +224,23 @@ public class ItemsCreator {
}
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, UserNotAuthorizedException, ItemLockedException, BackendGenericError{
//to inherit hidden property
//item.setHidden(destinationItem.isHidden());
Node newNode;
try {
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationNode.getPath()), name).toPath());
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
if (withLock) {
try {
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
}catch (LockException le) {
throw new ItemLockedException(le);
}
}
try {
versionHandler.checkoutContentNode(newNode, ses);
log.trace("replacing content of class {}",item.getContent().getClass());
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, false);
ses.save();
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
}
}catch(PathNotFoundException pnf) {
authChecker.checkWriteAuthorizationControl(ses, destinationNode.getIdentifier(), true);
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
if (withLock) {
try {
log.debug("trying to acquire lock");
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
}catch (LockException le) {
throw new ItemLockedException(le);
}
}
try {
newNode = item2Node.getNode(destinationNode, item);
ses.save();
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
}
versionHandler.makeVersionableContent(newNode, ses);
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
}
return newNode;
}
private AbstractFileItem fillItemWithContent(InputStream stream, String name, String description, String path, String login) throws BackendGenericError{
ContentHandler handler = getContentHandler(stream , name, path, login);
AbstractFileItem item =handler.buildItem(name, description, login);
return item ;
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/{id}/create/ARCHIVE")
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
@FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail){
@FormDataParam("file") InputStream stream, @FormDataParam("file") FormDataContentDisposition fileDetail) {
InnerMethodName.instance.set("createItem(ARCHIVE)");
Session ses = null;
String toReturn = null;
try {
if (parentFolderName==null) throw new InvalidCallParameters("new folder name is null");
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node destination = ses.getNodeByIdentifier(id);
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier() , true);
try {
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
}catch (LockException le) {
throw new ItemLockedException(le);
}
Node parentDirectoryNode = Utils.createFolderInternally(ses, destination, parentFolderName, "", false, login, accountingHandler);
try {
if (ses.getWorkspace().getLockManager().isLocked(destination.getPath()))
ses.getWorkspace().getLockManager().unlock(destination.getPath());
} catch (Throwable t){
log.warn("error unlocking {}", destination.getPath(), t);
}
Set<Node> fileNodes = new HashSet<>();
HashMap<String, Node> directoryNodeMap = new HashMap<>();
try (ArchiveInputStream input = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(stream, 1024*64))){
ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {
if (entry.isDirectory()) {
String entirePath = entry.getName();
String name = entirePath.replaceAll("(.*/)*(.*)/", "$2");
String parentPath = entirePath.replaceAll("(.*/)*(.*)/", "$1");
log.debug("creating directory with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
Node createdNode;
if (parentPath.isEmpty()) {
createdNode = Utils.createFolderInternally(ses, parentDirectoryNode, name, "", false, login, accountingHandler);
}else {
Node parentNode = directoryNodeMap.get(parentPath);
createdNode = Utils.createFolderInternally(ses, parentNode, name, "", false, login, accountingHandler);
}
directoryNodeMap.put(entirePath, createdNode);
continue;
} else {
try {
String entirePath = entry.getName();
String name = entirePath.replaceAll("(.*/)*(.*)", "$2");
String parentPath = entirePath.replaceAll("(.*/)*(.*)", "$1");
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
Node fileNode = null;
if (parentPath.isEmpty())
fileNode = createFileItemInternally(ses, parentDirectoryNode, input, name, "", login, false);
else {
Node parentNode = directoryNodeMap.get(parentPath);
fileNode = createFileItemInternally(ses, parentNode, input, name, "", login, false);
}
fileNodes.add(fileNode);
}catch(Exception e) {
log.warn("error getting file {}",entry.getName(),e);
}
}
}
}
ses.save();
for (Node node : fileNodes)
versionHandler.checkinContentNode(node, ses);
toReturn = parentDirectoryNode.getIdentifier();
ItemsParameterBuilder<ArchiveStructureCreationParameter> builder = ArchiveStructureCreationParameter
.builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail).on(id).with(ses)
.author(currentUser);
toReturn = itemHandler.create(builder.build());
} catch (RepositoryException | ArchiveException | IOException re) {
log.error("jcr error extracting archive", re);
@ -468,6 +248,9 @@ public class ItemsCreator {
} 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();
@ -476,86 +259,4 @@ public class ItemsCreator {
return toReturn;
}
private ContentHandler getContentHandler(InputStream stream , String name, String path, String login) throws BackendGenericError {
final MultipleOutputStream mos;
try{
mos = new MultipleOutputStream(stream, 2);
}catch (IOException e) {
throw new BackendGenericError(e);
}
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
@Override
public ContentHandler call() throws Exception {
ContentHandler handler =null;
long start = System.currentTimeMillis();
log.debug("TIMING: reading the mimetype - start");
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
org.apache.tika.mime.MediaType mediaType = null;
TikaConfig config = TikaConfig.getDefaultConfig();
Detector detector = config.getDetector();
TikaInputStream stream = TikaInputStream.get(is1);
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, name);
mediaType = detector.detect(stream, metadata);
String mimeType = mediaType.getBaseType().toString();
handler = contenthandlerFactory.create(mimeType);
is1.reset();
handler.initiliseSpecificContent(is1, name, mimeType);
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
} catch (Throwable e) {
log.error("error retrieving mimeType",e);
throw new RuntimeException(e);
}
return handler;
}
};
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
@Override
public MetaInfo call() throws Exception {
try(InputStream is1 = mos.get()){
String uid = UUID.randomUUID().toString();
String remotePath= String.format("%s/%s-%s",path,uid,name);
MetaInfo info = storageBackend.upload(is1, remotePath);
return info;
}catch (Throwable e) {
log.error("error writing content",e );
throw e;
}
}
};
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
long start = System.currentTimeMillis();
log.debug("TIMING: writing the stream - start");
try {
mos.startWriting();
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
ContentHandler handler = detectorF.get();
MetaInfo info = uploaderF.get();
handler.getContent().setData(NodeConstants.CONTENT_NAME);
handler.getContent().setStorageId(info.getStorageId());
handler.getContent().setSize(info.getSize());
handler.getContent().setRemotePath(info.getRemotePath());
return handler;
}catch (Exception e) {
throw new BackendGenericError(e);
}
}
}

View File

@ -44,8 +44,7 @@ import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.io.FilenameUtils;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.encryption.StringEncrypter;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
@ -58,12 +57,16 @@ import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.VreFolder;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.common.storagehub.model.service.VersionList;
@ -71,30 +74,40 @@ import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.gcube.data.access.storagehub.handlers.CompressHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("items")
public class ItemsManager {
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class ItemsManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(ItemsManager.class);
@Inject
RepositoryInitializer repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@ -115,10 +128,18 @@ public class ItemsManager {
@Inject
TrashHandler trashHandler;
@Inject PathUtil pathUtil;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject StorageBackendHandler storageBackend;
@Inject
FolderPluginHandler folderPluginHandler;
@Inject
CompressHandler compressHandler;
@GET
@Path("{id}")
@ -130,14 +151,14 @@ public class ItemsManager {
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = node2Item.getItem(node, excludes);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
@ -149,16 +170,90 @@ public class ItemsManager {
return new ItemWrapper<Item>(toReturn);
}
@GET
@Path("{id}/path")
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getByRelativePath(@QueryParam("path") String path, @QueryParam("exclude") List<String> excludes){
InnerMethodName.instance.set("getByPath");
Session ses = null;
Item toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
String relativePath = path.startsWith("/")? path.substring(1) : path;
if (path.endsWith("/"))
relativePath.substring(0,relativePath.lastIndexOf("/"));
if (relativePath.isEmpty()) throw new InvalidCallParameters("empty path");
Item item =null;
String nextId = id;
String[] paths = relativePath.split("/");
for (String actualPath: paths) {
item = getChildrenMatchingName(ses, nextId, actualPath, Excludes.ALL);
if (item ==null) throw new InvalidCallParameters("relative path "+actualPath+" not found under item with id "+nextId);
authChecker.checkReadAuthorizationControl(ses, currentUser, item.getId());
nextId = item.getId();
}
if (excludes.containsAll(Excludes.ALL))
return new ItemWrapper<Item>(item);
else
return new ItemWrapper<Item>(node2Item.getItem(ses.getNodeByIdentifier(item.getId()), excludes));
}catch(RepositoryException re){
log.error("jcr error getting item by path", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item by path", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return new ItemWrapper<Item>(toReturn);
}
private Item getChildrenMatchingName(Session ses, String id, String name, List<String> excludes) throws ItemNotFoundException , RepositoryException, StorageHubException {
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
while (it.hasNext()) {
Node child= it.nextNode();
String nodeName = child.getName();
if (!child.hasProperty(NodeProperty.TITLE.toString())) continue;
String title = child.getProperty(NodeProperty.TITLE.toString()).getString();
if (nodeName.equals(name) || title.equals(name)){
return node2Item.getItem(child, excludes);
}
}
return null;
}
@Deprecated
@GET
@Path("{id}/items/{name}")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
@GET
@Path("{id}/items")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
public ItemList _findChildrenByNamePattern(List<String> excludes, String name){
Session ses = null;
List<Item> toReturn = new ArrayList<>();
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
//NOT using the internal pattern matching of jcr because of title for shared folder
NodeIterator it = ses.getNodeByIdentifier(id).getNodes();
@ -191,8 +286,8 @@ public class ItemsManager {
}
return new ItemList(toReturn);
}
}
@GET
@Path("{id}/children/count")
@ -204,7 +299,7 @@ public class ItemsManager {
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
@ -231,7 +326,7 @@ public class ItemsManager {
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
@ -250,6 +345,36 @@ public class ItemsManager {
return new ItemList(toReturn);
}
@GET
@Path("{id}/search")
@Produces(MediaType.APPLICATION_JSON)
public ItemList searchItems(@QueryParam("showHidden") Boolean showHidden, @QueryParam("excludeTrashed") Boolean excludeTrashed, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType,@QueryParam("name") String name ){
InnerMethodName.instance.set("search");
Session ses = null;
List<? extends Item> toReturn = null;
try{
log.debug("search for node {}",name);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = Utils.searchByNameOnFolder(ses, currentUser, authChecker, ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden,excludeTrashed==true?false:excludeTrashed , nodeType!=null ? ClassHandler.instance().get(nodeType) : null, name);
log.debug("search retrieved {} elements",toReturn.size());
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(RepositoryException re){
log.error("jcr error getting children", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@GET
@Path("{id}/children/paged")
@Produces(MediaType.APPLICATION_JSON)
@ -259,7 +384,7 @@ public class ItemsManager {
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
@ -280,16 +405,14 @@ public class ItemsManager {
@GET
@Path("publiclink/{id}")
@AuthorizationControl(allowed={"URIResolver"}, exception=MyAuthException.class)
@AuthorizationControl(allowedUsers={"URIResolver"}, exception=MyAuthException.class)
public Response resolvePublicLink() {
InnerMethodName.instance.set("resolvePubliclink");
log.warn("arrived id is {}",id);
Session ses = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
String complexId = id;
if (id.startsWith(enchriptedPrefix)) {
@ -321,16 +444,21 @@ public class ItemsManager {
log.warn("item id to retrieve is {}",itemId);
Node selectedNode = ses.getNodeByIdentifier(itemId);
Node selectedNode;
try {
selectedNode= ses.getNodeByIdentifier(itemId);
}catch (ItemNotFoundException e) {
throw new IdNotFoundException(itemId);
}
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
if (versionName!=null)
return downloadVersionInternal(ses, login, itemId, versionName, false);
return downloadVersionInternal(ses, currentUser, itemId, versionName, false);
else
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
}catch(RepositoryException re ){
@ -355,7 +483,7 @@ public class ItemsManager {
URL toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node selectedNode = ses.getNodeByIdentifier(id);
@ -438,7 +566,7 @@ public class ItemsManager {
Item folder= null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, id, false);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath());
@ -474,7 +602,7 @@ public class ItemsManager {
Item sharedParent= null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode =ses.getNodeByIdentifier(id);
log.trace("current node is {}",currentNode.getPath());
@ -517,7 +645,7 @@ public class ItemsManager {
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node node = ses.getNodeByIdentifier(id);
@ -525,7 +653,7 @@ public class ItemsManager {
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not versioned");
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node, ses);
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
for (Version version: jcrVersions) {
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
@ -551,11 +679,10 @@ public class ItemsManager {
InnerMethodName.instance.set("downloadSpecificVersion");
Session ses = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
return downloadVersionInternal(ses, login, id, versionName, true);
return downloadVersionInternal(ses, currentUser, id, versionName, true);
}catch(RepositoryException re ){
log.error("jcr error downloading version", re);
@ -576,16 +703,17 @@ public class ItemsManager {
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not a file");
List<Version> jcrVersions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(id), ses);
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
for (Version version: jcrVersions) {
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
if (version.getName().equals(versionName)) {
long size = version.getFrozenNode().getProperty(NodeProperty.SIZE.toString()).getLong();
String mimeType = version.getFrozenNode().getProperty(NodeProperty.MIME_TYPE.toString()).getString();
String storageId = version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
Content content = node2Item.getContentFromVersion(version);
final InputStream streamToWrite = storageBackend.download(storageId);
FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
log.debug("retrieved storage id is {} with storageBackend {} (stream is null? {})",content.getStorageId(), folderManager.getStorageBackend().getClass().getSimpleName(), streamToWrite==null );
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
String ext = FilenameUtils.getExtension(currentItem.getTitle());
@ -593,15 +721,15 @@ public class ItemsManager {
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
if (withAccounting)
accountingHandler.createReadObj(fileName, ses, node, true);
accountingHandler.createReadObj(fileName, ses, node, login, true);
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
return Response
.ok(so)
.header("content-disposition","attachment; filename = "+fileName)
.header("Content-Length", size)
.header("Content-Type", mimeType)
.header("Content-Length", content.getSize())
.header("Content-Type", content.getMimeType())
.build();
}
}
@ -613,26 +741,29 @@ public class ItemsManager {
@Produces(MediaType.APPLICATION_JSON)
public ItemList getAnchestors(@QueryParam("exclude") List<String> excludes){
InnerMethodName.instance.set("getAnchestors");
org.gcube.common.storagehub.model.Path absolutePath = Utils.getWorkspacePath();
org.gcube.common.storagehub.model.Path absolutePath = pathUtil.getWorkspacePath(currentUser);
Session ses = null;
List<Item> toReturn = new LinkedList<>();
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
Node currentNode = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(currentNode, excludes);
log.trace("current node is {}",currentNode.getPath());
while (!(currentNode.getPath()+"/").equals(absolutePath.toPath())) {
while (!(currentNode.getPath().matches("/Home/[^/]{1,}/Workspace"))) {
if (currentItem instanceof SharedFolder){
NodeIterator sharedSetIterator = currentNode.getSharedSet();
boolean found = false;
while (sharedSetIterator.hasNext()) {
Node sharedNode = sharedSetIterator.nextNode();
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath(login).toPath())) {
if (sharedNode.getPath().startsWith(absolutePath.toPath())) {
currentNode = sharedNode.getParent();
found=true;
break;
}
}
if (!found) break;
currentItem = node2Item.getItem(currentNode, excludes);
}else {
currentNode = currentNode.getParent();
@ -669,17 +800,16 @@ public class ItemsManager {
Session ses = null;
Response response = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
final Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Item item = node2Item.getItem(node, null);
if (item instanceof AbstractFileItem){
return downloadFileInternal(ses, (AbstractFileItem) item, login, true);
return downloadFileInternal(ses, (AbstractFileItem) item, currentUser, true);
} else if (item instanceof FolderItem){
try {
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler, excludes);
final Deque<Item> allNodes = compressHandler.getAllNodesForZip((FolderItem)item, ses, currentUser, accountingHandler, excludes);
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
StreamingOutput so = new StreamingOutput() {
@ -690,7 +820,7 @@ public class ItemsManager {
long start = System.currentTimeMillis();
zos.setLevel(Deflater.BEST_COMPRESSION);
log.debug("writing StreamOutput");
Utils.zipNode(zos, allNodes, login, originalPath, storageBackend);
compressHandler.zipNode(zos, allNodes, currentUser, originalPath);
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
} catch (Exception e) {
log.error("error writing stream",e);
@ -706,7 +836,7 @@ public class ItemsManager {
.header("Content-Length", -1l)
.build();
accountingHandler.createReadObj(item.getTitle(), ses, ses.getNodeByIdentifier(item.getId()), false);
accountingHandler.createReadObj(item.getTitle(), ses, (Node) item.getRelatedNode(), currentUser, false);
}finally {
if (ses!=null) ses.save();
}
@ -725,12 +855,14 @@ public class ItemsManager {
return response;
}
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException {
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, BackendGenericError {
final InputStream streamToWrite = storageBackend.download(fileItem.getContent().getStorageId());
FolderManager folderManager = folderPluginHandler.getFolderManager(fileItem);
final InputStream streamToWrite = folderManager.getStorageBackend().download(fileItem.getContent());
if (withAccounting)
accountingHandler.createReadObj(fileItem.getTitle(), ses, ses.getNodeByIdentifier(fileItem.getId()), true);
accountingHandler.createReadObj(fileItem.getTitle(), ses, (Node) fileItem.getRelatedNode(), login, true);
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
@ -751,13 +883,12 @@ public class ItemsManager {
Session ses = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
authChecker.checkWriteAuthorizationControl(ses, id, false);
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToMove = ses.getNodeByIdentifier(id);
final Node destination = ses.getNodeByIdentifier(destinationId);
@ -778,12 +909,11 @@ public class ItemsManager {
if (!(destinationItem instanceof FolderItem))
throw new InvalidItemException("destination item is not a folder");
if (item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier())))
throw new InvalidCallParameters("shared Item cannot be moved in a different shared folder or in a private folder");
boolean movingSharedItemOutside = item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier()));
try {
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
@ -791,13 +921,18 @@ public class ItemsManager {
String uniqueName =(Utils.checkExistanceAndGetUniqueName(ses, destination, nodeToMove.getName()));
String newPath = String.format("%s/%s",destination.getPath(), uniqueName);
ses.getWorkspace().move(nodeToMove.getPath(), newPath);
Utils.setPropertyOnChangeNode(ses.getNode(newPath), login, ItemAction.MOVED);
ses.move(nodeToMove.getPath(), newPath);
Utils.setPropertyOnChangeNode(ses.getNode(newPath), currentUser, ItemAction.MOVED);
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting , ses, destination, false);
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, originalParent, false);
if (movingSharedItemOutside)
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
//folderHandler.onMove(source, destination);
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
@ -826,13 +961,11 @@ public class ItemsManager {
Session ses = null;
String newFileIdentifier = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
//ses = RepositoryInitializer.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
authChecker.checkReadAuthorizationControl(ses, id);
authChecker.checkWriteAuthorizationControl(ses, currentUser, destinationId, true);
authChecker.checkReadAuthorizationControl(ses, currentUser, id);
final Node nodeToCopy = ses.getNodeByIdentifier(id);
final Node destination = ses.getNodeByIdentifier(destinationId);
@ -844,8 +977,8 @@ public class ItemsManager {
throw new InvalidItemException("folder cannot be copied");
try {
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
@ -856,20 +989,23 @@ public class ItemsManager {
Node newNode = ses.getNode(newPath);
newFileIdentifier = newNode.getIdentifier();
//TODO: folderHandler.onCopy(source, destination);
if (item instanceof AbstractFileItem) {
FolderManager manager = folderPluginHandler.getFolderManager(item);
((AbstractFileItem) item).getContent().setRemotePath(newPath);
String newStorageID = storageBackend.copy((AbstractFileItem) item);
String newStorageID = manager.getStorageBackend().onCopy((AbstractFileItem) item);
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
}
Utils.setPropertyOnChangeNode(newNode, login, ItemAction.CLONED);
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), login);
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, destination, false);
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
ses.save();
@ -900,12 +1036,11 @@ public class ItemsManager {
Session ses = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, id, false);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToMove = ses.getNodeByIdentifier(id);
@ -919,8 +1054,8 @@ public class ItemsManager {
try {
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
@ -930,9 +1065,9 @@ public class ItemsManager {
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
Utils.setPropertyOnChangeNode(nodeToMove, login, ItemAction.RENAMED);
Utils.setPropertyOnChangeNode(nodeToMove, currentUser, ItemAction.RENAMED);
ses.move(nodeToMove.getPath(), newPath);
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), ses, false);
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), currentUser, ses, false);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
@ -954,6 +1089,96 @@ public class ItemsManager {
return Response.ok(id).build();
}
//TODO: transform this and setMetadata in a generic method for all properties
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/hidden")
public Response setItemAsHidden(Boolean hidden){
InnerMethodName.instance.set("setHidden");
Session ses = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
try {
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
item2Node.updateHidden(nodeToUpdate, hidden, currentUser);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
}
//TODO: UPDATE accounting
}catch(RepositoryException re ){
log.error("jcr error moving item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null) {
ses.logout();
}
}
return Response.ok(id).build();
}
//TODO: transform this and setMetadata in a generic method for all properties
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/description")
public Response setDescription(String description){
InnerMethodName.instance.set("setDescription");
Session ses = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
try {
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
item2Node.updateDescription(nodeToUpdate, description, currentUser);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
}
//TODO: UPDATE accounting
}catch(RepositoryException re ){
log.error("jcr error moving item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null) {
ses.logout();
}
}
return Response.ok(id).build();
}
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{id}/metadata")
@ -963,21 +1188,20 @@ public class ItemsManager {
Session ses = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, id, false);
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
try {
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,currentUser);
}catch (LockException e) {
throw new ItemLockedException(e);
}
try {
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), login);
item2Node.updateMetadataNode(nodeToUpdate, metadata.getMap(), currentUser);
ses.save();
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
@ -1013,21 +1237,24 @@ public class ItemsManager {
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, currentUser, id, false);
authChecker.checkMoveOpsForProtectedFolders(ses, id);
authChecker.checkWriteAuthorizationControl(ses, id, false);
final Node nodeToDelete = ses.getNodeByIdentifier(id);
Item itemToDelete = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
if (itemToDelete.isExternalManaged() && !force)
throw new InvalidItemException("External managed Items cannot be moved to Trash");
log.debug("item is trashed? {}", itemToDelete.isTrashed());
if (!itemToDelete.isTrashed() && !force)
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete);
else
if (!itemToDelete.isTrashed() && !force) {
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete, currentUser);
}else
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
}catch (LockException e) {

View File

@ -0,0 +1,434 @@
package org.gcube.data.access.storagehub.services;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.User;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.nodes.Owner;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.MessageList;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter.Values;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.types.MessageSharable;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("messages")
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class MessageManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(MessageManager.class);
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@RequestScoped
@PathParam("id")
String id;
@Context
ServletContext context;
@Inject PathUtil pathUtil;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject TrashHandler trashHandler;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Message getById(){
InnerMethodName.instance.set("getMessageById");
Session ses = null;
Message toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
toReturn = node2Item.getMessageItem(messageNode);
checkRights(currentUser, toReturn);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return toReturn;
}
@DELETE
@Path("{id}")
public void deleteById(){
InnerMethodName.instance.set("deleteMessageById");
Session ses = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message message = node2Item.getMessageItem(messageNode);
Node personalNode = checkRights(currentUser, message);
if (countSharedSet(messageNode)>1)
personalNode.removeShare();
else {
if (message.isWithAttachments()) {
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
List<Item> attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
trashHandler.removeOnlyNodesContent(ses, attachments);
}
messageNode.removeSharedSet();
}
ses.save();
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
}
@GET
@Path("{id}/attachments")
@Produces(MediaType.APPLICATION_JSON)
public ItemList getAttachments(){
InnerMethodName.instance.set("getAttachmentsByMessageId");
Session ses = null;
List<Item> attachments = new ArrayList<>();
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem);
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class);
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(attachments);
}
@GET
@Path("inbox")
@Produces(MediaType.APPLICATION_JSON)
public MessageList getReceivedMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.instance.set("getReceivedMessages");
Session ses = null;
List<Message> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getInboxPath(currentUser).toPath());
//return sorted for createdTime
toReturn = getMessages(node, reduceBody);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}finally{
if (ses!=null)
ses.logout();
}
return new MessageList(toReturn);
}
@GET
@Path("sent")
@Produces(MediaType.APPLICATION_JSON)
public MessageList getSentMessages(@QueryParam("reduceBody") Integer reduceBody){
InnerMethodName.instance.set("getSentMessages");
Session ses = null;
List<Message> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node node = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
toReturn = getMessages(node, reduceBody);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}finally{
if (ses!=null)
ses.logout();
}
return new MessageList(toReturn);
}
@PUT
@Path("{id}/{prop}")
@Consumes(MediaType.APPLICATION_JSON)
public void setProperty(@PathParam("prop") String property,Object value){
InnerMethodName.instance.set("setPropertyOnMessage("+property+")");
Session ses = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Node messageNode = ses.getNodeByIdentifier(id);
Message messageItem = node2Item.getMessageItem(messageNode);
checkRights(currentUser, messageItem);
Values val = Item2NodeConverter.getObjectValue(value.getClass(), value);
messageNode.setProperty(property, val.getValue());
ses.save();
}catch (ItemNotFoundException e) {
log.error("id {} not found",id,e);
GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND);
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch( Exception re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}finally{
if (ses!=null)
ses.logout();
}
}
@POST
@Path("send")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String sendMessage(@FormParam("to[]") List<String> addresses,
@FormParam("subject") String subject, @FormParam("body") String body,
@FormParam("attachments[]") List<String> attachments){
InnerMethodName.instance.set("sendMessage");
JackrabbitSession ses = null;
String messageId = null;
try{
if (addresses.size()==0 || body==null || subject==null)
throw new InvalidCallParameters();
log.debug("attachments send are {}",attachments);
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Message message = new MessageSharable();
message.setAddresses(addresses.toArray(new String[0]));
message.setSubject(subject);
message.setBody(body);
message.setName(UUID.randomUUID().toString());
User user = ses.getUserManager().getAuthorizable(currentUser, User.class);
Owner owner = new Owner();
owner.setUserId(user.getID());
owner.setUserName(user.getPrincipal().getName());
message.setSender(owner);
Node outbox = ses.getNode(pathUtil.getOutboxPath(currentUser).toPath());
Node messageNode = item2Node.getNode(outbox, message);
ses.save();
if (attachments!=null && !attachments.isEmpty()) {
saveAttachments(ses, messageNode, attachments);
ses.save();
}
for (String to: addresses)
try {
String userMessagePath = Paths.append(pathUtil.getInboxPath(to), messageNode.getName()).toPath();
ses.getWorkspace().clone(ses.getWorkspace().getName(), messageNode.getPath(), userMessagePath, false);
}catch (Exception e) {
log.warn("message not send to {}",to,e);
}
ses.save();
messageId = messageNode.getIdentifier();
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error getting item", re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return messageId;
}
private Node saveAttachments(Session ses, Node messageNode , List<String> attachments) throws RepositoryException, BackendGenericError{
Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME);
for (String itemId: attachments) {
Node node = ses.getNodeByIdentifier(itemId);
Item item = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT);
Node newNode = copyNode(ses, attachmentNode, item);
//removes accounting if exists
if (newNode.hasNode(NodeProperty.ACCOUNTING.toString()))
newNode.getNode(NodeProperty.ACCOUNTING.toString()).remove();
}
return messageNode;
}
//returns Messages sorted by createdTime
private List<Message> getMessages(Node node, Integer reduceBody) throws RepositoryException{
List<Message> messages = new ArrayList<Message>();
NodeIterator nodeIt = node.getNodes();
while(nodeIt.hasNext()) {
Node child = nodeIt.nextNode();
log.info("message type "+child.getPrimaryNodeType().getName());
Message message = node2Item.getMessageItem(child);
if (message == null) {
log.info("message discarded");
continue;
}
if (reduceBody != null && reduceBody>0 && message.getBody().length()>reduceBody )
message.setBody(message.getBody().substring(0, reduceBody));
insertOrdered(messages, message);
}
return messages;
}
private void insertOrdered(List<Message> messages, Message toInsert) {
if (messages.isEmpty())
messages.add(toInsert);
else {
int i;
for ( i=0 ; i<messages.size(); i++)
if (messages.get(i).getCreationTime().getTimeInMillis()<=toInsert.getCreationTime().getTimeInMillis())
break;
messages.add(i, toInsert);
}
}
private Node checkRights(String user, Message messageItem) throws RepositoryException, StorageHubException{
Node personalNode = null;
Node messageNode = (Node) messageItem.getRelatedNode();
if (messageNode.getPath().startsWith(pathUtil.getInboxPath(user).toPath()))
return messageNode;
NodeIterator nodeIt = messageNode.getSharedSet();
while (nodeIt.hasNext()) {
Node node = nodeIt.nextNode();
if (node.getPath().startsWith(pathUtil.getInboxPath(user).toPath()))
personalNode = node;
}
if (personalNode == null &&
!messageItem.getSender().getUserName().equals(user) && !Arrays.asList(messageItem.getAddresses()).contains(user))
throw new UserNotAuthorizedException("user "+currentUser+"cannot read message with id "+id);
return personalNode== null ? messageNode : personalNode;
}
//TODO: move in a common place
@Inject FolderPluginHandler folderPluginHandler;
private Node copyNode(Session session, Node destination, Item itemToCopy) throws RepositoryException, BackendGenericError{
//it needs to be locked ??
Node nodeToCopy = ((Node)itemToCopy.getRelatedNode());
String uniqueName = Utils.checkExistanceAndGetUniqueName(session, destination,itemToCopy.getName() );
String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
session.getWorkspace().copy(nodeToCopy.getPath(), newPath);
Node newNode = session.getNode(newPath);
if (itemToCopy instanceof AbstractFileItem) {
AbstractFileItem newNodeItem = node2Item.getItem(newNode, Excludes.EXCLUDE_ACCOUNTING);
newNodeItem.getContent().setRemotePath(newPath);
String newStorageID = folderPluginHandler.getDefault().getStorageBackend().onCopy(newNodeItem);
newNodeItem.getContent().setStorageId(newStorageID);
item2Node.replaceContent(newNode, newNodeItem, ItemAction.CLONED);
}
Utils.setPropertyOnChangeNode(newNode, currentUser, ItemAction.CLONED);
newNode.setProperty(NodeProperty.PORTAL_LOGIN.toString(), currentUser);
newNode.setProperty(NodeProperty.IS_PUBLIC.toString(), false);
newNode.setProperty(NodeProperty.TITLE.toString(), uniqueName);
return newNode;
}
private int countSharedSet(Node node) throws RepositoryException{
int count =0;
NodeIterator it = node.getSharedSet();
while (it.hasNext()) {
count ++;
it.next();
}
return count;
}
}

View File

@ -5,4 +5,6 @@ import javax.jcr.Repository;
public interface RepositoryInitializer {
Repository getRepository();
void shutdown();
}

View File

@ -2,13 +2,17 @@ package org.gcube.data.access.storagehub.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.query.QueryResult;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@ -20,49 +24,86 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.Query;
import org.apache.jackrabbit.api.security.user.QueryBuilder;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.core.security.principal.PrincipalImpl;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.GroupHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.UnshareHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("users")
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class UserManager {
private static final String INFRASTRUCTURE_MANAGER_ROLE = "Infrastructure-Manager";
@Context ServletContext context;
private static final Logger log = LoggerFactory.getLogger(UserManager.class);
@Inject
RepositoryInitializer repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
UnshareHandler unshareHandler;
@Inject
AuthorizationChecker authChecker;
@Inject
TrashHandler trashHandler;
@Inject
GroupHandler groupHandler;
@Inject
PathUtil pathUtil;
@GET
@Path("")
@Produces(MediaType.APPLICATION_JSON)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
public List<String> getUsers(){
InnerMethodName.instance.set("getUsers");
JackrabbitSession session = null;
List<String> users= new ArrayList<>();
List<String> users = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Iterator<Authorizable> result = session.getUserManager().findAuthorizables(new Query() {
@Override
@ -71,11 +112,19 @@ public class UserManager {
}
});
Set<String> usersSet= new HashSet<>();
String adminUser = context.getInitParameter(Constants.ADMIN_PARAM_NAME);
while (result.hasNext()) {
Authorizable user = result.next();
log.debug("user {} found",user.getPrincipal().getName());
users.add(user.getPrincipal().getName());
if (user.getPrincipal().getName().equals(adminUser)) continue;
usersSet.add(user.getPrincipal().getName());
}
users = new ArrayList<>(usersSet);
Collections.sort(users);
}catch(Exception e) {
log.error("jcr error getting users", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
@ -86,36 +135,87 @@ public class UserManager {
return users;
}
@GET
@Path("{user}")
public String getUser(@PathParam("user") String user){
InnerMethodName.instance.set("getUser");
JackrabbitSession session = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
Authorizable authorizable = usrManager.getAuthorizable(user);
if (authorizable != null && !authorizable.isGroup())
return authorizable.getPrincipal().getName();
log.debug("user {} not found", user);
}catch(Exception e) {
log.error("jcr error getting user", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
} finally {
if (session!=null)
session.logout();
}
GXOutboundErrorResponse.throwException(new IdNotFoundException(user));
return null;
}
@POST
@Path("")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String createUser(@FormParam("user") String user, @FormParam("password") String password){
InnerMethodName.instance.set("createUser");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
User createdUser = usrManager.createUser(user, password);
userId = createdUser.getID();
Node homeNode = session.getNode("/Home");
Node userHome = homeNode.addNode(user, "nthl:home");
userHome.setProperty(Constants.HOME_VERSION_PROP, 1l);
//creating workspace folder
Node workspaceFolder = Utils.createFolderInternally(session, userHome, Constants.WORKSPACE_ROOT_FOLDER_NAME, "workspace of "+user, false, user, null);
FolderCreationParameters wsFolderParameters = FolderCreationParameters.builder().name(Constants.WORKSPACE_ROOT_FOLDER_NAME).description("workspace of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(wsFolderParameters, null);
//creating thrash folder
Utils.createFolderInternally(session, workspaceFolder, Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME).description("trash of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(trashFolderParameters, null);
//creating Vre container folder
Utils.createFolderInternally(session, workspaceFolder, Constants.VRE_FOLDER_PARENT_NAME, "special folder container of "+user, false, user, null);
FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder().name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(vreFolderParameters, null);
//creating inbox folder
FolderCreationParameters inboxFolderParameters = FolderCreationParameters.builder().name(Constants.INBOX_FOLDER_NAME).description("inbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(inboxFolderParameters, null);
//creating outbox folder
FolderCreationParameters outboxFolderParameters = FolderCreationParameters.builder().name(Constants.OUTBOX_FOLDER_NAME).description("outbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(outboxFolderParameters, null);
session.save();
}catch(Exception e) {
log.error("jcr error creating user {}", user, e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
@ -126,51 +226,144 @@ public class UserManager {
@DELETE
@Path("{id}")
@AuthorizationControl(allowed={"lucio.lelii"}, exception=MyAuthException.class)
public String deleteUser(@PathParam("id") String id){
@Path("{user}")
@AuthorizationControl(allowedRoles={INFRASTRUCTURE_MANAGER_ROLE}, exception=MyAuthException.class)
public String deleteUser(@PathParam("user") final String user){
InnerMethodName.instance.set("deleteUser");
JackrabbitSession session = null;
String userId = null;
try {
session = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
org.gcube.common.storagehub.model.Path path = Utils.getWorkspacePath(id);
User authorizable = (User) usrManager.getAuthorizable(new PrincipalImpl(user));
if (authorizable!=null)
removeUserFromBelongingGroup(session, authorizable, usrManager);
else log.warn("user was already deleted from jackrabbit, trying to delete folders");
String sql2Query = String.format("SELECT * FROM [nthl:workspaceSharedItem] AS node WHERE ISDESCENDANTNODE('%s')", path.toPath());
unshareUsersFolders(session, user);
log.info("query sent is {}",sql2Query);
removeUserHomeAndDeleteFiles(session, user);
javax.jcr.query.Query jcrQuery = session.getWorkspace().getQueryManager().createQuery(sql2Query, Constants.QUERY_LANGUAGE);
QueryResult result = jcrQuery.execute();
NodeIterator nodeIt = result.getNodes();
while (nodeIt.hasNext()) {
Node rNode = nodeIt.nextNode();
String title = rNode.hasProperty(NodeProperty.TITLE.toString()) ? rNode.getProperty(NodeProperty.TITLE.toString()).getString():"unknown";
log.debug("removing sharing for folder name {} with title {} and path {} ",rNode.getName(), title, rNode.getPath());
unshareHandler.unshare(session, Collections.singleton(id), rNode, id);
}
Authorizable authorizable = usrManager.getAuthorizable(new PrincipalImpl(id));
if (!authorizable.isGroup()) {
log.info("removing user {}", id);
//FINALIZE user removal
if (authorizable!=null && !authorizable.isGroup()) {
log.info("removing user {}", user);
authorizable.remove();
}
} else log.warn("the user {} was already deleted, it should never happen", user);
session.save();
}catch(Exception e) {
log.error("jcr error getting users", e);
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}catch(RepositoryException re ){
log.error("jcr error creating item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
} finally {
if (session!=null)
session.logout();
}
return userId;
return user;
}
private void removeUserFromBelongingGroup(JackrabbitSession session, User authorizable, org.apache.jackrabbit.api.security.user.UserManager usrManager) throws RepositoryException, StorageHubException {
Iterator<Authorizable> groups = session.getUserManager().findAuthorizables(new Query() {
@Override
public <T> void build(QueryBuilder<T> builder) {
builder.setSelector(Group.class);
}
});
String user = authorizable.getPrincipal().getName();
while(groups.hasNext()) {
Authorizable group = groups.next();
log.info("group found {}", group.getPrincipal().getName() );
if (group.isGroup() && ((Group)group).isMember(authorizable)) {
boolean success = groupHandler.removeUserFromGroup(group.getPrincipal().getName(), user, session);
log.warn("user {} {} removed from vre {}",user,success?"":"not" ,group.getPrincipal().getName());
}
}
}
private void unshareUsersFolders(JackrabbitSession session, String user){
try {
Node sharedFolderNode = session.getNode(Constants.SHARED_FOLDER_PATH);
Predicate<Node> sharedWithUserChecker = new Predicate<Node>() {
@Override
public boolean test(Node t) {
try {
authChecker.checkReadAuthorizationControl(t.getSession(), user, t.getIdentifier());
return true;
} catch (UserNotAuthorizedException | BackendGenericError | RepositoryException e) {
return false;
}
}
};
List<SharedFolder> items = Utils.getItemList(sharedWithUserChecker, sharedFolderNode, Excludes.ALL, null, false, SharedFolder.class);
log.debug(" Shared folder to unshare found are {}", items.size());
for (SharedFolder item: items) {
String title = item.getTitle();
log.debug("in list folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
if (item.isPublicItem() && !item.getUsers().getMap().containsKey(user)) continue;
if (item.isVreFolder()) continue;
log.info("removing sharing for folder name {} with title {} and path {} ",item.getName(), title, item.getPath());
String owner = item.getOwner();
Set<String> usersToUnshare= owner.equals(user)? Collections.emptySet():Collections.singleton(user);
try {
unshareHandler.unshareForRemoval(session, usersToUnshare, session.getNodeByIdentifier(item.getId()), user);
}catch (Throwable e) {
log.warn("error unsharing folder with title '{}' and id {} ", title, item.getId(), e);
}
}
} catch (Throwable t) {
log.warn("error getting folder shared with {}",user, t);
}
}
private void removeUserHomeAndDeleteFiles(JackrabbitSession session, String user) throws RepositoryException, StorageHubException {
org.gcube.common.storagehub.model.Path homePath = pathUtil.getHome(user);
org.gcube.common.storagehub.model.Path workspacePath = pathUtil.getWorkspacePath(user);
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(user, session);
try {
Node workspaceNode = session.getNode(workspacePath.toPath());
List<Item> workspaceItems = Utils.getItemList(workspaceNode, Excludes.GET_ONLY_CONTENT, null, true, null).stream().filter(i -> !i.isShared()).collect(Collectors.toList());
trashHandler.removeOnlyNodesContent(session, workspaceItems);
} catch (PathNotFoundException e) {
log.warn("{} workspace dir {} was already deleted", user, homePath.toPath());
}
try {
Node trashNode = session.getNode(trashPath.toPath());
List<Item> trashItems = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
trashHandler.removeOnlyNodesContent(session, trashItems);
} catch (PathNotFoundException e) {
log.warn("{} trash dir {} was already deleted", user, homePath.toPath());
}
try {
Node homeNode = session.getNode(homePath.toPath());
homeNode.remove();
} catch (PathNotFoundException e) {
log.warn("{} home dir {} was already deleted", user, homePath.toPath());
}
}
}

View File

@ -1,87 +1,91 @@
package org.gcube.data.access.storagehub.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.expressions.Expression;
import org.gcube.common.storagehub.model.expressions.logical.And;
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.VRE;
import org.gcube.data.access.storagehub.handlers.VREManager;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.handlers.vres.VRE;
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("")
public class WorkspaceManager {
@Path("/")
@ManagedBy(StorageHubAppllicationManager.class)
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class WorkspaceManager extends Impersonable{
private static final Logger log = LoggerFactory.getLogger(WorkspaceManager.class);
@Inject
RepositoryInitializer repository;
RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
Evaluators evaluator;
@Inject
AuthorizationChecker authChecker;
@Inject
ServletContext context;
PathUtil pathUtil;
@Inject
VREManager vreManager;
@Context
ServletContext context;
@Inject
AuthorizationChecker authChecker;
@Inject
TrashHandler trashHandler;
@ -92,9 +96,11 @@ public class WorkspaceManager {
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject StorageBackendHandler storageBackend;
@Inject
FolderPluginHandler folderHandler;
@Path("")
@Path("/")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
@ -102,25 +108,24 @@ public class WorkspaceManager {
Session ses = null;
org.gcube.common.storagehub.model.Path absolutePath;
if (relPath==null)
absolutePath = Utils.getWorkspacePath();
else absolutePath = Paths.append(Utils.getWorkspacePath(), relPath);
absolutePath = pathUtil.getWorkspacePath(currentUser);
else absolutePath = Paths.append(pathUtil.getWorkspacePath(currentUser), relPath);
Item toReturn = null;
try{
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
//TODO: remove it when users will be created via storageHub
String user = AuthorizationProvider.instance.get().getClient().getId();
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
//TODO: remove when all user will have TRASH
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
if (!ses.nodeExists(trashPath.toPath())) {
Utils.createFolderInternally(ses, ses.getNode(Utils.getWorkspacePath().toPath()) , Constants.TRASH_ROOT_FOLDER_NAME, "trash of "+user, false, user, null);
Node wsNode = ses.getNode(pathUtil.getWorkspacePath(currentUser).toPath());
FolderCreationParameters trashFolderParameters = FolderCreationParameters.builder().name(Constants.TRASH_ROOT_FOLDER_NAME)
.description("trash of "+currentUser)
.author(currentUser).on(wsNode.getIdentifier()).with(ses).build();
Utils.createFolderInternally(trashFolderParameters, null);
ses.save();
}
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
Node node = ses.getNode(absolutePath.toPath());
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
authChecker.checkReadAuthorizationControl(ses, currentUser, node.getIdentifier());
toReturn = node2Item.getItem(node, excludes);
}catch(RepositoryException re ){
log.error("jcr error getting workspace item", re);
@ -136,38 +141,17 @@ public class WorkspaceManager {
return new ItemWrapper<Item>(toReturn);
}
private synchronized VRE getVreFolderItem(Session ses) throws RepositoryException, BackendGenericError{
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
VRE vre = vreManager.getVRE(entireScopeName);
if (vre!=null) return vre;
else {
String query = String.format("SELECT * FROM [nthl:workspaceItem] As node WHERE node.[jcr:title] like '%s' AND ISDESCENDANTNODE('%s')",entireScopeName, vrePath.toPath());
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
NodeIterator it = jcrQuery.execute().getNodes();
if (!it.hasNext()) throw new BackendGenericError("vre folder not found for context "+entireScopeName);
Node folder = it.nextNode();
Item vreFolder = node2Item.getItem(folder, excludes);
return vreManager.putVRE(vreFolder);
}
}
@Path("vrefolder")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getVreRootFolder(){
InnerMethodName.instance.set("getVreRootFolder");
Session ses = null;
JackrabbitSession ses = null;
Item vreItem = null;
try {
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
vreItem = getVreFolderItem(ses).getVreFolder();
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
vreItem = vreManager.getVreFolderItem(ses, currentUser, excludes).getVreFolder();
}catch(RepositoryException re ){
log.error("jcr error getting vrefolder", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
@ -186,13 +170,12 @@ public class WorkspaceManager {
@Produces(MediaType.APPLICATION_JSON)
public ItemList getVreFolderRecentsDocument(){
InnerMethodName.instance.set("getVreFolderRecents");
Session ses = null;
JackrabbitSession ses = null;
List<Item> recentItems = Collections.emptyList();
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
VRE vre = getVreFolderItem(ses);
VRE vre = vreManager.getVreFolderItem(ses, currentUser, excludes);
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
recentItems = vre.getRecents();
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
@ -220,12 +203,12 @@ public class WorkspaceManager {
public ItemWrapper<Item> getTrashRootFolder(){
InnerMethodName.instance.set("getTrashRootFolder");
Session ses = null;
String user = AuthorizationProvider.instance.get().getClient().getId();
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
Item item = null;
try{
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node folder = ses.getNode(trashPath.toPath());
@ -242,18 +225,18 @@ public class WorkspaceManager {
}
return new ItemWrapper<Item>(item);
}
@Path("trash/empty")
@DELETE
public String emptyTrash(){
InnerMethodName.instance.set("emptyTrash");
Session ses = null;
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getWorkspacePath(), Constants.TRASH_ROOT_FOLDER_NAME);
String toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
Node trashNode = ses.getNode(trashPath.toPath());
List<Item> itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
trashHandler.removeNodes(ses, itemsToDelete);
@ -273,32 +256,39 @@ public class WorkspaceManager {
}
@PUT
@Consumes(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("trash/restore")
public String restoreItem(String identifier){
public String restoreItem(@FormParam("trashedItemId") String trashedItemId,@FormParam("destinationId") String destinationFolderId){
InnerMethodName.instance.set("restoreItem");
Session ses = null;
String toReturn = null;
try{
log.info("restoring node with id {}", identifier);
//TODO check if it is possible to change all the ACL on a workspace
log.info("restoring node with id {}", trashedItemId);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
final Node nodeToRestore = ses.getNodeByIdentifier(identifier);
final Node nodeToRestore = ses.getNodeByIdentifier(trashedItemId);
Item itemToRestore = node2Item.getItem(nodeToRestore, Excludes.ALL);
if (!(itemToRestore instanceof TrashItem))
throw new InvalidItemException("Only trash items can be restored");
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore);
org.gcube.common.storagehub.model.Path trashPath = pathUtil.getTrashPath(currentUser, ses);
if (!itemToRestore.getPath().startsWith(trashPath.toPath()))
throw new UserNotAuthorizedException("this item is not in the user "+currentUser+" trash");
Item destinationItem = null;
if (destinationFolderId!=null ) {
destinationItem = node2Item.getItem(ses.getNodeByIdentifier(destinationFolderId), Excludes.ALL);
if (!(destinationItem instanceof FolderItem))
throw new InvalidCallParameters("destintation item is not a folder");
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore, (FolderItem) destinationItem, currentUser);
} else
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore, null, currentUser);
}catch(RepositoryException re ){
log.error("error restoring item with id {}",identifier, re);
log.error("error restoring item with id {}",trashedItemId, re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
@ -319,12 +309,13 @@ public class WorkspaceManager {
public ItemList getVreFolders(){
InnerMethodName.instance.set("getVreFolders");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
List<? extends Item> toReturn = null;
org.gcube.common.storagehub.model.Path vrePath = null;
try{
log.info("vres folder path is {}",vrePath.toPath());
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
vrePath = pathUtil.getVREsPath(currentUser, ses);
log.info("vres folder path is {}",vrePath.toPath());
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
}catch(RepositoryException re ){
log.error("error reading the node children of {}",vrePath, re);
@ -346,10 +337,11 @@ public class WorkspaceManager {
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
InnerMethodName.instance.set("getVreFoldersPaged");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getWorkspacePath(), Constants.VRE_FOLDER_PARENT_NAME);
org.gcube.common.storagehub.model.Path vrePath = null;
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
vrePath = pathUtil.getVREsPath(currentUser, ses);
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false, null);
}catch(RepositoryException re ){
log.error("(paged) error reading the node children of {}",vrePath, re);
@ -367,64 +359,11 @@ public class WorkspaceManager {
@Path("query")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemList searchItems(@QueryParam("n") String node, @QueryParam("e") String jsonExpr, @QueryParam("o") List<String> orderField, @QueryParam("l") Integer limit, @QueryParam("f") Integer offset){
InnerMethodName.instance.set("searchItems");
Session ses = null;
List<? extends Item> toReturn = new ArrayList<>();
try{
ObjectMapper mapper = new ObjectMapper();
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getWorkspacePath()), expression));
String orderBy = "";
if (orderField!=null && orderField.size()>0)
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
log.info("query sent is {}",sql2Query);
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(sql2Query, Constants.QUERY_LANGUAGE);
if (limit!=null && limit!=-1 )
jcrQuery.setLimit(limit);
if (offset!=null && offset!=-1 )
jcrQuery.setOffset(offset);
QueryResult result = jcrQuery.execute();
NodeIterator it = result.getNodes();
while (it.hasNext())
toReturn.add(node2Item.getItem(it.nextNode(), null));
}catch(RepositoryException | IOException re ){
log.error("error executing the query", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@Path("count")
@GET
public String getTotalItemsCount(){
InnerMethodName.instance.set("getTotalItemsCount");
return storageBackend.getTotalItemsCount();
return folderHandler.getDefault().getStorageBackend().getTotalItemsCount();
}
@ -432,7 +371,7 @@ public class WorkspaceManager {
@GET
public String getTotalVolume(){
InnerMethodName.instance.set("getTotalSize");
return storageBackend.getTotalVolume();
return folderHandler.getDefault().getStorageBackend().getTotalSizeStored();
}

View File

@ -0,0 +1,200 @@
package org.gcube.data.access.storagehub.services.admin;
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.io.ReaderInputStream;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.data.access.storagehub.PathUtil;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
import org.gcube.data.access.storagehub.scripting.AbstractScript;
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
@Path("admin/script")
@RequestHeaders({
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
})
public class ScriptManager {
private static Logger log = LoggerFactory.getLogger(ScriptManager.class);
private RepositoryInitializer repository = StorageHubAppllicationManager.repository;
@Inject
AccountingHandler accountingHandler;
@Context
ServletContext context;
@Inject
ScriptUtil scriptUtil;
@Inject
ItemHandler itemHandler;
@Inject
PathUtil pathUtil;
@POST
@Path("execute")
@AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String run( @FormDataParam("name") String name,
@FormDataParam("asynch") Boolean asynch,
@FormDataParam("destinationFolderId") String destinationFolderId,
@FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {
try {
ScriptClassLoader scriptClassLoader = new ScriptClassLoader(Thread.currentThread().getContextClassLoader());
Class<?> scriptClass = uploadClass(stream, scriptClassLoader, fileDetail.getFileName().replace(".class", ""));
return run(scriptClass, name, destinationFolderId, asynch!=null? asynch : false);
}catch(Throwable e) {
log.error("error executing script {}", name,e);
throw new WebApplicationException("error loading class",e);
}
}
private Class<?> uploadClass(InputStream stream, ScriptClassLoader classLoader, String name) throws Throwable {
try(ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
int nRead;
byte[] data = new byte[1024];
while ((nRead = stream.read(data, 0, data.length)) != -1)
buffer.write(data, 0, nRead);
buffer.flush();
byte[] byteArray = buffer.toByteArray();
return classLoader.findClass(name, byteArray);
}
}
private String run(Class<?> clazz, String name, String destinationFolderId, boolean asynch) throws Throwable {
String login = AuthorizationProvider.instance.get().getClient().getId();
log.info("script {} called by {}", clazz.getSimpleName(), login);
JackrabbitSession ses = null;
try {
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
String parentId = destinationFolderId!=null ? destinationFolderId : ses.getNode(pathUtil.getWorkspacePath(login).toPath()).getIdentifier();
Node parentNode = ses.getNodeByIdentifier(parentId);
String parentPath = parentNode.getPath();
if (AbstractScript.class.isAssignableFrom(clazz)) {
AbstractScript scriptInstance = (AbstractScript) clazz.newInstance();
RealRun realRun = new RealRun(ses, scriptInstance, login, parentId, name);
if (asynch) {
new Thread(AuthorizedTasks.bind(realRun)).start();
}else realRun.run();
} else throw new Exception("class "+clazz.getSimpleName()+" not implements AbstractScript");
return Paths.append(Paths.getPath(parentPath), name).toPath();
}catch (Throwable e) {
if (ses !=null && ses.isLive())
ses.logout();
throw e;
}
}
class RealRun implements Runnable{
private JackrabbitSession ses;
AbstractScript instance;
String login;
String parentId;
String name;
public RealRun(JackrabbitSession ses, AbstractScript instance, String login, String parentId, String name) {
super();
this.ses = ses;
this.instance = instance;
this.login = login;
this.parentId = parentId;
this.name = name;
}
@Override
public void run() {
try{
String result ="";
try {
result = instance.run(ses, null, scriptUtil);
log.info("result is {}",result);
}catch(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
result+= "\n"+sw.toString();
}
try( InputStream stream = new ReaderInputStream(new StringReader(result))){
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description("result of script execution "+name)
.stream(stream).on(parentId).with(ses).author(login);
itemHandler.create(builder.build());
} catch (Throwable e) {
log.error("error saving script result {} in the Workspace",name, e);
}
} finally {
if (ses!=null)
ses.logout();
}
}
}
class ScriptClassLoader extends ClassLoader{
public ScriptClassLoader(ClassLoader parent) {
super(parent);
}
public Class<?> findClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}
}

View File

@ -0,0 +1,32 @@
package org.gcube.data.access.storagehub.services.admin;
import java.util.List;
import java.util.function.Predicate;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
@Singleton
public class ScriptUtilImpl implements ScriptUtil {
@Inject Node2ItemConverter node2Item;
@Override
public List<Item> getChildren(Predicate<Node> checker, Node parent, List<String> excludes, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError {
return Utils.getItemList(checker, parent, excludes, null, showHidden, nodeTypeToInclude);
}
@Override
public Item getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError {
return node2Item.getItem(node, excludes);
}
}

View File

@ -0,0 +1,107 @@
package org.gcube.data.access.storagehub.services.delegates;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.storagehub.model.acls.ACL;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ACLManagerDelegate implements ACLManagerInterface {
@Inject
Node2ItemConverter node2Item;
private static final Logger log = LoggerFactory.getLogger(ACLManagerDelegate.class);
@Override
public List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError {
List<ACL> acls = new ArrayList<>();
if (!item.isShared()) return acls;
Node toRetrieve = (Node) item.getRelatedNode();
if (!(item instanceof SharedFolder))
toRetrieve = retrieveSharedFolderParent(toRetrieve, session);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, toRetrieve.getPath());
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
ACL acl = new ACL();
acl.setPricipal(aclEntry.getPrincipal().getName());
List<AccessType> types = new ArrayList<>();
for (Privilege priv : aclEntry.getPrivileges())
try {
types.add(AccessType.fromValue(priv.getName()));
}catch (Exception e) {
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
}
acl.setAccessTypes(types);
acls.add(acl);
}
return acls;
}
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
else
return retrieveSharedFolderParent(node.getParent(), session);
}
@Override
public void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException {
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
_remove(acls, principal);
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
acls.addAccessControlEntry(principal, userPrivileges);
acm.setPolicy(folder.getPath(), acls);
session.save();
}
@Override
public void delete(String targetUser, SharedFolder folder, Session session) throws RepositoryException {
AccessControlManager acm = session.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
_remove(acls, principal);
acm.setPolicy(folder.getPath(), acls);
}
private void _remove(JackrabbitAccessControlList acls, Principal principal) throws RepositoryException {
AccessControlEntry aceToDelete = null;
for (AccessControlEntry ace : acls.getAccessControlEntries())
if (ace.getPrincipal().equals(principal)) {
aceToDelete = ace;
break;
}
if (aceToDelete!= null)
acls.removeAccessControlEntry(aceToDelete);
}
}

View File

@ -0,0 +1,42 @@
package org.gcube.data.access.storagehub.services.interfaces;
import java.util.List;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.acls.ACL;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
public interface ACLManagerInterface {
/**
* returns the AccessType for all the users in a shared folder
*
* @exception {@link RepositoryException} when a generic jcr error occurs
* @exception {@link UserNotAuthorizedException} when the caller is not authorized to access to the shared folder
*/
List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError;
/**
* Set a new AccessType for a user in a shared folder or VRE folder
*
*
* @param String user
* @param accessType accessType
*
* @exception {@link RepositoryException} when a generic jcr error occurs
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
* @exception {@link InvalidItemException} when the folder is not share
*/
void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException;
void delete(String targetUser, SharedFolder folder, Session session)
throws RepositoryException, StorageHubException;
}

View File

@ -0,0 +1,22 @@
package org.gcube.data.access.storagehub.storage.backend.impl;
import java.util.Map;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
@Singleton
public class GCubeFolderManagerConnector implements FolderManagerConnector {
@Override
public FolderManager connect(FolderItem item, Map<String, Object> parameters) throws PluginInitializationException {
return new GcubeFolderManager();
}
}

View File

@ -1,10 +1,11 @@
package org.gcube.data.access.storagehub.storage.backend.impl;
import java.io.InputStream;
import javax.inject.Singleton;
import java.util.UUID;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.storages.StorageBackend;
import org.gcube.contentmanagement.blobstorage.service.IClient;
@ -14,7 +15,6 @@ import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class GCubeStorageBackend implements StorageBackend {
private static final Logger log = LoggerFactory.getLogger(GCubeStorageBackend.class);
@ -22,9 +22,13 @@ public class GCubeStorageBackend implements StorageBackend {
private final static String SERVICE_NAME = "home-library";
private final static String SERVICE_CLASS = "org.gcube.portlets.user";
protected GCubeStorageBackend() {}
@Override
public InputStream getContent(String id) {
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(id);
public InputStream download(Content content) {
return getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().get().RFileAsInputStream(content.getStorageId());
}
@Override
@ -33,35 +37,38 @@ public class GCubeStorageBackend implements StorageBackend {
}
@Override
public String copy(String idToCopy, String path) {
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(idToCopy).to(path);
log.info("copying storage Id {} to newPath {} and the id returned by storage is {}", idToCopy, path, newStorageID);
public String onCopy(AbstractFileItem item) {
log.info("copying storage Id {} to newPath {}", item.getContent().getStorageId(), item.getPath());
String newStorageID = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().copyFile(true).from(item.getContent().getStorageId()).to(item.getPath());
log.info("The id returned by storage is {}", newStorageID);
return newStorageID;
}
@Override
public String move(String idToMove) {
return idToMove;
public String onMove(AbstractFileItem item) {
return item.getContent().getStorageId();
}
@Override
public MetaInfo upload(InputStream stream, String itemPath) {
public MetaInfo upload(InputStream stream, String relPath, String name) {
log.debug("uploading file");
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
String storageId =storageClient.put(true).LFile(stream).RFile(itemPath);
String uid = UUID.randomUUID().toString();
String remotePath= String.format("%s/%s-%s",relPath,uid,name);
String storageId =storageClient.put(true).LFile(stream).RFile(remotePath);
long size = storageClient.getSize().RFileById(storageId);
MetaInfo info = new MetaInfo();
info.setSize(size);
info.setStorageId(storageId);
info.setRemotePath(itemPath);
info.setRemotePath(remotePath);
return info;
}
@Override
public void delete(String id) {
public void onDelete(Content content) {
log.debug("deleting");
IClient storageClient = getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient();
storageClient.remove().RFileById(id);
storageClient.remove().RFileById(content.getStorageId());
}
private static StorageClient getStorageClient(String login){
@ -82,7 +89,4 @@ public class GCubeStorageBackend implements StorageBackend {
}
}

View File

@ -0,0 +1,48 @@
package org.gcube.data.access.storagehub.storage.backend.impl;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.StorageBackend;
@Singleton
public class GcubeFolderManager implements FolderManager {
@Override
public StorageBackend getStorageBackend() {
return new GCubeStorageBackend();
}
@Override
public boolean manageVersion() {
return true;
}
@Override
public void onCreatedFolder(FolderItem folder) {
}
@Override
public void onDeletingFolder(FolderItem folder) {
}
@Override
public void onMovedFolder(FolderItem movedFolder) {
// TODO Auto-generated method stub
}
@Override
public void onCopiedFolder(FolderItem copiedFolder) {
// TODO Auto-generated method stub
}
@Override
public FolderItem getRootFolder() {
return null;
}
}

View File

@ -0,0 +1,47 @@
package org.gcube.data.access.storagehub.types;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.storages.StorageBackend;
public class ContentPair {
private Content content;
private StorageBackend storageBackend;
public ContentPair(Content content, StorageBackend storageBackend) {
super();
this.content = content;
this.storageBackend = storageBackend;
}
public Content getContent() {
return content;
}
public StorageBackend getStorageBackend() {
return storageBackend;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((content.getStorageId() == null) ? 0 : content.getStorageId().hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContentPair other = (ContentPair) obj;
if (content.getStorageId() == null) {
if (other.content.getStorageId() != null)
return false;
} else if (!content.getStorageId().equals(other.content.getStorageId()))
return false;
return true;
}
}

View File

@ -0,0 +1,16 @@
package org.gcube.data.access.storagehub.types;
import org.gcube.common.storagehub.model.annotations.RootNode;
import org.gcube.common.storagehub.model.messages.Message;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
@RootNode("nthl:itemSentRequestSH")
public class MessageSharable extends Message {
}

View File

@ -1,3 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,6 @@ Licensed under the EUPL V.1.1
or has expressed by any other mean his willingness to license under the EUPL.
1. Definitions
In this Licence, the following terms have the following meaning:
@ -59,7 +58,6 @@ In this Licence, the following terms have the following meaning:
person.
2. Scope of the rights granted by the Licence
The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
@ -85,7 +83,6 @@ any patents held by the Licensor, to the extent necessary to make use of the
rights granted on the Work under this Licence.
3. Communication of the Source Code
The Licensor may provide the Work either in its Source Code form, or as
@ -97,7 +94,6 @@ the Source Code is easily and freely accessible for as long as the Licensor
continues to distribute and/or communicate the Work.
4. Limitations on copyright
Nothing in this Licence is intended to deprive the Licensee of the benefits from
@ -106,7 +102,6 @@ Original Work or Software, of the exhaustion of those rights or of other
applicable limitations thereto.
5. Obligations of the Licensee
The grant of the rights mentioned above is subject to some restrictions and
@ -147,7 +142,6 @@ reasonable and customary use in describing the origin of the Work and
reproducing the content of the copyright notice.
6. Chain of Authorship
The original Licensor warrants that the copyright in the Original Work granted
@ -163,7 +157,6 @@ Contributors grant You a licence to their contributions to the Work, under the
terms of this Licence.
7. Disclaimer of Warranty
The Work is a work in progress, which is continuously improved by numerous
@ -180,7 +173,6 @@ This disclaimer of warranty is an essential part of the Licence and a condition
for the grant of any rights to the Work.
8. Disclaimer of Liability
Except in the cases of wilful misconduct or damages directly caused to natural
@ -193,7 +185,6 @@ damage. However, the Licensor will be liable under statutory product liability
laws as far such laws apply to the Work.
9. Additional agreements
While distributing the Original Work or Derivative Works, You may choose to
@ -207,7 +198,6 @@ by, or claims asserted against such Contributor by the fact You have accepted
any such warranty or additional liability.
10. Acceptance of the Licence
The provisions of this Licence can be accepted by clicking on an icon “I agree”
@ -222,7 +212,6 @@ such as the use of the Work, the creation by You of a Derivative Work or the
Distribution and/or Communication by You of the Work or copies thereof.
11. Information to the public
In case of any Distribution and/or Communication of the Work by means of
@ -233,7 +222,6 @@ applicable law regarding the Licensor, the Licence and the way it may be
accessible, concluded, stored and reproduced by the Licensee.
12. Termination of the Licence
The Licence and the rights granted hereunder will terminate automatically upon
@ -244,7 +232,6 @@ received the Work from the Licensee under the Licence, provided such persons
remain in full compliance with the Licence.
13. Miscellaneous
Without prejudice of Article 9 above, the Licence represents the complete
@ -265,7 +252,6 @@ have identical value. Parties can take advantage of the linguistic version of
their choice.
14. Jurisdiction
Any litigation resulting from the interpretation of this License, arising
@ -279,7 +265,6 @@ exclusive jurisdiction of the competent court where the Licensor resides or
conducts its primary business.
15. Applicable Law
This Licence shall be governed by the law of the European Union country where
@ -298,7 +283,6 @@ This licence shall be governed by the Belgian law if:
Appendix
“Compatible Licences” according to article 5 EUPL are:

View File

@ -25,7 +25,7 @@ no. 654119), SoBigData (grant no. 654024), AGINFRA PLUS (grant no. 731001).
Version
--------------------------------------------------
1.0.7-SNAPSHOT (2019-09-16)
1.4.2 (20230524-150450)
Please see the file named "changelog.xml" in this directory for the release notes.
@ -48,7 +48,7 @@ Download information
--------------------------------------------------
Source code is available from SVN:
${scm.url}
https://code-repo.d4science.org/gCubeSystem/storagehub
Binaries can be downloaded from the gCube website:
https://www.gcube-system.org/

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

@ -0,0 +1,26 @@
.d4science_intro {
top: 0;
z-index: 2000;
position: fixed;
display: block ruby;
padding: 10px;
background: white;
width: 100%;
height: 100px;
}
.navbar-fixed-top {
top: 100px !important;
}
.sidebar {
top: 160px !important;
}
.navbar {
margin-bottom: 40px !important;
}
.main {
top: 90px;
}

View File

@ -9,15 +9,15 @@ import org.gcube.common.storagehub.model.expressions.GenericSearchableItem;
import org.gcube.common.storagehub.model.expressions.date.Before;
import org.gcube.common.storagehub.model.expressions.logical.And;
import org.gcube.common.storagehub.model.expressions.text.Contains;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//@RunWith(WeldJunit4Runner.class)
public class Expressions {
/*
private static Logger log = LoggerFactory.getLogger(Expression.class);
@Inject
@ -36,12 +36,21 @@ public class Expressions {
}
*/
@Test
public void test2() {
String groupId ="/gcube/devsec/devVre";
String title = groupId.substring(groupId.lastIndexOf("/")+1);
System.out.println(title);
public void test() {
String entirePath = "sp2/comic/";
/*String[] parentPathSplit = entirePath.split("/");
System.out.println(parentPathSplit.length);
for (String v: parentPathSplit)
System.out.println(v);
*/
String name = entirePath.replaceAll("([^/]*/)*(.*)", "$2");
String parentPath = entirePath.replaceAll("(([^/]*/)*)(.*)", "$1");
System.out.println(entirePath+" --"+name+"-- "+parentPath);
}
}

View File

@ -5,6 +5,7 @@ import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import javax.jcr.Node;
@ -13,18 +14,23 @@ import javax.jcr.nodetype.NodeType;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vlkan.rfos.RotatingFileOutputStream;
import com.vlkan.rfos.RotationConfig;
import com.vlkan.rfos.policy.DailyRotationPolicy;
import com.vlkan.rfos.policy.SizeBasedRotationPolicy;
public class TestFields {
Logger logger = LoggerFactory.getLogger(TestFields.class);
//@Test
@Test
public void iterateOverFields() throws Exception{
Property prop = mock(Property.class);
@ -63,4 +69,21 @@ public class TestFields {
}
@Test
public void print() throws Exception{
RotationConfig config = RotationConfig
.builder()
.file("/tmp/app.log")
.filePattern("/tmp/app-%d{yyyyMMdd-HHmmss.SSS}.log")
.policy(new SizeBasedRotationPolicy(1024 * 1024 * 100 /* 100MiB */))
.policy(DailyRotationPolicy.getInstance())
.build();
try (RotatingFileOutputStream stream = new RotatingFileOutputStream(config)) {
for (int i =0 ; i<1000 ; i++)
stream.write("Operation: done".getBytes(StandardCharsets.UTF_8));
}
}
}

View File

@ -1,19 +1,5 @@
package org.gcube.data.access.fs;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import java.io.File;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import org.junit.Test;
public class TestNode {
/*@Test