Compare commits
131 Commits
Author | SHA1 | Date |
---|---|---|
Massimiliano Assante | fc37ffec6f | 10 months ago |
lucio | e0a50f2a72 | 10 months ago |
lucio | b4c9cfeee6 | 10 months ago |
lucio | 7920345286 | 10 months ago |
lucio | 80704b9df2 | 10 months ago |
lucio | a42919ffcf | 10 months ago |
lucio | 6b54bf4554 | 10 months ago |
lucio | 122cba00e4 | 10 months ago |
Lucio Lelii | 60d9bf570c | 10 months ago |
Lucio Lelii | f9870a0190 | 10 months ago |
lucio | d9a229929b | 10 months ago |
Lucio Lelii | 0b907277cd | 1 year ago |
Lucio Lelii | 500aaa3fc9 | 1 year ago |
Lucio Lelii | e167aa24d9 | 1 year ago |
Lucio Lelii | 39d73b97c4 | 1 year ago |
Lucio Lelii | 4dc547afd2 | 1 year ago |
Lucio Lelii | 122b326203 | 1 year ago |
Lucio Lelii | 1bbd1d200f | 1 year ago |
Lucio Lelii | 647dbb651a | 2 years ago |
lucio.lelii | 7f88e20a88 | 2 years ago |
lucio.lelii | 08f0160d8d | 2 years ago |
lucio.lelii | 2a46ac3aa2 | 2 years ago |
lucio.lelii | 882f849e2f | 2 years ago |
lucio.lelii | 8c934a138e | 2 years ago |
lucio.lelii | 20390e3147 | 2 years ago |
lucio.lelii | 47bf9b57d2 | 3 years ago |
lucio.lelii | 27c6f2d3e1 | 3 years ago |
lucio.lelii | 586d9df939 | 3 years ago |
lucio.lelii | 7ebd1ae629 | 3 years ago |
lucio.lelii | 51cbd0776a | 3 years ago |
lucio.lelii | f30029c052 | 3 years ago |
Lucio Lelii | 68eb65e168 | 3 years ago |
lucio.lelii | 8fd9bb5ac2 | 3 years ago |
lucio.lelii | 147e8a8961 | 3 years ago |
ROBERTO CIRILLO | 933009f8ab | 3 years ago |
ROBERTO CIRILLO | 0222d27a5e | 3 years ago |
ROBERTO CIRILLO | 082b49ebc6 | 3 years ago |
ROBERTO CIRILLO | e255a2ff5d | 3 years ago |
lucio.lelii | 24576cd30f | 3 years ago |
Lucio Lelii | f68588e05c | 3 years ago |
Lucio Lelii | cb609cf51c | 3 years ago |
Lucio Lelii | 8929ff579c | 3 years ago |
Lucio Lelii | aeb434dd06 | 3 years ago |
lucio.lelii | 470cc28035 | 3 years ago |
lucio.lelii | 13016497f1 | 3 years ago |
lucio.lelii | eab7dc19b4 | 3 years ago |
lucio.lelii | 3723ac730c | 3 years ago |
lucio.lelii | 2aadb9cce7 | 3 years ago |
lucio.lelii | bcbe97f547 | 3 years ago |
lucio.lelii | a2613dc1a7 | 3 years ago |
lucio.lelii | 64952442ed | 3 years ago |
lucio.lelii | e271e9fe78 | 3 years ago |
lucio.lelii | 7566a3cf9f | 3 years ago |
lucio.lelii | 8c677df64e | 3 years ago |
lucio.lelii | 61c84fbb11 | 3 years ago |
lucio.lelii | 31751ca11e | 3 years ago |
lucio.lelii | 7591536a69 | 3 years ago |
lucio.lelii | 6b690caf56 | 3 years ago |
lucio.lelii | 288e8d4254 | 3 years ago |
lucio.lelii | b68d30cd53 | 3 years ago |
lucio.lelii | 7df7afecd3 | 3 years ago |
lucio.lelii | 1e916b21b6 | 3 years ago |
lucio.lelii | 56e01e91f8 | 3 years ago |
lucio.lelii | 94cb6e4cd3 | 3 years ago |
ROBERTO CIRILLO | 5760a44220 | 3 years ago |
lucio.lelii | cbb77864c5 | 3 years ago |
user1 | effbb513a7 | 3 years ago |
user1 | 953cec03ee | 4 years ago |
user1 | 0d499d6c88 | 4 years ago |
user1 | 79f755dc13 | 4 years ago |
user1 | 8b494440af | 4 years ago |
user1 | d57647a714 | 4 years ago |
Fabio Sinibaldi | cb57512174 | 4 years ago |
Lucio Lelii | 2732b05426 | 4 years ago |
Lucio Lelii | 432859d9bb | 4 years ago |
Lucio Lelii | dcf1a614b4 | 4 years ago |
Lucio Lelii | 84cec8aa76 | 4 years ago |
Lucio Lelii | 52df23f2a9 | 4 years ago |
Lucio Lelii | ce8a1e744f | 4 years ago |
Lucio Lelii | 70ae49e28d | 4 years ago |
Lucio Lelii | f2742ce0e0 | 4 years ago |
Lucio Lelii | 7ed01ecc4e | 4 years ago |
Lucio Lelii | 1db74cc4df | 4 years ago |
Lucio Lelii | aae84a27d6 | 4 years ago |
Lucio Lelii | b80f1ccb0d | 4 years ago |
Lucio Lelii | ea438888c8 | 4 years ago |
Lucio Lelii | 01b74ae117 | 4 years ago |
Lucio Lelii | 94d9307b4c | 4 years ago |
Lucio Lelii | e82d695bbf | 4 years ago |
Lucio Lelii | 458b8a72ea | 4 years ago |
Lucio Lelii | 487eae33e2 | 4 years ago |
Lucio Lelii | 08351b2005 | 4 years ago |
Lucio Lelii | 4c13f4098e | 4 years ago |
lucio | 6e69de91d0 | 4 years ago |
lucio | 62fe5a77a0 | 4 years ago |
lucio | acbd780dff | 4 years ago |
lucio | a7ee9afb76 | 4 years ago |
lucio | 9e3b5f08e0 | 4 years ago |
lucio | 133d71f14f | 4 years ago |
Lucio Lelii | 9d895f0adf | 4 years ago |
lucio | 177888e1b4 | 4 years ago |
lucio | 868eadfdaa | 4 years ago |
lucio | 6c9aaa9489 | 4 years ago |
lucio | 774e2b4bfb | 4 years ago |
lucio | fae5173b17 | 4 years ago |
lucio | ddbac93245 | 4 years ago |
lucio | 8a84c93c18 | 4 years ago |
lucio | 2033af4572 | 4 years ago |
lucio | 0711d8a702 | 4 years ago |
lucio | b9d62994f9 | 4 years ago |
lucio | 8f725d46c0 | 4 years ago |
lucio | eb3daa0a26 | 4 years ago |
lucio | e08984af23 | 4 years ago |
lucio | 067f487f8b | 4 years ago |
lucio | df1956c08d | 4 years ago |
Lucio Lelii | 4ebc3ce222 | 4 years ago |
Lucio Lelii | abc2e16cde | 4 years ago |
Lucio Lelii | 0311d9782d | 4 years ago |
lucio | 1bcaa47d48 | 4 years ago |
lucio | 0f645fdde7 | 4 years ago |
lucio | 8ac4752ca7 | 4 years ago |
lucio | a4dc3cff54 | 4 years ago |
lucio | de91f86daf | 4 years ago |
lucio | 188d11ff70 | 4 years ago |
lucio | c1ab8333b8 | 4 years ago |
lucio | 67fe556a4f | 4 years ago |
lucio | 2dc02aa194 | 4 years ago |
lucio | 4802a0542e | 4 years ago |
lucio | 0f156c6637 | 4 years ago |
lucio | 0508aa0e3a | 5 years ago |
lucio | 18cba6c067 | 5 years ago |
@ -1,14 +1,8 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
|
@ -1,16 +1,226 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-module deploy-name="storagehub">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
|
||||
<dependent-module archiveName="authorization-control-library-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/authorization-control-library/authorization-control-library">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module archiveName="storagehub-model-1.0.5.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<property name="context-root" value="storagehub"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</wb-module>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</project-modules>
|
||||
|
@ -0,0 +1,78 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [v1.4.2] - [2023-05-22]
|
||||
|
||||
- added enunciate libraries for documentation
|
||||
|
||||
## [v1.4.1] - [2022-11-14]
|
||||
|
||||
- added libraries to manage different image format
|
||||
|
||||
## [v1.4.0] - [2021-10-07]
|
||||
|
||||
- slow query removed from VRE retrieving and recents
|
||||
- incident #22184 solved
|
||||
|
||||
## [v1.3.2] - [2021-09-28]
|
||||
- fix 22087
|
||||
|
||||
## [v1.3.1] - [2021-09-08]
|
||||
|
||||
- solved bug on attachment rights
|
||||
|
||||
## [v1.3.0] - [2021-03-31]
|
||||
|
||||
- possibility to impersonate people added
|
||||
|
||||
## [v1.2.5] - [2021-03-11]
|
||||
|
||||
use of query (indexes are not working well in jackrabbit) to retrieve shared folder removed on delete user
|
||||
|
||||
## [v1.2.4] - [2021-01-11]
|
||||
|
||||
mimetype set also on non parsable pdf
|
||||
|
||||
method add and remove admin on a VREFolder enabled also for admin role
|
||||
|
||||
fixed bug on unsharing folder on user removal
|
||||
|
||||
added method exist user
|
||||
|
||||
## [v1.2.2] - [2020-10-12]
|
||||
|
||||
method for description update added
|
||||
|
||||
## [v1.2.1] - [2020-06-20]
|
||||
|
||||
bug on Archive uploader solved
|
||||
|
||||
|
||||
|
||||
## [v1.2.0] - [2020-04-15]
|
||||
|
||||
trash items changes owner on restore
|
||||
|
||||
restore with new destination folder added
|
||||
|
||||
move between shared and private or different shared folder enabled
|
||||
|
||||
|
||||
|
||||
## [v1.0.8] - [2019-09-20]
|
||||
|
||||
Bug on ushare owner fixed
|
||||
|
||||
|
||||
|
||||
## [v1.0.5] - [2019-04-04]
|
||||
|
||||
Active wait for lock in case of item creation added
|
||||
|
||||
|
||||
|
||||
## [v1.0.0] - [2015-07-01]
|
||||
|
||||
First commit
|
@ -0,0 +1,26 @@
|
||||
# Acknowledgments
|
||||
|
||||
The projects leading to this software have received funding from a series of European Union programmes including:
|
||||
|
||||
- the Sixth Framework Programme for Research and Technological Development
|
||||
- [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
|
||||
- the Seventh Framework Programme for research, technological development and demonstration
|
||||
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
|
||||
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
|
||||
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
|
||||
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
|
||||
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
|
||||
- the H2020 research and innovation programme
|
||||
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
|
||||
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
|
||||
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
|
||||
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
|
||||
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
|
||||
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
|
||||
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
|
||||
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
|
||||
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
|
||||
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
|
||||
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
|
||||
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
|
||||
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
|
@ -1,14 +0,0 @@
|
||||
<ReleaseNotes>
|
||||
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.8"
|
||||
date="2019-09-20">
|
||||
<Change>Bug on ushare owner fixed</Change>
|
||||
</Changeset>
|
||||
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.5"
|
||||
date="2019-04-04">
|
||||
<Change>Active wait for lock in case of item creation added</Change>
|
||||
</Changeset>
|
||||
<Changeset component="org.gcube.data-access.storagehub-webapp.1.0.0"
|
||||
date="2015-07-01">
|
||||
<Change>First commit</Change>
|
||||
</Changeset>
|
||||
</ReleaseNotes>
|
@ -1,32 +0,0 @@
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
<id>servicearchive</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
<baseDirectory>/</baseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>.</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<includes>
|
||||
<include>README.md</include>
|
||||
<include>LICENSE.md</include>
|
||||
<include>changelog.xml</include>
|
||||
<include>profile.xml</include>
|
||||
</includes>
|
||||
<fileMode>755</fileMode>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<files>
|
||||
<file>
|
||||
<source>target/${build.finalName}.war</source>
|
||||
<outputDirectory>/${artifactId}</outputDirectory>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
</assembly>
|
@ -1,7 +1,8 @@
|
||||
<application mode='online'>
|
||||
<name>StorageHub</name>
|
||||
<group>DataAccess</group>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<version>1.4.2</version>
|
||||
<description>Storage Hub webapp</description>
|
||||
<local-persistence location='target' />
|
||||
<exclude>/workspace/api-docs/*</exclude>
|
||||
</application>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<enunciate
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://enunciate.webcohesion.com/schemas/enunciate-2.14.0.xsd">
|
||||
<api-classes>
|
||||
<!-- Use patterns to exclude classes... e.g. for URI-Resolver <exclude
|
||||
pattern="org.gcube.datatransfer.resolver.services.DocsGenerator" /> -->
|
||||
</api-classes>
|
||||
<modules>
|
||||
<gwt-json-overlay disabled="true" />
|
||||
<php-json-client disabled="true" />
|
||||
<ruby-json-client disabled="true" />
|
||||
<java-json-client disabled="true" />
|
||||
<javascript-client disabled="true" />
|
||||
<docs docsDir="${project.build.directory}" docsSubdir="api-docs" />
|
||||
|
||||
<docs
|
||||
freemarkerTemplate="${project.basedir}/src/main/resources/META-INF/enunciate/d4science_docs.fmt">
|
||||
<additional-css
|
||||
file="css/d4science_enunciate_custom.css" />
|
||||
</docs>
|
||||
<swagger basePath="/workspace" />
|
||||
</modules>
|
||||
</enunciate>
|
@ -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>
|
@ -0,0 +1,42 @@
|
||||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitRepository;
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
import org.glassfish.jersey.server.monitoring.ApplicationEvent;
|
||||
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
|
||||
import org.glassfish.jersey.server.monitoring.RequestEvent;
|
||||
import org.glassfish.jersey.server.monitoring.RequestEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Provider
|
||||
public class MyApplicationListener implements ApplicationEventListener {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(MyApplicationListener.class);
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
|
||||
@Override
|
||||
public void onEvent(ApplicationEvent event) {
|
||||
log.info("StorageHub - event called");
|
||||
switch (event.getType()) {
|
||||
case DESTROY_FINISHED:
|
||||
log.info("Destroying application storageHub");
|
||||
((JackrabbitRepository) repository.getRepository()).shutdown();
|
||||
log.info("Jackrabbit repository stopped");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestEventListener onRequest(RequestEvent requestEvent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
||||
|
||||
public class NodeChildrenFilterIterator implements Iterator<Node> {
|
||||
|
||||
private NodeIterator it;
|
||||
|
||||
public NodeChildrenFilterIterator(Node node) throws BackendGenericError{
|
||||
super();
|
||||
try {
|
||||
it = node.getNodes();
|
||||
} catch (RepositoryException e) {
|
||||
throw new BackendGenericError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public NodeChildrenFilterIterator(NodeIterator iterator) throws BackendGenericError{
|
||||
it = iterator;
|
||||
|
||||
}
|
||||
|
||||
private Node currentNode = null;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
currentNode=it.nextNode();
|
||||
if (ClassHandler.instance().get(currentNode.getPrimaryNodeType().getName())!=null)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}catch (RepositoryException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node next() {
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package org.gcube.data.access.storagehub;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.Path;
|
||||
import org.gcube.common.storagehub.model.Paths;
|
||||
|
||||
@Singleton
|
||||
public class PathUtil {
|
||||
|
||||
public Path getWorkspacePath(String login){
|
||||
return Paths.getPath(String.format("/Home/%s/%s",login,Constants.WORKSPACE_ROOT_FOLDER_NAME));
|
||||
}
|
||||
|
||||
public Path getHome(String login){
|
||||
return Paths.getPath(String.format("/Home/%s",login));
|
||||
}
|
||||
|
||||
public Path getInboxPath(String login) {
|
||||
return Paths.append(getHome(login),Constants.INBOX_FOLDER_NAME);
|
||||
}
|
||||
|
||||
public Path getOutboxPath(String login) {
|
||||
return Paths.append(getHome(login),Constants.OUTBOX_FOLDER_NAME);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private Path getOldTrashPath(String login){
|
||||
return Paths.append(getWorkspacePath(login),Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
}
|
||||
|
||||
private Path getNewTrashPath(String login){
|
||||
return Paths.append(getHome(login), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private Path getOldVREsPath(String login){
|
||||
return Paths.append(getWorkspacePath(login),Constants.OLD_VRE_FOLDER_PARENT_NAME);
|
||||
}
|
||||
|
||||
private Path getNewVREsPath(String login){
|
||||
return Paths.append(getHome(login),Constants.PERSONAL_VRES_FOLDER_PARENT_NAME);
|
||||
}
|
||||
|
||||
public Path getSharedWithMePath(String login){
|
||||
return Paths.append(getWorkspacePath(login),Constants.SHARED_WITH_ME_PARENT_NAME);
|
||||
}
|
||||
|
||||
public Path getVREsPath(String login, Session session) throws RepositoryException {
|
||||
Path home = getHome(login);
|
||||
Node node = session.getNode(home.toPath());
|
||||
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
|
||||
return getNewVREsPath(login);
|
||||
else
|
||||
return getOldVREsPath(login);
|
||||
}
|
||||
|
||||
public Path getTrashPath(String login, Session session) throws RepositoryException {
|
||||
Path home = getHome(login);
|
||||
Node node = session.getNode(home.toPath());
|
||||
if (node.hasProperty(Constants.HOME_VERSION_PROP) && node.getProperty(Constants.HOME_VERSION_PROP).getLong()>0)
|
||||
return getNewTrashPath(login);
|
||||
else
|
||||
return getOldTrashPath(login);
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.Paths;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CompressHandler {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(CompressHandler.class);
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler pluginHandler;
|
||||
|
||||
public Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||
Deque<Item> queue = new LinkedList<Item>();
|
||||
Node currentNode = session.getNodeByIdentifier(directory.getId());
|
||||
queue.push(directory);
|
||||
Deque<Item> tempQueue = new LinkedList<Item>();
|
||||
logger.trace("adding directory {}",currentNode.getPath());
|
||||
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
|
||||
if (excludes.contains(item.getId())) continue;
|
||||
if (item instanceof FolderItem)
|
||||
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, login, accountingHandler, excludes));
|
||||
else if (item instanceof AbstractFileItem){
|
||||
logger.trace("adding file {}",item.getPath());
|
||||
AbstractFileItem fileItem = (AbstractFileItem) item;
|
||||
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
|
||||
queue.addLast(item);
|
||||
}
|
||||
}
|
||||
queue.addAll(tempQueue);
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
public void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath) throws Exception{
|
||||
logger.trace("originalPath is {}",originalPath.toPath());
|
||||
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
|
||||
while (!queue.isEmpty()) {
|
||||
Item item = queue.pop();
|
||||
if (item instanceof FolderItem) {
|
||||
actualPath = Paths.getPath(item.getPath());
|
||||
logger.trace("actualPath is {}",actualPath.toPath());
|
||||
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
|
||||
logger.trace("writing dir {}",name);
|
||||
if (name.isEmpty()) continue;
|
||||
try {
|
||||
zos.putNextEntry(new ZipEntry(name));
|
||||
}finally {
|
||||
zos.closeEntry();
|
||||
}
|
||||
} else if (item instanceof AbstractFileItem){
|
||||
try {
|
||||
AbstractFileItem fileItem = (AbstractFileItem)item;
|
||||
FolderManager manager = pluginHandler.getFolderManager(fileItem);
|
||||
InputStream streamToWrite = manager.getStorageBackend().download(fileItem.getContent());
|
||||
if (streamToWrite == null){
|
||||
logger.warn("discarding item {} ",item.getName());
|
||||
continue;
|
||||
}
|
||||
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
|
||||
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
|
||||
logger.trace("writing file {}",name);
|
||||
zos.putNextEntry(new ZipEntry(name));
|
||||
Utils.copyStream(is, zos);
|
||||
}catch (Exception e) {
|
||||
logger.warn("error writing item {}", item.getName(),e);
|
||||
} finally{
|
||||
zos.closeEntry();
|
||||
}
|
||||
zos.flush();
|
||||
}catch (Throwable e) {
|
||||
logger.warn("error reading content for item {}", item.getPath(),e);
|
||||
}
|
||||
}
|
||||
}
|
||||
zos.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.ItemNotFoundException;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.PathNotFoundException;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.apache.jackrabbit.api.security.user.Group;
|
||||
import org.apache.jackrabbit.api.security.user.User;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.services.GroupManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class GroupHandler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(GroupManager.class);
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
public boolean removeUserFromGroup(String groupId, String userId, JackrabbitSession session) throws StorageHubException, RepositoryException {
|
||||
org.apache.jackrabbit.api.security.user.UserManager usrManager = session.getUserManager();
|
||||
|
||||
Group group = (Group)usrManager.getAuthorizable(groupId);
|
||||
User user = (User)usrManager.getAuthorizable(userId);
|
||||
|
||||
if (!group.isMember(user))
|
||||
throw new InvalidCallParameters("user "+userId+" is not member of group "+groupId);
|
||||
|
||||
//delete folder on user
|
||||
String folderName = group.getPrincipal().getName();
|
||||
Node folder = getFolderNodeRelatedToGroup(session, folderName);
|
||||
|
||||
NodeIterator ni = folder.getSharedSet();
|
||||
while (ni.hasNext()) {
|
||||
Node node = ni.nextNode();
|
||||
if (node.getPath().startsWith(pathUtil.getWorkspacePath(user.getPrincipal().getName()).toPath())) {
|
||||
node.removeShare();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return group.removeMember(user);
|
||||
|
||||
}
|
||||
|
||||
public Node getFolderNodeRelatedToGroup(JackrabbitSession session, String name) throws ItemNotFoundException, RepositoryException {
|
||||
Node sharedRootNode = session.getNode(Constants.SHARED_FOLDER_PATH);
|
||||
|
||||
Node vreFolder = null;
|
||||
try {
|
||||
vreFolder = sharedRootNode.getNode(name);
|
||||
}catch (PathNotFoundException e) {
|
||||
log.debug("is an old HL VRE");
|
||||
}
|
||||
|
||||
if (vreFolder==null) {
|
||||
NodeIterator nodes = sharedRootNode.getNodes();
|
||||
while (nodes.hasNext()) {
|
||||
Node node = nodes.nextNode();
|
||||
if (node.hasProperty(NodeProperty.TITLE.toString()) && node.getProperty(NodeProperty.TITLE.toString()).getString().equals(name)) {
|
||||
vreFolder= node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vreFolder==null) throw new ItemNotFoundException("vre folder not found for group "+name);
|
||||
return vreFolder;
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.GCubeStorageBackend;
|
||||
|
||||
|
||||
@Singleton
|
||||
public class StorageBackendHandler {
|
||||
|
||||
@Inject
|
||||
private GCubeStorageBackend defaultBackend;
|
||||
|
||||
|
||||
public String move(Item item, FolderItem destination) {
|
||||
//if item is a folder we have to move everything
|
||||
return defaultBackend.move(((AbstractFileItem) item).getContent().getStorageId());
|
||||
}
|
||||
|
||||
public String copy(AbstractFileItem item) {
|
||||
return defaultBackend.copy(item.getContent().getStorageId(), item.getContent().getRemotePath());
|
||||
}
|
||||
|
||||
public MetaInfo upload(InputStream stream, String itemPath) {
|
||||
return defaultBackend.upload(stream, itemPath);
|
||||
}
|
||||
|
||||
public InputStream download(String id) {
|
||||
return defaultBackend.getContent(id);
|
||||
}
|
||||
|
||||
public void delete(String id) {
|
||||
defaultBackend.delete(id);
|
||||
}
|
||||
|
||||
public String getTotalVolume() {
|
||||
return defaultBackend.getTotalSizeStored();
|
||||
}
|
||||
|
||||
public String getTotalItemsCount() {
|
||||
return defaultBackend.getTotalItemsCount();
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.SimpleCredentials;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class VREManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
|
||||
|
||||
private Map<String, VRE> vreMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
SimpleCredentials credentials;
|
||||
|
||||
@Inject
|
||||
public VREManager(ServletContext context) {
|
||||
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
|
||||
}
|
||||
|
||||
|
||||
public synchronized VRE getVRE(String completeName) {
|
||||
logger.trace("requesting VRE {}",completeName);
|
||||
if (vreMap.containsKey(completeName))
|
||||
return vreMap.get(completeName);
|
||||
else
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public synchronized VRE putVRE(Item vreFolder) {
|
||||
logger.trace("inserting VRE {}",vreFolder.getTitle());
|
||||
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
|
||||
else {
|
||||
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, executor);
|
||||
vreMap.put(vreFolder.getTitle(), toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
package org.gcube.data.access.storagehub.handlers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.jcr.Credentials;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.Property;
|
||||
import javax.jcr.Repository;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.observation.Event;
|
||||
import javax.jcr.observation.EventJournal;
|
||||
import javax.jcr.query.Query;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.NodeConstants;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VREQueryRetriever implements Callable<List<Item>> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
|
||||
|
||||
private static final int CACHE_DIMENSION = 50;
|
||||
|
||||
private Repository repository;
|
||||
private Credentials credentials;
|
||||
private Item vreFolder;
|
||||
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
|
||||
long lastTimestamp =0;
|
||||
|
||||
private Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||
|
||||
|
||||
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
|
||||
super();
|
||||
this.repository = repository;
|
||||
this.credentials = credentials;
|
||||
this.vreFolder = vreFolder;
|
||||
}
|
||||
|
||||
public List<Item> call() {
|
||||
logger.trace("executing recents task");
|
||||
Session ses = null;
|
||||
if (lastTimestamp==0) {
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
ses = repository.login(credentials);
|
||||
String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
|
||||
logger.trace("query for recents is {}",query);
|
||||
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
|
||||
jcrQuery.setLimit(CACHE_DIMENSION);
|
||||
lastTimestamp = System.currentTimeMillis();
|
||||
NodeIterator it = jcrQuery.execute().getNodes();
|
||||
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
|
||||
while (it.hasNext()) {
|
||||
Node node = it.nextNode();
|
||||
Item item =node2Item.getItem(node, Excludes.EXCLUDE_ACCOUNTING);
|
||||
cachedList.add(item);
|
||||
logger.trace("adding item {} with node {}",item.getTitle(), node.getName());
|
||||
}
|
||||
logger.trace("creating objects took {}",System.currentTimeMillis()-start);
|
||||
if (cachedList.size()<=10) return cachedList;
|
||||
else return cachedList.subList(0, 10);
|
||||
} catch (Exception e) {
|
||||
logger.error("error querying vre {}",vreFolder.getTitle(),e);
|
||||
throw new RuntimeException(e);
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
logger.trace("recents task finished");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
|
||||
long timestampToUse = lastTimestamp;
|
||||
lastTimestamp = System.currentTimeMillis();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
ses = repository.login(credentials);
|
||||
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
|
||||
|
||||
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
|
||||
journalChanged.skipTo(timestampToUse);
|
||||
|
||||
logger.trace("getting the journal took {}",System.currentTimeMillis()-start);
|
||||
|
||||
int events = 0;
|
||||
|
||||
while (journalChanged.hasNext()) {
|
||||
events++;
|
||||
Event event = journalChanged.nextEvent();
|
||||
switch(event.getType()) {
|
||||
|
||||
case Event.NODE_ADDED:
|
||||
if (ses.nodeExists(event.getPath())) {
|
||||
Node nodeAdded = ses.getNode(event.getPath());
|
||||
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
||||
logger.trace("node added event received with name {}", nodeAdded.getName());
|
||||
Item item = node2Item.getItem(nodeAdded, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
||||
insertItemInTheRightPlace(item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Event.PROPERTY_CHANGED:
|
||||
if (ses.propertyExists(event.getPath())) {
|
||||
Property property = ses.getProperty(event.getPath());
|
||||
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
|
||||
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
||||
String identifier = property.getParent().getIdentifier();
|
||||
cachedList.removeIf(i -> i.getId().equals(identifier));
|
||||
Item item = node2Item.getItem(property.getParent(), Excludes.EXCLUDE_ACCOUNTING);
|
||||
insertItemInTheRightPlace(item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Event.NODE_REMOVED:
|
||||
logger.trace("node removed event received with type {}", event.getIdentifier());
|
||||
cachedList.removeIf(i -> {
|
||||
try {
|
||||
return i.getId().equals(event.getIdentifier()) && i.getLastModificationTime().getTime().getTime()<event.getDate();
|
||||
} catch (RepositoryException e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
case Event.NODE_MOVED:
|
||||
Node nodeMoved = ses.getNode(event.getPath());
|
||||
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
|
||||
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
|
||||
logger.trace("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
|
||||
String identifier = nodeMoved.getIdentifier();
|
||||
cachedList.removeIf(i -> i.getId().equals(identifier) && !i.getPath().startsWith(vreFolder.getPath()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception("error in event handling");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (cachedList.size()>CACHE_DIMENSION)
|
||||
cachedList.subList(51, cachedList.size()).clear();
|
||||
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
|
||||
if (cachedList.size()<=10) return cachedList;
|
||||
else return cachedList.subList(0, 10);
|
||||
} catch (Exception e) {
|
||||
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
|
||||
throw new RuntimeException(e);
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void insertItemInTheRightPlace(Item item) {
|
||||
Iterator<Item> it = cachedList.iterator();
|
||||
int index =0;
|
||||
while (it.hasNext()) {
|
||||
Item inListItem = it.next();
|
||||
if (item.getLastModificationTime().getTime().getTime()>=inListItem.getLastModificationTime().getTime().getTime()) break;
|
||||
index++;
|
||||
}
|
||||
if (index<CACHE_DIMENSION)
|
||||
cachedList.add(index, item);
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public void onEvent(EventIterator events) {
|
||||
logger.trace("on event called");
|
||||
while (events.hasNext()) {
|
||||
Event event = events.nextEvent();
|
||||
try {
|
||||
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
|
||||
} catch (RepositoryException e) {
|
||||
logger.error("error reading event",e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
|
||||
public class ArchiveStructureCreationParameter extends CreateParameters {
|
||||
|
||||
String parentFolderName;
|
||||
FormDataContentDisposition fileDetails;
|
||||
InputStream stream;
|
||||
|
||||
|
||||
protected ArchiveStructureCreationParameter() {}
|
||||
|
||||
public String getParentFolderName() {
|
||||
return parentFolderName;
|
||||
}
|
||||
|
||||
public FormDataContentDisposition getFileDetails() {
|
||||
return fileDetails;
|
||||
}
|
||||
|
||||
public InputStream getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(parentFolderName) && Objects.nonNull(stream) && Objects.nonNull(fileDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FileCreationParameters [parentFolder=" + parentFolderName + ", fileDetails=" + fileDetails
|
||||
+ ", parentId=" + parentId + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
public static ArchiveCreationBuilder builder() {
|
||||
return new ArchiveCreationBuilder();
|
||||
}
|
||||
|
||||
public static class ArchiveCreationBuilder extends ItemsParameterBuilder<ArchiveStructureCreationParameter>{
|
||||
|
||||
private ArchiveCreationBuilder() {
|
||||
super(new ArchiveStructureCreationParameter());
|
||||
}
|
||||
|
||||
public ArchiveCreationBuilder parentName(String name) {
|
||||
parameters.parentFolderName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ArchiveCreationBuilder stream(InputStream stream) {
|
||||
parameters.stream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ArchiveCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
|
||||
parameters.fileDetails = fileDetails;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedType getMangedType() {
|
||||
return ManagedType.ARCHIVE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import javax.jcr.Session;
|
||||
|
||||
public abstract class CreateParameters {
|
||||
|
||||
public enum ManagedType {
|
||||
FILE,
|
||||
FOLDER,
|
||||
ARCHIVE,
|
||||
URL,
|
||||
GCUBEITEM;
|
||||
}
|
||||
|
||||
String parentId;
|
||||
Session session;
|
||||
String user;
|
||||
|
||||
protected CreateParameters() {}
|
||||
|
||||
public abstract ManagedType getMangedType();
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
protected abstract boolean isValid();
|
||||
|
||||
public abstract String toString();
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
|
||||
public class FileCreationParameters extends CreateParameters {
|
||||
|
||||
String name;
|
||||
String description;
|
||||
FormDataContentDisposition fileDetails;
|
||||
InputStream stream;
|
||||
|
||||
|
||||
protected FileCreationParameters() {}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public FormDataContentDisposition getFileDetails() {
|
||||
return fileDetails;
|
||||
}
|
||||
|
||||
public InputStream getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FileCreationParameters [name=" + name + ", description=" + description + ", fileDetails=" + fileDetails
|
||||
+ ", parentId=" + parentId + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
public static FileCreationBuilder builder() {
|
||||
return new FileCreationBuilder();
|
||||
}
|
||||
|
||||
public static class FileCreationBuilder extends ItemsParameterBuilder<FileCreationParameters>{
|
||||
|
||||
private FileCreationBuilder() {
|
||||
super(new FileCreationParameters());
|
||||
}
|
||||
|
||||
public FileCreationBuilder name(String name) {
|
||||
parameters.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileCreationBuilder description(String description) {
|
||||
parameters.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileCreationBuilder stream(InputStream stream) {
|
||||
parameters.stream = stream;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileCreationBuilder fileDetails(FormDataContentDisposition fileDetails) {
|
||||
parameters.fileDetails = fileDetails;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedType getMangedType() {
|
||||
return ManagedType.FILE;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.gcube.common.storagehub.model.plugins.PluginParameters;
|
||||
|
||||
public class FolderCreationParameters extends CreateParameters {
|
||||
|
||||
private String name;
|
||||
private String description="";
|
||||
private boolean hidden = false;
|
||||
private String externalPluginName = null;
|
||||
private PluginParameters externalPluginParameters = null;
|
||||
|
||||
protected FolderCreationParameters() {}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
public boolean isExternal() {
|
||||
return externalPluginName!=null;
|
||||
}
|
||||
|
||||
public String getPluginName(String name) {
|
||||
return this.externalPluginName;
|
||||
}
|
||||
|
||||
public PluginParameters getPluginParameters() {
|
||||
return externalPluginParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(name) && Objects.nonNull(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FolderCreationParameters [name=" + name + ", description=" + description + ", hidden=" + hidden
|
||||
+ ", parentId=" + parentId + ", session=" + session + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
|
||||
public static FolderCreationBuilder builder() {
|
||||
return new FolderCreationBuilder();
|
||||
}
|
||||
|
||||
public static class FolderCreationBuilder extends ItemsParameterBuilder<FolderCreationParameters>{
|
||||
|
||||
private FolderCreationBuilder() {
|
||||
super(new FolderCreationParameters());
|
||||
}
|
||||
|
||||
public FolderCreationBuilder name(String name) {
|
||||
parameters.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FolderCreationBuilder description(String description) {
|
||||
parameters.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExternalFolderCreationBuilder onRepository(String pluginName) {
|
||||
return new ExternalFolderCreationBuilder(pluginName, this);
|
||||
}
|
||||
|
||||
public FolderCreationBuilder hidden(boolean hidden) {
|
||||
parameters.hidden = hidden;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ExternalFolderCreationBuilder {
|
||||
|
||||
FolderCreationBuilder cb;
|
||||
|
||||
protected ExternalFolderCreationBuilder(String pluginName, FolderCreationBuilder cb) {
|
||||
this.cb.parameters.externalPluginName = pluginName;
|
||||
}
|
||||
|
||||
public FolderCreationBuilder withParameters(PluginParameters params){
|
||||
this.cb.parameters.externalPluginParameters = params;
|
||||
return this.cb;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ManagedType getMangedType() {
|
||||
return ManagedType.FOLDER;
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||
|
||||
public class GCubeItemCreationParameters extends CreateParameters{
|
||||
|
||||
GCubeItem item;
|
||||
|
||||
|
||||
protected GCubeItemCreationParameters() {}
|
||||
|
||||
public GCubeItem getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GCubeItemCreationParameters [item=" + item + ", parentId=" + parentId + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
public static GCubeItemCreationBuilder builder() {
|
||||
return new GCubeItemCreationBuilder();
|
||||
}
|
||||
|
||||
public static class GCubeItemCreationBuilder extends ItemsParameterBuilder<GCubeItemCreationParameters>{
|
||||
|
||||
private GCubeItemCreationBuilder() {
|
||||
super(new GCubeItemCreationParameters());
|
||||
}
|
||||
|
||||
public GCubeItemCreationBuilder item(GCubeItem item) {
|
||||
parameters.item = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedType getMangedType() {
|
||||
return ManagedType.GCUBEITEM;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
|
||||
public abstract class ItemsParameterBuilder<T extends CreateParameters> {
|
||||
|
||||
T parameters;
|
||||
|
||||
protected ItemsParameterBuilder(T parameters) {
|
||||
super();
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public ItemsParameterBuilder<T> on(String parentId) {
|
||||
parameters.parentId = parentId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemsParameterBuilder<T> author(String author) {
|
||||
parameters.user = author;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemsParameterBuilder<T> with(Session session){
|
||||
parameters.session = session;
|
||||
return this;
|
||||
}
|
||||
|
||||
public T build() throws InvalidCallParameters {
|
||||
if (!(parameters.isValid() && Objects.nonNull(parameters.parentId)))
|
||||
throw new InvalidCallParameters("invalid call");
|
||||
return parameters;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.gcube.data.access.storagehub.handlers.items.builders;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
|
||||
public class URLCreationParameters extends CreateParameters {
|
||||
|
||||
String name;
|
||||
String description;
|
||||
URL url;
|
||||
|
||||
|
||||
protected URLCreationParameters() {}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isValid() {
|
||||
return Objects.nonNull(name) && Objects.nonNull(description) && Objects.nonNull(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "URLCreationParameters [name=" + name + ", description=" + description + ", url=" + url + ", parentId="
|
||||
+ parentId + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
public static URLCreationBuilder builder() {
|
||||
return new URLCreationBuilder();
|
||||
}
|
||||
|
||||
public static class URLCreationBuilder extends ItemsParameterBuilder<URLCreationParameters>{
|
||||
|
||||
private URLCreationBuilder() {
|
||||
super(new URLCreationParameters());
|
||||
}
|
||||
|
||||
public URLCreationBuilder name(String name) {
|
||||
parameters.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URLCreationBuilder description(String description) {
|
||||
parameters.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public URLCreationBuilder url(URL url) {
|
||||
parameters.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManagedType getMangedType() {
|
||||
return ManagedType.URL;
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.inject.Default;
|
||||
import javax.enterprise.inject.Instance;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
|
||||
import org.gcube.common.storagehub.model.items.ExternalFolder;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeFolderManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class FolderPluginHandler {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(FolderPluginHandler.class);
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
private GcubeFolderManager defaultManager = new GcubeFolderManager();
|
||||
|
||||
public FolderManager getDefault() {
|
||||
return defaultManager;
|
||||
}
|
||||
|
||||
@Inject
|
||||
Instance<FolderManagerConnector> connectors;
|
||||
|
||||
private Map<String, FolderManagerConnector> connectorsMap;
|
||||
|
||||
FolderPluginHandler(){
|
||||
if (connectors !=null)
|
||||
connectorsMap = connectors.stream().collect(Collectors.toMap(FolderManagerConnector::getName, e -> e ));
|
||||
else {
|
||||
log.info("connectors are null");
|
||||
connectorsMap = Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
public FolderManagerConnector getConnector(String name) throws PluginNotFoundException {
|
||||
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
|
||||
return connectorsMap.get(name);
|
||||
}
|
||||
|
||||
public FolderManager getFolderManager(Item item) throws PluginInitializationException, PluginNotFoundException, RepositoryException, BackendGenericError{
|
||||
if (!item.isExternalManaged())
|
||||
return defaultManager;
|
||||
Session session = ((Node)item.getRelatedNode()).getSession();
|
||||
Item parent = null;
|
||||
do {
|
||||
String parentId = item.getParentId();
|
||||
Node node = session.getNodeByIdentifier(parentId);
|
||||
parent = node2Item.getItem(node, Excludes.ALL);
|
||||
|
||||
if (parent !=null && parent instanceof ExternalFolder) {
|
||||
ExternalFolder extParent = (ExternalFolder) parent;
|
||||
String plugin = extParent.getManagedBy();
|
||||
Map<String, Object> parameters = extParent.getConnectionParameters().getMap();
|
||||
return getConnector(plugin).connect(extParent, parameters);
|
||||
}
|
||||
} while (parent!=null);
|
||||
throw new BackendGenericError("selected external managed item doesn't have a parent external folder");
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package org.gcube.data.access.storagehub.handlers.plugins;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@Singleton
|
||||
public class OperationMediator {
|
||||
|
||||
@Inject
|
||||
FolderPluginHandler folderHandler;
|
||||
|
||||
/*
|
||||
boolean onMove(Item source, Item destination, Session session) throws PluginInitializationException, PluginNotFoundException, BackendGenericError, RepositoryException{
|
||||
FolderManager sourceFolderManager = folderHandler.getFolderManager(source);
|
||||
FolderManager destinationFolderManager = folderHandler.getFolderManager(destination);
|
||||
|
||||
if (source instanceof FolderItem) {
|
||||
destinationFolderManager.onCreatedFolder((FolderItem) source);
|
||||
|
||||
|
||||
session.move(source.getPath(), destination.getPath());
|
||||
sourceFolderManager.onDeletingFolder((FolderItem) source);
|
||||
} else if (source instanceof AbstractFileItem){
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package org.gcube.data.access.storagehub.handlers.vres;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.SimpleCredentials;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.apache.jackrabbit.api.security.user.Group;
|
||||
import org.apache.jackrabbit.api.security.user.User;
|
||||
import org.apache.jackrabbit.api.security.user.UserManager;
|
||||
import org.gcube.common.scope.api.ScopeProvider;
|
||||
import org.gcube.common.scope.impl.ScopeBean;
|
||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.data.access.storagehub.Constants;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.handlers.GroupHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class VREManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
|
||||
|
||||
private Map<String, VRE> vreMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
RepositoryInitializer repository;
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@Inject
|
||||
GroupHandler groupHandler;
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
SimpleCredentials credentials;
|
||||
|
||||
@Inject
|
||||
public VREManager(ServletContext context) {
|
||||
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
|
||||
}
|
||||
|
||||
|
||||
public synchronized VRE getVRE(String completeName) {
|
||||
logger.trace("requesting VRE {}",completeName);
|
||||
if (vreMap.containsKey(completeName))
|
||||
return vreMap.get(completeName);
|
||||
else
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
private synchronized VRE putVRE(Item vreFolder) {
|
||||
logger.trace("inserting VRE {}",vreFolder.getTitle());
|
||||
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
|
||||
else {
|
||||
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, node2Item, executor);
|
||||
vreMap.put(vreFolder.getTitle(), toReturn);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public synchronized VRE getVreFolderItem(JackrabbitSession ses, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
|
||||
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
|
||||
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
|
||||
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
|
||||
return getVreFolderItemByGroupName(ses, entireScopeName, userId, excludes);
|
||||
}
|
||||
|
||||
|
||||
public synchronized VRE getVreFolderItemByGroupName(JackrabbitSession ses, String groupName, String userId, List<String> excludes ) throws RepositoryException, StorageHubException{
|
||||
UserManager um = ses.getUserManager();
|
||||
Group groupAuth = um.getAuthorizable(groupName, Group.class);
|
||||
User userAuth = um.getAuthorizable(userId, User.class);
|
||||
|
||||
if (groupAuth == null || userAuth == null || !groupAuth.isMember(userAuth))
|
||||
throw new InvalidCallParameters("error getting VRE with user "+userId+" for group "+groupName);
|
||||
|
||||
|
||||
VRE vre = this.getVRE(groupName);
|
||||
if (vre!=null) return vre;
|
||||
else {
|
||||
|
||||
Node vreFolderNode = groupHandler.getFolderNodeRelatedToGroup(ses, groupName);
|
||||
|
||||
Item vreFolder = node2Item.getItem(vreFolderNode, excludes);
|
||||
return this.putVRE(vreFolder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
package org.gcube.data.access.storagehub.handlers.vres;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.jcr.Credentials;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.NodeIterator;
|
||||
import javax.jcr.Property;
|
||||
import javax.jcr.Repository;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.observation.Event;
|
||||
import javax.jcr.observation.EventJournal;
|
||||
|
||||
import org.gcube.common.storagehub.model.Excludes;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VREQueryRetriever implements Callable<List<Item>> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
|
||||
|
||||
private static final int CACHE_DIMENSION = 50;
|
||||
|
||||
private Repository repository;
|
||||
private Credentials credentials;
|
||||
private Item vreFolder;
|
||||
Map<String, Long> cachedMap = new HashMap<>(CACHE_DIMENSION);
|
||||
|
||||
long lastTimestamp =0;
|
||||
|
||||
long doTime= 0;
|
||||
boolean underRedo = false;
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
private static int TIME_MEASURE = Calendar.MINUTE;
|
||||
private static int VALUE_TIME_BEFORE = 30;
|
||||
|
||||
|
||||
public VREQueryRetriever(Repository repository, Credentials credentials, Node2ItemConverter node2Item, Item vreFolder) {
|
||||
super();
|
||||
this.repository = repository;
|
||||
this.credentials = credentials;
|
||||
this.vreFolder = vreFolder;
|
||||
this.node2Item = node2Item;
|
||||
}
|
||||
|
||||
public List<Item> call() {
|
||||
Session ses = null;
|
||||
try {
|
||||
ses = repository.login(credentials);
|
||||
Calendar now = Calendar.getInstance();
|
||||
now.add(TIME_MEASURE, -1*Math.abs(VALUE_TIME_BEFORE));
|
||||
|
||||
if (doTime> now.getTimeInMillis() || underRedo) {
|
||||
logger.debug("executing recents task for {} (cahced result)",vreFolder.getTitle());
|
||||
return correctValues(ses, cachedMap);
|
||||
}else {
|
||||
logger.debug("executing recents task for {} (redoing it)",vreFolder.getTitle());
|
||||
List<Item> toReturn = redo(ses);
|
||||
doTime = System.currentTimeMillis();
|
||||
return toReturn;
|
||||
}
|
||||
}catch (Exception e) {
|
||||
logger.error("error preparing recents for folder {}", vreFolder.getTitle(),e);
|
||||
return Collections.emptyList();
|
||||
}finally{
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
logger.debug("recents task finished");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized List<Item> redo(Session ses) {
|
||||
underRedo = true;
|
||||
try {
|
||||
Map<String, Long> tempCachedMap = new HashMap<>(cachedMap);
|
||||
if (cachedMap.isEmpty())
|
||||
init(ses, tempCachedMap);
|
||||
else {
|
||||
logger.debug("redoing recents for {}",vreFolder.getTitle());
|
||||
update(ses, tempCachedMap);
|
||||
}
|
||||
cachedMap = tempCachedMap;
|
||||
return correctValues(ses, tempCachedMap);
|
||||
}finally{
|
||||
underRedo = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Item> correctValues(Session ses, Map<String, Long> tempCachedMap){
|
||||
logger.debug("preparing returning values for {}",vreFolder.getTitle());
|
||||
long start = System.currentTimeMillis();
|
||||
List<Map.Entry<String, Long>> list = new LinkedList<>(tempCachedMap.entrySet());
|
||||
list.sort((c1, c2) -> c1.getValue().compareTo(c2.getValue())*-1);
|
||||
if (list.size()>CACHE_DIMENSION)
|
||||
for (int index = CACHE_DIMENSION-1; index< list.size() ; index++)
|
||||
tempCachedMap.remove(list.get(index).getKey());
|
||||
|
||||
List<String> cachedIds = list.stream().map(m -> m.getKey()).collect(Collectors.toList());
|
||||
if (cachedIds.size()>10)
|
||||
cachedIds = cachedIds.subList(0, 10);
|
||||
|
||||
List<Item> result = new ArrayList<>(10);
|
||||
|
||||
for (String id: cachedIds) {
|
||||
try {
|
||||
Item item = node2Item.getItem(id, ses, Excludes.EXCLUDE_ACCOUNTING);
|
||||
if (item!=null)
|
||||
result.add(item);
|
||||
else logger.warn("item with id {} is null",id);
|
||||
} catch (BackendGenericError | RepositoryException e) { }
|
||||
}
|
||||
|
||||
logger.debug("returning values prepared in {} for {}",System.currentTimeMillis()-start,vreFolder.getTitle());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void insertItemInTheRightPlace(Item item, Map<String, Long> tempCachedMap) {
|
||||
long lastModifiedTime = item.getLastModificationTime().getTimeInMillis();
|
||||
|
||||
if (tempCachedMap.size()<CACHE_DIMENSION || lastModifiedTime>Collections.min(tempCachedMap.values()))
|
||||
tempCachedMap.put(item.getId(), lastModifiedTime);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void init(Session ses,Map<String, Long> tempCachedMap){
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
lastTimestamp = System.currentTimeMillis();
|
||||
Node vreFolderNode = ses.getNodeByIdentifier(vreFolder.getId());
|
||||
logger.debug("starting visiting children for {}",vreFolder.getTitle());
|
||||
visitChildren(vreFolderNode, tempCachedMap);
|
||||
logger.debug("initializing recents for {} took {}",vreFolder.getTitle(),System.currentTimeMillis()-start);
|
||||
} catch (Exception e) {
|
||||
logger.error("error querying vre {}",vreFolder.getTitle(),e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void update(Session ses, Map<String, Long> tempCachedMap) {
|
||||
try {
|
||||
long timestampToUse = lastTimestamp;
|
||||
lastTimestamp = System.currentTimeMillis();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
|
||||
|
||||
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED^Event.NODE_ADDED, vreFolder.getPath(), true, null, types);
|
||||
journalChanged.skipTo(timestampToUse);
|
||||
|
||||
logger.debug("getting the journal took {}",System.currentTimeMillis()-start);
|
||||
|
||||
int events = 0;
|
||||
|
||||
//TODO: manage hidden nodes
|
||||
while (journalChanged.hasNext()) {
|
||||
events++;
|
||||
Event event = journalChanged.nextEvent();
|
||||
try {
|
||||
switch(event.getType()) {
|
||||
|
||||
case Event.NODE_ADDED:
|
||||
if (ses.nodeExists(event.getPath())) {
|
||||
Node nodeAdded = ses.getNode(event.getPath());
|
||||
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
||||
logger.debug("node added event received with name {}", nodeAdded.getName());
|
||||
Item item = node2Item.getItem(nodeAdded, Excludes.ALL);
|
||||
if (tempCachedMap.get(event.getIdentifier())!=null)
|
||||
tempCachedMap.remove(event.getIdentifier());
|
||||
if (item.isHidden())
|
||||
break;
|
||||
insertItemInTheRightPlace(item,tempCachedMap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Event.PROPERTY_CHANGED:
|
||||
if (ses.propertyExists(event.getPath())) {
|
||||
Property property = ses.getProperty(event.getPath());
|
||||
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
|
||||
logger.debug("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
||||
String identifier = property.getParent().getIdentifier();
|
||||
tempCachedMap.remove(identifier);
|
||||
Item item = node2Item.getItem(property.getParent(), Excludes.ALL);
|
||||
if (item.isHidden())
|
||||
break;
|
||||
insertItemInTheRightPlace(item, tempCachedMap);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Event.NODE_REMOVED:
|
||||
logger.trace("node removed event received with type {}", event.getIdentifier());
|
||||
|
||||
if (tempCachedMap.get(event.getIdentifier())!=null &&
|
||||
tempCachedMap.get(event.getIdentifier())<event.getDate())
|
||||
tempCachedMap.remove(event.getIdentifier());
|
||||
break;
|
||||
case Event.NODE_MOVED:
|
||||
Node nodeMoved = ses.getNode(event.getPath());
|
||||
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
|
||||
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
|
||||
logger.debug("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
|
||||
String identifier = nodeMoved.getIdentifier();
|
||||
String nodePath = ses.getNode(identifier).getPath();
|
||||
if (tempCachedMap.get(event.getIdentifier())!=null &&
|
||||
!nodePath.startsWith(vreFolder.getPath()))
|
||||
tempCachedMap.remove(event.getIdentifier());
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}catch (Exception e) {
|
||||
logger.warn("error handling event {}",event.getType(),e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
logger.trace("retrieving event took {} with {} events",System.currentTimeMillis()-start, events);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void visitChildren(Node node, Map<String, Long> tempCachedMap) throws Exception{
|
||||
NodeIterator nodeIt = node.getNodes();
|
||||
while(nodeIt.hasNext()) {
|
||||
Node child = nodeIt.nextNode();
|
||||
Item item = node2Item.getItem(child, Excludes.ALL);
|
||||
if (item==null || item.isHidden()) continue;
|
||||
if (item instanceof FolderItem)
|
||||
visitChildren(child,tempCachedMap);
|
||||
else if(item instanceof AbstractFileItem)
|
||||
insertItemInTheRightPlace(item,tempCachedMap);
|
||||
}
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public void onEvent(EventIterator events) {
|
||||
logger.trace("on event called");
|
||||
while (events.hasNext()) {
|
||||
Event event = events.nextEvent();
|
||||
try {
|
||||
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
|
||||
} catch (RepositoryException e) {
|
||||
logger.error("error reading event",e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package org.gcube.data.access.storagehub.services.admin;
|
||||
|
||||
import static org.gcube.data.access.storagehub.Roles.INFRASTRUCTURE_MANAGER_ROLE;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.jcr.Node;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.apache.cxf.io.ReaderInputStream;
|
||||
import org.apache.jackrabbit.api.JackrabbitSession;
|
||||
import org.gcube.common.authorization.control.annotations.AuthorizationControl;
|
||||
import org.gcube.common.authorization.library.AuthorizedTasks;
|
||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||
import org.gcube.common.storagehub.model.Paths;
|
||||
import org.gcube.data.access.storagehub.PathUtil;
|
||||
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
|
||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||
import org.gcube.data.access.storagehub.exception.MyAuthException;
|
||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.ItemHandler;
|
||||
import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationParameters;
|
||||
import org.gcube.data.access.storagehub.handlers.items.builders.ItemsParameterBuilder;
|
||||
import org.gcube.data.access.storagehub.scripting.AbstractScript;
|
||||
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
|
||||
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
|
||||
|
||||
@Path("admin/script")
|
||||
@RequestHeaders({
|
||||
@RequestHeader( name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
|
||||
})
|
||||
public class ScriptManager {
|
||||
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(ScriptManager.class);
|
||||
|
||||
private RepositoryInitializer repository = StorageHubAppllicationManager.repository;
|
||||
|
||||
@Inject
|
||||
AccountingHandler accountingHandler;
|
||||
|
||||
@Context
|
||||
ServletContext context;
|
||||
|
||||
@Inject
|
||||
ScriptUtil scriptUtil;
|
||||
|
||||
@Inject
|
||||
ItemHandler itemHandler;
|
||||
|
||||
@Inject
|
||||
PathUtil pathUtil;
|
||||
|
||||
@POST
|
||||
@Path("execute")
|
||||
@AuthorizationControl(allowedRoles = {INFRASTRUCTURE_MANAGER_ROLE},exception=MyAuthException.class)
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public String run( @FormDataParam("name") String name,
|
||||
@FormDataParam("asynch") Boolean asynch,
|
||||
@FormDataParam("destinationFolderId") String destinationFolderId,
|
||||
@FormDataParam("file") InputStream stream,
|
||||
@FormDataParam("file") FormDataContentDisposition fileDetail) {
|
||||
try {
|
||||
ScriptClassLoader scriptClassLoader = new ScriptClassLoader(Thread.currentThread().getContextClassLoader());
|
||||
Class<?> scriptClass = uploadClass(stream, scriptClassLoader, fileDetail.getFileName().replace(".class", ""));
|
||||
return run(scriptClass, name, destinationFolderId, asynch!=null? asynch : false);
|
||||
}catch(Throwable e) {
|
||||
log.error("error executing script {}", name,e);
|
||||
throw new WebApplicationException("error loading class",e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Class<?> uploadClass(InputStream stream, ScriptClassLoader classLoader, String name) throws Throwable {
|
||||
try(ByteArrayOutputStream buffer = new ByteArrayOutputStream()){
|
||||
int nRead;
|
||||
byte[] data = new byte[1024];
|
||||
while ((nRead = stream.read(data, 0, data.length)) != -1)
|
||||
buffer.write(data, 0, nRead);
|
||||
|
||||
buffer.flush();
|
||||
byte[] byteArray = buffer.toByteArray();
|
||||
return classLoader.findClass(name, byteArray);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String run(Class<?> clazz, String name, String destinationFolderId, boolean asynch) throws Throwable {
|
||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||
log.info("script {} called by {}", clazz.getSimpleName(), login);
|
||||
JackrabbitSession ses = null;
|
||||
|
||||
try {
|
||||
ses = (JackrabbitSession) repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||
|
||||
String parentId = destinationFolderId!=null ? destinationFolderId : ses.getNode(pathUtil.getWorkspacePath(login).toPath()).getIdentifier();
|
||||
Node parentNode = ses.getNodeByIdentifier(parentId);
|
||||
String parentPath = parentNode.getPath();
|
||||
|
||||
if (AbstractScript.class.isAssignableFrom(clazz)) {
|
||||
AbstractScript scriptInstance = (AbstractScript) clazz.newInstance();
|
||||
|
||||
RealRun realRun = new RealRun(ses, scriptInstance, login, parentId, name);
|
||||
if (asynch) {
|
||||
new Thread(AuthorizedTasks.bind(realRun)).start();
|
||||
}else realRun.run();
|
||||
|
||||
} else throw new Exception("class "+clazz.getSimpleName()+" not implements AbstractScript");
|
||||
|
||||
return Paths.append(Paths.getPath(parentPath), name).toPath();
|
||||
|
||||
}catch (Throwable e) {
|
||||
if (ses !=null && ses.isLive())
|
||||
ses.logout();
|
||||
throw e;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class RealRun implements Runnable{
|
||||
|
||||
private JackrabbitSession ses;
|
||||
AbstractScript instance;
|
||||
String login;
|
||||
String parentId;
|
||||
String name;
|
||||
|
||||
public RealRun(JackrabbitSession ses, AbstractScript instance, String login, String parentId, String name) {
|
||||
super();
|
||||
this.ses = ses;
|
||||
this.instance = instance;
|
||||
this.login = login;
|
||||
this.parentId = parentId;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
String result ="";
|
||||
try {
|
||||
result = instance.run(ses, null, scriptUtil);
|
||||
log.info("result is {}",result);
|
||||
}catch(Throwable t) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw, true);
|
||||
t.printStackTrace(pw);
|
||||
result+= "\n"+sw.toString();
|
||||
}
|
||||
|
||||
try( InputStream stream = new ReaderInputStream(new StringReader(result))){
|
||||
ItemsParameterBuilder<FileCreationParameters> builder = FileCreationParameters.builder().name(name).description("result of script execution "+name)
|
||||
.stream(stream).on(parentId).with(ses).author(login);
|
||||
itemHandler.create(builder.build());
|
||||
} catch (Throwable e) {
|
||||
log.error("error saving script result {} in the Workspace",name, e);
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (ses!=null)
|
||||
ses.logout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ScriptClassLoader extends ClassLoader{
|
||||
|
||||
public ScriptClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public Class<?> findClass(String name, byte[] b) {
|
||||
return defineClass(name, b, 0, b.length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.gcube.data.access.storagehub.services.admin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.data.access.storagehub.Utils;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.scripting.ScriptUtil;
|
||||
|
||||
@Singleton
|
||||
public class ScriptUtilImpl implements ScriptUtil {
|
||||
|
||||
@Inject Node2ItemConverter node2Item;
|
||||
|
||||
@Override
|
||||
public List<Item> getChildren(Predicate<Node> checker, Node parent, List<String> excludes, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError {
|
||||
return Utils.getItemList(checker, parent, excludes, null, showHidden, nodeTypeToInclude);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError {
|
||||
return node2Item.getItem(node, excludes);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package org.gcube.data.access.storagehub.services.delegates;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.jcr.Node;
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
import javax.jcr.security.AccessControlEntry;
|
||||
import javax.jcr.security.AccessControlManager;
|
||||
import javax.jcr.security.Privilege;
|
||||
|
||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||
import org.gcube.common.storagehub.model.acls.ACL;
|
||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
|
||||
import org.gcube.data.access.storagehub.services.interfaces.ACLManagerInterface;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public class ACLManagerDelegate implements ACLManagerInterface {
|
||||
|
||||
@Inject
|
||||
Node2ItemConverter node2Item;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ACLManagerDelegate.class);
|
||||
|
||||
@Override
|
||||
public List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError {
|
||||
List<ACL> acls = new ArrayList<>();
|
||||
if (!item.isShared()) return acls;
|
||||
|
||||
Node toRetrieve = (Node) item.getRelatedNode();
|
||||
if (!(item instanceof SharedFolder))
|
||||
toRetrieve = retrieveSharedFolderParent(toRetrieve, session);
|
||||
|
||||
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, toRetrieve.getPath());
|
||||
for (AccessControlEntry aclEntry : accessControlList.getAccessControlEntries()) {
|
||||
ACL acl = new ACL();
|
||||
acl.setPricipal(aclEntry.getPrincipal().getName());
|
||||
List<AccessType> types = new ArrayList<>();
|
||||
for (Privilege priv : aclEntry.getPrivileges())
|
||||
try {
|
||||
types.add(AccessType.fromValue(priv.getName()));
|
||||
}catch (Exception e) {
|
||||
log.warn(priv.getName()+" cannot be mapped to AccessTypes",e);
|
||||
}
|
||||
acl.setAccessTypes(types);
|
||||
acls.add(acl);
|
||||
}
|
||||
return acls;
|
||||
}
|
||||
|
||||
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
|
||||
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
|
||||
else
|
||||
return retrieveSharedFolderParent(node.getParent(), session);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException {
|
||||
|
||||
AccessControlManager acm = session.getAccessControlManager();
|
||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
||||
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
|
||||
_remove(acls, principal);
|
||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
||||
acls.addAccessControlEntry(principal, userPrivileges);
|
||||
acm.setPolicy(folder.getPath(), acls);
|
||||
session.save();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String targetUser, SharedFolder folder, Session session) throws RepositoryException {
|
||||
AccessControlManager acm = session.getAccessControlManager();
|
||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, folder.getPath());
|
||||
|
||||
Principal principal = AccessControlUtils.getPrincipal(session, targetUser);
|
||||
_remove(acls, principal);
|
||||
acm.setPolicy(folder.getPath(), acls);
|
||||
}
|
||||
|
||||
|
||||
private void _remove(JackrabbitAccessControlList acls, Principal principal) throws RepositoryException {
|
||||
AccessControlEntry aceToDelete = null;
|
||||
for (AccessControlEntry ace : acls.getAccessControlEntries())
|
||||
if (ace.getPrincipal().equals(principal)) {
|
||||
aceToDelete = ace;
|
||||
break;
|
||||
}
|
||||
|
||||
if (aceToDelete!= null)
|
||||
acls.removeAccessControlEntry(aceToDelete);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package org.gcube.data.access.storagehub.services.interfaces;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.jcr.RepositoryException;
|
||||
import javax.jcr.Session;
|
||||
|
||||
import org.gcube.common.storagehub.model.acls.ACL;
|
||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||
import org.gcube.common.storagehub.model.items.Item;
|
||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||
|
||||
public interface ACLManagerInterface {
|
||||
|
||||
/**
|
||||
* returns the AccessType for all the users in a shared folder
|
||||
*
|
||||
* @exception {@link RepositoryException} when a generic jcr error occurs
|
||||
* @exception {@link UserNotAuthorizedException} when the caller is not authorized to access to the shared folder
|
||||
*/
|
||||
List<ACL> get(Item item, Session session) throws RepositoryException, BackendGenericError;
|
||||
|
||||
/**
|
||||
* Set a new AccessType for a user in a shared folder or VRE folder
|
||||
*
|
||||
*
|
||||
* @param String user
|
||||
* @param accessType accessType
|
||||
*
|
||||
* @exception {@link RepositoryException} when a generic jcr error occurs
|
||||
* @exception {@link UserNotAuthorizedException} when the caller is not ADMINISTRATOR of the shared folder
|
||||
* @exception {@link InvalidCallParameters} when the folder is not shared with the specified user
|
||||
* @exception {@link InvalidItemException} when the folder is not share
|
||||
*/
|
||||
void update(String targetUser, SharedFolder folder, AccessType accessType, Session session) throws RepositoryException, StorageHubException;
|
||||
|
||||
void delete(String targetUser, SharedFolder folder, Session session)
|
||||
throws RepositoryException, StorageHubException;
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
|
||||
|
||||
@Singleton
|
||||
public class GCubeFolderManagerConnector implements FolderManagerConnector {
|
||||
|
||||
@Override
|
||||
public FolderManager connect(FolderItem item, Map<String, Object> parameters) throws PluginInitializationException {
|
||||
return new GcubeFolderManager();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package org.gcube.data.access.storagehub.storage.backend.impl;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||
import org.gcube.common.storagehub.model.plugins.FolderManager;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||
|
||||
@Singleton
|
||||
public class GcubeFolderManager implements FolderManager {
|
||||
|
||||
@Override
|
||||
public StorageBackend getStorageBackend() {
|
||||
return new GCubeStorageBackend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean manageVersion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatedFolder(FolderItem folder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeletingFolder(FolderItem folder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovedFolder(FolderItem movedFolder) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCopiedFolder(FolderItem copiedFolder) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public FolderItem getRootFolder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package org.gcube.data.access.storagehub.types;
|
||||
|
||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
||||
import org.gcube.common.storagehub.model.storages.StorageBackend;
|
||||
|
||||
public class ContentPair {
|
||||
|
||||
private Content content;
|
||||
private StorageBackend storageBackend;
|
||||
public ContentPair(Content content, StorageBackend storageBackend) {
|
||||
super();
|
||||
this.content = content;
|
||||
this.storageBackend = storageBackend;
|
||||
}
|
||||
public Content getContent() {
|
||||
return content;
|
||||
}
|
||||
public StorageBackend getStorageBackend() {
|
||||
return storageBackend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((content.getStorageId() == null) ? 0 : content.getStorageId().hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ContentPair other = (ContentPair) obj;
|
||||
if (content.getStorageId() == null) {
|
||||
if (other.content.getStorageId() != null)
|
||||
return false;
|
||||
} else if (!content.getStorageId().equals(other.content.getStorageId()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.gcube.data.access.storagehub.types;
|
||||
|
||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
||||
import org.gcube.common.storagehub.model.messages.Message;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@RootNode("nthl:itemSentRequestSH")
|
||||
public class MessageSharable extends Message {
|
||||
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
|
||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
|
||||
bean-discovery-mode="all">
|
||||
</beans>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@
|
||||
<application mode='online'>
|
||||
<name>StorageHub</name>
|
||||
<group>DataAccess</group>
|
||||
<version>1.4.2</version>
|
||||
<description>Storage Hub webapp</description>
|
||||
<local-persistence location='target' />
|
||||
<exclude>/workspace/api-docs/*</exclude>
|
||||
</application>
|
@ -0,0 +1,26 @@
|
||||
.d4science_intro {
|
||||
top: 0;
|
||||
z-index: 2000;
|
||||
position: fixed;
|
||||
display: block ruby;
|
||||
padding: 10px;
|
||||
background: white;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.navbar-fixed-top {
|
||||
top: 100px !important;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
top: 160px !important;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-bottom: 40px !important;
|
||||
}
|
||||
|
||||
.main {
|
||||
top: 90px;
|
||||
}
|
Loading…
Reference in New Issue