commit for release 4.13
git-svn-id: https://svn.d4science-ii.research-infrastructures.eu/gcube/branches/data-access/storagehub-webapp/1.0@173824 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
6185b1563b
commit
70581080f4
28
pom.xml
28
pom.xml
|
@ -49,8 +49,8 @@
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
<artifactId>common-smartgears</artifactId>
|
<artifactId>common-smartgears</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -86,14 +86,14 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>gov.nih.imagej</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>imagej</artifactId>
|
<artifactId>slf4j-api</artifactId>
|
||||||
<version>1.47</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.gcube.common</groupId>
|
||||||
<artifactId>slf4j-api</artifactId>
|
<artifactId>gxRest</artifactId>
|
||||||
|
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- JCR dependencies -->
|
<!-- JCR dependencies -->
|
||||||
|
@ -214,9 +214,21 @@
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>16.0</version>
|
<version>16.0</version>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-compress</artifactId>
|
||||||
|
<version>1.17</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.tukaani</groupId>
|
||||||
|
<artifactId>xz</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
|
||||||
<artifactId>jersey-test-framework-provider-simple</artifactId>
|
<artifactId>jersey-test-framework-provider-simple</artifactId>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package org.gcube.data.access.storagehub;
|
package org.gcube.data.access.storagehub;
|
||||||
|
|
||||||
import static org.gcube.common.storagehub.model.NodeConstants.*;
|
import javax.inject.Inject;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.security.AccessControlEntry;
|
import javax.jcr.security.AccessControlEntry;
|
||||||
import javax.jcr.security.Privilege;
|
import javax.jcr.security.Privilege;
|
||||||
|
@ -12,70 +11,124 @@ import javax.jcr.security.Privilege;
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AuthorizationChecker {
|
public class AuthorizationChecker {
|
||||||
|
|
||||||
public void checkReadAuthorizationControl(Session session, String id) throws Exception{
|
@Inject
|
||||||
|
Node2ItemConverter node2Item;
|
||||||
|
|
||||||
|
public void checkReadAuthorizationControl(Session session, String id) throws UserNotAuthorizedException , BackendGenericError, RepositoryException{
|
||||||
Node node = session.getNodeByIdentifier(id);
|
Node node = session.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item item = ItemHandler.getItem(node, Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id+": it's not a valid StorageHub node");
|
||||||
|
|
||||||
|
if (item.isPublicItem()) return;
|
||||||
|
|
||||||
if (item.isShared()) {
|
if (item.isShared()) {
|
||||||
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
|
SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
|
||||||
if (!parentShared.getUsers().getValues().containsKey(AuthorizationProvider.instance.get().getClient().getId()))
|
if (!parentShared.getUsers().getValues().containsKey(login))
|
||||||
throw new IllegalAccessException("Insufficent Provileges to read node with id "+id);
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
|
||||||
} else if (!item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
|
} else if (!item.getOwner().equals(login))
|
||||||
throw new IllegalAccessException("Insufficent Provileges to read node with id "+id);
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SharedFolder retrieveSharedFolderParent(Item item, Session session) throws Exception{
|
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
|
||||||
if (item instanceof SharedFolder) return (SharedFolder)item;
|
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
|
||||||
else
|
else
|
||||||
return retrieveSharedFolderParent(ItemHandler.getItem(session.getNodeByIdentifier(item.getParentId()), Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME)), session);
|
return retrieveSharedFolderParent(node.getParent(), session);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkWriteAuthorizationControl(Session session, String id, boolean isNewItem) throws Exception {
|
public void checkWriteAuthorizationControl(Session session, String id, boolean isNewItem) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
||||||
//in case of newItem the id is the parent otherwise the old node to replace
|
//in case of newItem the id is the parent otherwise the old node to replace
|
||||||
Node node = session.getNodeByIdentifier(id);
|
Node node = session.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item item = ItemHandler.getItem(node, Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME, METADATA_NAME));
|
Item item = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's not a valid StorageHub node");
|
||||||
|
|
||||||
|
if (Constants.PROTECTED_FOLDER.contains(item.getName()) || Constants.PROTECTED_FOLDER.contains(item.getTitle()))
|
||||||
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id+": it's a protected folder");
|
||||||
|
|
||||||
if (item.isShared()) {
|
if (item.isShared()) {
|
||||||
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
|
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||||
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentShared.getPath());
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||||
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||||
//put it in a different method
|
//put it in a different method
|
||||||
|
SharedFolder parentShared = node2Item.getItem(parentSharedNode, Excludes.EXCLUDE_ACCOUNTING);
|
||||||
for (AccessControlEntry entry: entries) {
|
for (AccessControlEntry entry: entries) {
|
||||||
if (entry.getPrincipal().getName().equals(AuthorizationProvider.instance.get().getClient().getId()) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
|
if (entry.getPrincipal().getName().equals(login) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
|
||||||
for (Privilege privilege : entry.getPrivileges()){
|
for (Privilege privilege : entry.getPrivileges()){
|
||||||
AccessType access = AccessType.fromValue(privilege.getName());
|
AccessType access = AccessType.fromValue(privilege.getName());
|
||||||
if (isNewItem && access!=AccessType.READ_ONLY)
|
if (isNewItem && access!=AccessType.READ_ONLY)
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
if (!isNewItem &&
|
if (!isNewItem &&
|
||||||
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))))
|
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(login))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
if(item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
|
if(item.getOwner().equals(login))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
|
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to write into node with id "+id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkAdministratorControl(Session session, SharedFolder item) throws UserNotAuthorizedException, BackendGenericError, RepositoryException {
|
||||||
|
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
if (item==null) throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+item.getId()+": it's not a valid StorageHub node");
|
||||||
|
|
||||||
|
Node node = session.getNodeByIdentifier(item.getId());
|
||||||
|
|
||||||
|
if (item.isShared()) {
|
||||||
|
Node parentSharedNode = retrieveSharedFolderParent(node, session);
|
||||||
|
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentSharedNode.getPath());
|
||||||
|
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
|
||||||
|
//put it in a different method
|
||||||
|
|
||||||
|
SharedFolder parentShared = node2Item.getItem(parentSharedNode, Excludes.EXCLUDE_ACCOUNTING);
|
||||||
|
for (AccessControlEntry entry: entries) {
|
||||||
|
if (entry.getPrincipal().getName().equals(login) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
|
||||||
|
for (Privilege privilege : entry.getPrivileges()){
|
||||||
|
AccessType access = AccessType.fromValue(privilege.getName());
|
||||||
|
if (access==AccessType.ADMINISTRATOR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UserNotAuthorizedException("The user "+login+" is not an administrator of node with id "+item.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
private String retrieveOwner(Node node) {
|
private String retrieveOwner(Node node) {
|
||||||
Node nodeOwner;
|
Node nodeOwner;
|
||||||
|
|
|
@ -19,4 +19,6 @@ public class Constants {
|
||||||
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
public static final String ADMIN_PARAM_PWD ="admin-pwd";
|
||||||
|
|
||||||
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
|
||||||
|
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.gcube.data.access.storagehub;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class ConstraintChecker {
|
||||||
|
|
||||||
|
public boolean isValidName(String name){
|
||||||
|
//^ < > ? $ / \ ' "
|
||||||
|
Pattern p = Pattern.compile("[^a-z0-9 _/-/?/$<>']", Pattern.CASE_INSENSITIVE);
|
||||||
|
Matcher m = p.matcher(name);
|
||||||
|
boolean b = m.find();
|
||||||
|
return !b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,34 +36,35 @@ public class MultipleOutputStream {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startWriting() throws Exception{
|
public void startWriting() throws IOException{
|
||||||
try(BufferedInputStream bis = new BufferedInputStream(is)){
|
|
||||||
byte[] buf = new byte[65536];
|
|
||||||
int read=-1;
|
|
||||||
int writeTot = 0;
|
|
||||||
while ((read =bis.read(buf))!=-1){
|
|
||||||
for (int i=0; i< pipedInStreams.length; i++) {
|
|
||||||
if (!pipedInStreams[i].isClosed()) {
|
|
||||||
pipedOutStreams[i].write(buf, 0, read);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
writeTot+= read;
|
byte[] buf = new byte[1024*64];
|
||||||
if (allOutStreamClosed())
|
int read=-1;
|
||||||
break;
|
int writeTot = 0;
|
||||||
|
while ((read =bis.read(buf))!=-1){
|
||||||
}
|
for (int i=0; i< pipedInStreams.length; i++) {
|
||||||
|
if (!pipedInStreams[i].isClosed()) {
|
||||||
for (int i=0; i< pipedOutStreams.length; i++) {
|
pipedOutStreams[i].write(buf, 0, read);
|
||||||
if (!pipedOutStreams[i].isClosed()) {
|
|
||||||
logger.debug("closing outputstream {}",i);
|
|
||||||
pipedOutStreams[i].close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("total written "+writeTot);
|
|
||||||
|
writeTot+= read;
|
||||||
|
if (allOutStreamClosed())
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i=0; i< pipedOutStreams.length; i++) {
|
||||||
|
if (!pipedOutStreams[i].isClosed()) {
|
||||||
|
logger.debug("closing outputstream {}",i);
|
||||||
|
pipedOutStreams[i].close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("total written {} ",writeTot);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,46 @@
|
||||||
package org.gcube.data.access.storagehub;
|
package org.gcube.data.access.storagehub;
|
||||||
|
|
||||||
import static org.gcube.common.storagehub.model.NodeConstants.ACCOUNTING_NAME;
|
|
||||||
import static org.gcube.common.storagehub.model.NodeConstants.CONTENT_NAME;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Calendar;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
|
import javax.jcr.PathNotFoundException;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.version.Version;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.apache.jackrabbit.util.Text;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.contentmanager.storageclient.wrapper.AccessType;
|
import org.gcube.contentmanager.storageclient.wrapper.AccessType;
|
||||||
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
|
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
|
||||||
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -62,32 +71,24 @@ public class Utils {
|
||||||
return digest;
|
return digest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getItemCount(Node parent, boolean showHidden) throws Exception{
|
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
|
||||||
NodeIterator iterator = parent.getNodes();
|
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
|
||||||
long count=0;
|
|
||||||
while (iterator.hasNext()){
|
|
||||||
Node current = iterator.nextNode();
|
|
||||||
|
|
||||||
if (isToExclude(current, showHidden))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden) throws Exception{
|
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
||||||
|
|
||||||
List<T> returnList = new ArrayList<T>();
|
List<T> returnList = new ArrayList<T>();
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
NodeIterator iterator = parent.getNodes();
|
NodeIterator iterator = parent.getNodes();
|
||||||
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
|
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
|
||||||
|
logger.trace("nodeType is {}",nodeTypeToInclude);
|
||||||
int count =0;
|
int count =0;
|
||||||
logger.trace("selected range is {}", range);
|
logger.trace("selected range is {}", range);
|
||||||
|
Node2ItemConverter node2Item= new Node2ItemConverter();
|
||||||
while (iterator.hasNext()){
|
while (iterator.hasNext()){
|
||||||
Node current = iterator.nextNode();
|
Node current = iterator.nextNode();
|
||||||
|
|
||||||
|
@ -95,18 +96,20 @@ public class Utils {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
|
if (range==null || (count>=range.getStart() && returnList.size()<range.getLimit())) {
|
||||||
T item = ItemHandler.getItem(current, excludes);
|
T item = node2Item.getFilteredItem(current, excludes, nodeTypeToInclude);
|
||||||
|
if (item==null) continue;
|
||||||
returnList.add(item);
|
returnList.add(item);
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
}
|
}
|
||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isToExclude(Node node, boolean showHidden) throws Exception{
|
private static boolean isToExclude(Node node, boolean showHidden) throws RepositoryException{
|
||||||
return ((node.getName().startsWith("rep:") || (node.getName().startsWith("hl:"))) ||
|
return ((node.getName().startsWith("rep:") || (node.getName().startsWith("hl:"))) ||
|
||||||
(!showHidden && node.hasProperty(NodeProperty.HIDDEN.toString()) && node.getProperty(NodeProperty.HIDDEN.toString()).getBoolean()) ||
|
(!showHidden && node.hasProperty(NodeProperty.HIDDEN.toString()) && node.getProperty(NodeProperty.HIDDEN.toString()).getBoolean()) ||
|
||||||
(node.getPrimaryNodeType().getName().equals(FOLDERS_TYPE) && Constants.FOLDERS_TO_EXLUDE.contains(node.getName())));
|
(node.getPrimaryNodeType().getName().equals(FOLDERS_TYPE) && Constants.FOLDERS_TO_EXLUDE.contains(node.getName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static org.gcube.common.storagehub.model.Path getHomePath(){
|
public static org.gcube.common.storagehub.model.Path getHomePath(){
|
||||||
|
@ -122,15 +125,16 @@ public class Utils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Deque<Item> getAllNodesForZip(FolderItem directory, Session session, AccountingHandler accountingHandler) throws Exception{
|
public static Deque<Item> getAllNodesForZip(FolderItem directory, Session session, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||||
Deque<Item> queue = new LinkedList<Item>();
|
Deque<Item> queue = new LinkedList<Item>();
|
||||||
Node currentNode = session.getNodeByIdentifier(directory.getId());
|
Node currentNode = session.getNodeByIdentifier(directory.getId());
|
||||||
queue.push(directory);
|
queue.push(directory);
|
||||||
Deque<Item> tempQueue = new LinkedList<Item>();
|
Deque<Item> tempQueue = new LinkedList<Item>();
|
||||||
logger.debug("adding directory {}",directory.getPath());
|
logger.debug("adding directory {}",currentNode.getPath());
|
||||||
for (Item item : Utils.getItemList(currentNode,null, null, false)){
|
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
|
||||||
|
if (excludes.contains(item.getId())) continue;
|
||||||
if (item instanceof FolderItem)
|
if (item instanceof FolderItem)
|
||||||
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler));
|
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler, excludes));
|
||||||
else if (item instanceof AbstractFileItem){
|
else if (item instanceof AbstractFileItem){
|
||||||
logger.debug("adding file {}",item.getPath());
|
logger.debug("adding file {}",item.getPath());
|
||||||
AbstractFileItem fileItem = (AbstractFileItem) item;
|
AbstractFileItem fileItem = (AbstractFileItem) item;
|
||||||
|
@ -150,31 +154,39 @@ public class Utils {
|
||||||
Item item = queue.pop();
|
Item item = queue.pop();
|
||||||
if (item instanceof FolderItem) {
|
if (item instanceof FolderItem) {
|
||||||
actualPath = Paths.getPath(item.getPath());
|
actualPath = Paths.getPath(item.getPath());
|
||||||
logger.trace("actualPath is {}",actualPath.toPath());
|
logger.debug("actualPath is {}",actualPath.toPath());
|
||||||
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
|
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
|
||||||
logger.trace("writing dir {}",name);
|
logger.debug("writing dir {}",name);
|
||||||
zos.putNextEntry(new ZipEntry(name));
|
if (name.isEmpty()) continue;
|
||||||
zos.closeEntry();
|
try {
|
||||||
} else if (item instanceof AbstractFileItem){
|
|
||||||
InputStream streamToWrite = Utils.getStorageClient(login).getClient().get().RFileAsInputStream(((AbstractFileItem)item).getContent().getStorageId());
|
|
||||||
if (streamToWrite == null){
|
|
||||||
logger.warn("discarding item {} ",item.getName());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
|
|
||||||
String name = Paths.remove(actualPath, originalPath).toPath()+item.getName().replaceFirst("/", "");
|
|
||||||
logger.trace("writing file {}",name);
|
|
||||||
zos.putNextEntry(new ZipEntry(name));
|
zos.putNextEntry(new ZipEntry(name));
|
||||||
copyStream(is, zos);
|
}finally {
|
||||||
|
|
||||||
}catch (Exception e) {
|
|
||||||
logger.warn("error writing item {}", item.getName(),e);
|
|
||||||
} finally{
|
|
||||||
zos.closeEntry();
|
zos.closeEntry();
|
||||||
}
|
}
|
||||||
|
} else if (item instanceof AbstractFileItem){
|
||||||
|
try {
|
||||||
|
InputStream streamToWrite = Utils.getStorageClient(login).getClient().get().RFileAsInputStream(((AbstractFileItem)item).getContent().getStorageId());
|
||||||
|
if (streamToWrite == null){
|
||||||
|
logger.warn("discarding item {} ",item.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
|
||||||
|
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
|
||||||
|
logger.debug("writing file {}",name);
|
||||||
|
zos.putNextEntry(new ZipEntry(name));
|
||||||
|
copyStream(is, zos);
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.warn("error writing item {}", item.getName(),e);
|
||||||
|
} finally{
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
zos.flush();
|
||||||
|
}catch (Throwable e) {
|
||||||
|
logger.warn("error reading content for item {}", item.getPath(),e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
zos.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyStream(InputStream in, OutputStream out) throws IOException {
|
private static void copyStream(InputStream in, OutputStream out) throws IOException {
|
||||||
|
@ -185,13 +197,126 @@ public class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasSharedChildren(FolderItem item, Session session) throws Exception{
|
|
||||||
Node currentNode = session.getNodeByIdentifier(item.getId());
|
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
|
||||||
for (Item children : Utils.getItemList(currentNode,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME), null, false)){
|
Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||||
if (children instanceof FolderItem)
|
NodeIterator children = node.getNodes();
|
||||||
return (children instanceof SharedFolder) || hasSharedChildren((FolderItem)children, session);
|
|
||||||
|
while (children.hasNext()) {
|
||||||
|
Node child= children.nextNode();
|
||||||
|
if (node2Item.checkNodeType(child, SharedFolder.class)) return true;
|
||||||
|
if (node2Item.checkNodeType(child, FolderItem.class) && hasSharedChildren(child)) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void getAllContentIds(Session ses, Set<String> idsToDelete, Item itemToDelete, VersionHandler versionHandler) throws Exception{
|
||||||
|
if (itemToDelete instanceof AbstractFileItem) {
|
||||||
|
List<Version> versions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(itemToDelete.getId()), ses);
|
||||||
|
|
||||||
|
versions.forEach(v -> {
|
||||||
|
try {
|
||||||
|
String storageId =v.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
|
||||||
|
idsToDelete.add(storageId);
|
||||||
|
logger.info("retrieved StorageId {} for version {}", storageId, v.getName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn("error retreiving sotrageId version for item with id {}",itemToDelete.getId(),e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
idsToDelete.add(((AbstractFileItem) itemToDelete).getContent().getStorageId());
|
||||||
|
}else if (itemToDelete instanceof FolderItem) {
|
||||||
|
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(itemToDelete.getId()), Excludes.GET_ONLY_CONTENT , null, true, null);
|
||||||
|
for (Item item: items)
|
||||||
|
getAllContentIds(ses, idsToDelete, item, versionHandler);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String checkExistanceAndGetUniqueName(Session ses, Node destination, String name) throws BackendGenericError{
|
||||||
|
try {
|
||||||
|
destination.getNode(name);
|
||||||
|
}catch(PathNotFoundException pnf) {
|
||||||
|
return Text.escapeIllegalJcrChars(name);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String filename = FilenameUtils.getBaseName(name);
|
||||||
|
String ext = FilenameUtils.getExtension(name);
|
||||||
|
|
||||||
|
String nameTocheck = ext.isEmpty()? String.format("%s(*)",filename): String.format("%s(*).%s",filename, ext);
|
||||||
|
|
||||||
|
logger.debug("filename is {}, extension is {} , and name to check is {}", filename, ext, nameTocheck);
|
||||||
|
|
||||||
|
NodeIterator ni = destination.getNodes(nameTocheck);
|
||||||
|
int maxval = 0;
|
||||||
|
while (ni.hasNext()) {
|
||||||
|
Node n = ni.nextNode();
|
||||||
|
int actual = Integer.parseInt(n.getName().replaceAll(String.format("%s\\((\\d*)\\).*", filename), "$1"));
|
||||||
|
if (actual>maxval)
|
||||||
|
maxval = actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String newName = ext.isEmpty()? String.format("%s(%d)", filename,maxval+1) : String.format("%s(%d).%s", filename,maxval+1, ext) ;
|
||||||
|
return Text.escapeIllegalJcrChars(newName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Node createFolderInternally(Session ses, Node destinationNode, String name, String description, String login, AccountingHandler accountingHandler) throws BackendGenericError {
|
||||||
|
|
||||||
|
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destinationNode, name);
|
||||||
|
|
||||||
|
FolderItem item = new FolderItem();
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
item.setName(uniqueName);
|
||||||
|
item.setTitle(uniqueName);
|
||||||
|
item.setDescription(description);
|
||||||
|
//item.setCreationTime(now);
|
||||||
|
item.setHidden(false);
|
||||||
|
item.setLastAction(ItemAction.CREATED);
|
||||||
|
item.setLastModificationTime(now);
|
||||||
|
item.setLastModifiedBy(login);
|
||||||
|
item.setOwner(login);
|
||||||
|
item.setPublicItem(false);
|
||||||
|
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
|
Node newNode = new Item2NodeConverter().getNode(ses, destinationNode, item);
|
||||||
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Node createGcubeItemInternally(Session ses, Node destinationNode, String name, String description, String login, GCubeItem gcubeItem, AccountingHandler accountingHandler) throws BackendGenericError {
|
||||||
|
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
gcubeItem.setName(name);
|
||||||
|
gcubeItem.setTitle(name);
|
||||||
|
gcubeItem.setDescription(description);
|
||||||
|
//item.setCreationTime(now);
|
||||||
|
gcubeItem.setHidden(false);
|
||||||
|
gcubeItem.setLastAction(ItemAction.CREATED);
|
||||||
|
gcubeItem.setLastModificationTime(now);
|
||||||
|
gcubeItem.setLastModifiedBy(login);
|
||||||
|
gcubeItem.setOwner(login);
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
|
Node newNode = new Item2NodeConverter().getNode(ses, destinationNode, gcubeItem);
|
||||||
|
//TODO: accounting for GCUBEITEM
|
||||||
|
//accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPropertyOnChangeNode(Node node, String login, ItemAction action) throws RepositoryException {
|
||||||
|
node.setProperty(NodeProperty.LAST_MODIFIED.toString(), Calendar.getInstance());
|
||||||
|
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), login);
|
||||||
|
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ public class AccountingHandler {
|
||||||
private static final String ITEM_TYPE = "hl:itemType";
|
private static final String ITEM_TYPE = "hl:itemType";
|
||||||
private static final String MIME_TYPE = "hl:mimeType";
|
private static final String MIME_TYPE = "hl:mimeType";
|
||||||
private static final String MEMBERS = "hl:members";
|
private static final String MEMBERS = "hl:members";
|
||||||
|
private static final String OLD_ITEM_NAME = "hl:oldItemName";
|
||||||
|
private static final String NEW_ITEM_NAME = "hl:newItemName";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
|
||||||
|
|
||||||
|
@ -112,7 +116,7 @@ public class AccountingHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shareFolder(String title, Set<String> users, Session ses, Node sharedNode, boolean saveHistory ) {
|
public void createShareFolder(String title, Set<String> users, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
@ -131,4 +135,44 @@ public class AccountingHandler {
|
||||||
logger.warn("error trying to retrieve accountign node",e);
|
logger.warn("error trying to retrieve accountign node",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void createUnshareFolder(String title, Session ses, Node sharedNode, boolean saveHistory ) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
sharedNode.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Node accountingNodeParent = sharedNode.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.SHARE.getNodeTypeDefinition());
|
||||||
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
|
accountingNode.setProperty(ITEM_NAME, title);
|
||||||
|
|
||||||
|
if (saveHistory) ses.save();
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.warn("error trying to retrieve accountign node",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createRename(String oldTitle, String newTitle, Node node, Session ses, boolean saveHistory ) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!node.hasNode(NodeProperty.ACCOUNTING.toString())){
|
||||||
|
node.addNode(NodeProperty.ACCOUNTING.toString(), NodeProperty.NT_ACCOUNTING.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Node accountingNodeParent = node.getNode(NodeProperty.ACCOUNTING.toString());
|
||||||
|
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.RENAMING.getNodeTypeDefinition());
|
||||||
|
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
|
||||||
|
accountingNode.setProperty(DATE, Calendar.getInstance());
|
||||||
|
accountingNode.setProperty(OLD_ITEM_NAME, oldTitle);
|
||||||
|
accountingNode.setProperty(NEW_ITEM_NAME, newTitle);
|
||||||
|
|
||||||
|
if (saveHistory) ses.save();
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.warn("error trying to retrieve accountign node",e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,21 @@ public class ClassHandler {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(ClassHandler.class);
|
private static Logger log = LoggerFactory.getLogger(ClassHandler.class);
|
||||||
|
|
||||||
|
private static ClassHandler instance = null;
|
||||||
|
|
||||||
|
public static ClassHandler instance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new ClassHandler();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
private Reflections reflection = new Reflections();
|
private Reflections reflection = new Reflections();
|
||||||
|
|
||||||
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
|
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
|
||||||
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
|
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
|
||||||
|
|
||||||
|
|
||||||
public ClassHandler() {
|
private ClassHandler() {
|
||||||
|
|
||||||
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
|
||||||
for (Class<?> clazz: classesAnnotated ){
|
for (Class<?> clazz: classesAnnotated ){
|
||||||
|
|
|
@ -0,0 +1,291 @@
|
||||||
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.jcr.ItemExistsException;
|
||||||
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.PathNotFoundException;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.Value;
|
||||||
|
|
||||||
|
import org.apache.jackrabbit.util.Text;
|
||||||
|
import org.apache.jackrabbit.value.BinaryValue;
|
||||||
|
import org.apache.jackrabbit.value.BooleanValue;
|
||||||
|
import org.apache.jackrabbit.value.DateValue;
|
||||||
|
import org.apache.jackrabbit.value.LongValue;
|
||||||
|
import org.apache.jackrabbit.value.StringValue;
|
||||||
|
import org.gcube.common.storagehub.model.Metadata;
|
||||||
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.Attribute;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||||
|
import org.gcube.common.storagehub.model.annotations.RootNode;
|
||||||
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class Item2NodeConverter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
|
||||||
|
|
||||||
|
public <T extends Item> Node getNode(Session session, Node parentNode, T item){
|
||||||
|
try {
|
||||||
|
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
|
||||||
|
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);
|
||||||
|
//newNode.setPrimaryType(primaryType);
|
||||||
|
for (Field field : retrieveAllFields(item.getClass())){
|
||||||
|
if (field.isAnnotationPresent(Attribute.class)){
|
||||||
|
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||||
|
if (attribute.isReadOnly()) continue;
|
||||||
|
field.setAccessible(true);
|
||||||
|
try{
|
||||||
|
//Class<?> returnType = field.getType();
|
||||||
|
logger.debug("creating node - added field {}",field.getName());
|
||||||
|
Values values = getObjectValue(field.getType(), field.get(item));
|
||||||
|
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||||
|
else newNode.setProperty(attribute.value(), values.getValue());
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value for attribute "+attribute.value(),e);
|
||||||
|
}
|
||||||
|
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
||||||
|
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
||||||
|
if (nodeAttribute.isReadOnly()) continue;
|
||||||
|
String nodeName = nodeAttribute.value();
|
||||||
|
logger.debug("retrieving field node "+field.getName());
|
||||||
|
field.setAccessible(true);
|
||||||
|
try{
|
||||||
|
Object obj = field.get(item);
|
||||||
|
if (obj!=null)
|
||||||
|
iterateItemNodeAttributeFields(obj, newNode, nodeName);
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value",e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.error("error writing repository",e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{
|
||||||
|
|
||||||
|
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
|
||||||
|
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
if (attributeRootNode==null || attributeRootNode.value().isEmpty())
|
||||||
|
newNode = parentNode.addNode(nodeName);
|
||||||
|
else newNode = parentNode.addNode(nodeName, attributeRootNode.value());
|
||||||
|
}catch(ItemExistsException iee) {
|
||||||
|
newNode = parentNode.getNode(nodeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Field field : retrieveAllFields(object.getClass())){
|
||||||
|
if (field.isAnnotationPresent(Attribute.class)){
|
||||||
|
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||||
|
if (attribute.isReadOnly()) continue;
|
||||||
|
field.setAccessible(true);
|
||||||
|
try{
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
Class returnType = field.getType();
|
||||||
|
Values values = getObjectValue(returnType, field.get(object));
|
||||||
|
if (values.isMulti()) newNode.setProperty(attribute.value(), values.getValues());
|
||||||
|
else newNode.setProperty(attribute.value(), values.getValue());
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value",e);
|
||||||
|
}
|
||||||
|
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
||||||
|
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
||||||
|
field.setAccessible(true);
|
||||||
|
Map<String, Object> mapToset = (Map<String, Object>)field.get(object);
|
||||||
|
for (Entry<String, Object> entry : mapToset.entrySet())
|
||||||
|
try{
|
||||||
|
Values values = getObjectValue(entry.getValue().getClass(), entry.getValue());
|
||||||
|
if (values.isMulti()) newNode.setProperty(entry.getKey(), values.getValues());
|
||||||
|
else newNode.setProperty(entry.getKey(), values.getValue());
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value",e);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (field.isAnnotationPresent(ListNodes.class)){
|
||||||
|
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
||||||
|
field.setAccessible(true);
|
||||||
|
List<Object> toSetList = (List<Object>) field.get(object);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Object obj: toSetList){
|
||||||
|
|
||||||
|
logger.debug("the current node {} has a list",newNode.getName());
|
||||||
|
|
||||||
|
iterateItemNodeAttributeFields(obj,newNode, field.getName()+(i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "rawtypes" })
|
||||||
|
private Values getObjectValue(Class returnType, Object value) throws Exception{
|
||||||
|
|
||||||
|
if (returnType.equals(String.class)) return new Values(new StringValue((String) value));
|
||||||
|
if (returnType.isEnum()) return new Values(new StringValue(((Enum) value).toString()));
|
||||||
|
if (returnType.equals(Calendar.class)) return new Values(new DateValue((Calendar) value));
|
||||||
|
if (returnType.equals(Boolean.class) || returnType.equals(boolean.class)) return new Values(new BooleanValue((Boolean) value));
|
||||||
|
if (returnType.equals(Long.class) || returnType.equals(long.class)) return new Values(new LongValue((Long) value));
|
||||||
|
if (returnType.equals(Integer.class) || returnType.equals(int.class)) return new Values(new LongValue((Long) value));
|
||||||
|
if (returnType.isArray()) {
|
||||||
|
if (returnType.getComponentType().equals(Byte.class)
|
||||||
|
|| returnType.getComponentType().equals(byte.class))
|
||||||
|
return new Values(new BinaryValue((byte[]) value));
|
||||||
|
else {
|
||||||
|
Object[] arrayObj= (Object[])value;
|
||||||
|
Value[] arrayValue = new Value[arrayObj.length];
|
||||||
|
int i=0;
|
||||||
|
for (Object val: arrayObj)
|
||||||
|
arrayValue[i++]=getObjectValue(returnType.getComponentType(), val).getValue();
|
||||||
|
return new Values(arrayValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception(String.format("class %s not recognized",returnType.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Field> retrieveAllFields(Class<?> clazz){
|
||||||
|
|
||||||
|
Set<Field> fields = new HashSet<Field>();
|
||||||
|
Class<?> currentClass = clazz;
|
||||||
|
do{
|
||||||
|
List<Field> fieldsFound = Arrays.asList(currentClass.getDeclaredFields());
|
||||||
|
fields.addAll(fieldsFound);
|
||||||
|
}while ((currentClass =currentClass.getSuperclass())!=null);
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <F extends AbstractFileItem> void replaceContent(Session session, Node node, F item, ItemAction action){
|
||||||
|
try {
|
||||||
|
|
||||||
|
node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value());
|
||||||
|
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
||||||
|
contentNode.setPrimaryType(item.getContent().getClass().getAnnotation(AttributeRootNode.class).value());
|
||||||
|
|
||||||
|
node.setProperty(NodeProperty.LAST_MODIFIED.toString(), item.getLastModificationTime());
|
||||||
|
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), item.getLastModifiedBy());
|
||||||
|
node.setProperty(NodeProperty.LAST_ACTION.toString(), action.name());
|
||||||
|
|
||||||
|
for (Field field : retrieveAllFields(item.getContent().getClass())){
|
||||||
|
if (field.isAnnotationPresent(Attribute.class)){
|
||||||
|
Attribute attribute = field.getAnnotation(Attribute.class);
|
||||||
|
if (attribute.isReadOnly()) continue;
|
||||||
|
field.setAccessible(true);
|
||||||
|
try{
|
||||||
|
//Class<?> returnType = field.getType();
|
||||||
|
Values values = getObjectValue(field.getType(), field.get(item.getContent()));
|
||||||
|
if (values.isMulti()) contentNode.setProperty(attribute.value(), values.getValues() );
|
||||||
|
else contentNode.setProperty(attribute.value(), values.getValue());
|
||||||
|
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value for attribute "+attribute.value(),e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.error("error writing repository",e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public <I extends Item> void updateMetadataNode(Session session, Node node, Map<String, Object> meta, String login){
|
||||||
|
try {
|
||||||
|
|
||||||
|
//TODO: make a method to update item not only metadata, check if the new metadata has an intersection with the old one to remove properties not needed
|
||||||
|
|
||||||
|
Utils.setPropertyOnChangeNode(node, login, ItemAction.UPDATED);
|
||||||
|
|
||||||
|
Node metadataNode;
|
||||||
|
try {
|
||||||
|
metadataNode = node.getNode(NodeProperty.METADATA.toString());
|
||||||
|
}catch (PathNotFoundException e) {
|
||||||
|
metadataNode = node.addNode(NodeProperty.METADATA.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Field field : retrieveAllFields(Metadata.class)){
|
||||||
|
if (field.isAnnotationPresent(MapAttribute.class)){
|
||||||
|
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
||||||
|
field.setAccessible(true);
|
||||||
|
for (Entry<String, Object> entry : meta.entrySet())
|
||||||
|
try{
|
||||||
|
Values values = getObjectValue(entry.getValue().getClass(), entry.getValue());
|
||||||
|
if (values.isMulti()) metadataNode.setProperty(entry.getKey(), values.getValues());
|
||||||
|
else metadataNode.setProperty(entry.getKey(), values.getValue());
|
||||||
|
} catch (Exception e ) {
|
||||||
|
logger.warn("error setting value",e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (RepositoryException e) {
|
||||||
|
logger.error("error writing repository",e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Values {
|
||||||
|
private Value singleValue;
|
||||||
|
private Value[] multivalues;
|
||||||
|
|
||||||
|
boolean multi = false;
|
||||||
|
|
||||||
|
public Values(Value singleValue) {
|
||||||
|
super();
|
||||||
|
this.singleValue = singleValue;
|
||||||
|
this.multivalues = null;
|
||||||
|
multi = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Values(Value[] multivalues) {
|
||||||
|
super();
|
||||||
|
multi = true;
|
||||||
|
this.multivalues = multivalues;
|
||||||
|
this.singleValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMulti() {
|
||||||
|
return multi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value getValue(){
|
||||||
|
if (multi) throw new RuntimeException("must be accessed as multi values");
|
||||||
|
return this.singleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value[] getValues(){
|
||||||
|
if (!multi) throw new RuntimeException("must be accessed as single value");
|
||||||
|
return this.multivalues;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,9 +10,9 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
import javax.jcr.PathNotFoundException;
|
import javax.jcr.PathNotFoundException;
|
||||||
|
@ -20,52 +20,59 @@ import javax.jcr.Property;
|
||||||
import javax.jcr.PropertyIterator;
|
import javax.jcr.PropertyIterator;
|
||||||
import javax.jcr.PropertyType;
|
import javax.jcr.PropertyType;
|
||||||
import javax.jcr.RepositoryException;
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
|
||||||
import javax.jcr.Value;
|
import javax.jcr.Value;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.jackrabbit.util.Text;
|
import org.apache.jackrabbit.util.Text;
|
||||||
import org.apache.jackrabbit.value.BinaryValue;
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.apache.jackrabbit.value.BooleanValue;
|
|
||||||
import org.apache.jackrabbit.value.DateValue;
|
|
||||||
import org.apache.jackrabbit.value.LongValue;
|
|
||||||
import org.apache.jackrabbit.value.StringValue;
|
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
|
||||||
import org.gcube.common.storagehub.model.annotations.Attribute;
|
import org.gcube.common.storagehub.model.annotations.Attribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
|
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
|
||||||
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
import org.gcube.common.storagehub.model.annotations.ListNodes;
|
||||||
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
import org.gcube.common.storagehub.model.annotations.MapAttribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
|
||||||
import org.gcube.common.storagehub.model.annotations.RootNode;
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.Content;
|
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
|
||||||
import org.gcube.common.storagehub.model.types.NodeProperty;
|
|
||||||
import org.reflections.Configuration;
|
import org.reflections.Configuration;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
import org.reflections.util.ConfigurationBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class ItemHandler {
|
@Singleton
|
||||||
|
public class Node2ItemConverter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ItemHandler.class);
|
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
|
||||||
|
|
||||||
private static ClassHandler classHandler = new ClassHandler();
|
|
||||||
|
|
||||||
private static HashMap<Class, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
|
private static HashMap<Class, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
|
||||||
|
|
||||||
public static <T extends Item> T getItem(Node node, List<String> excludes) throws Exception {
|
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Class<T> classToHandle = (Class<T>)classHandler.get(node.getPrimaryNodeType().getName());
|
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||||
|
if (nodeTypeToInclude!=null && !(nodeTypeToInclude.isAssignableFrom(classToHandle))) return null;
|
||||||
|
else return retrieveItem(node, excludes, classToHandle);
|
||||||
|
}
|
||||||
|
|
||||||
T item = classToHandle.newInstance();
|
public <T extends Item> T getItem(Node node, List<String> excludes) throws RepositoryException, BackendGenericError{
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
|
||||||
|
return retrieveItem(node, excludes, classToHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{
|
||||||
|
T item;
|
||||||
|
try {
|
||||||
|
item = classToHandle.newInstance();
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
item.setId(node.getIdentifier());
|
item.setId(node.getIdentifier());
|
||||||
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
|
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
|
||||||
|
|
||||||
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
|
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
|
||||||
|
|
||||||
item.setLocked(node.isLocked());
|
item.setLocked(node.isLocked());
|
||||||
item.setPrimaryType(node.getPrimaryNodeType().getName());
|
item.setPrimaryType(node.getPrimaryNodeType().getName());
|
||||||
Item parent = null ;
|
Item parent = null ;
|
||||||
|
@ -74,7 +81,7 @@ public class ItemHandler {
|
||||||
item.setShared(true);
|
item.setShared(true);
|
||||||
}else {
|
}else {
|
||||||
try {
|
try {
|
||||||
parent = ItemHandler.getItem(node.getParent(), Arrays.asList("hl:accounting","jcr:content"));
|
parent = getItem(node.getParent(), Excludes.ALL);
|
||||||
item.setShared(parent.isShared());
|
item.setShared(parent.isShared());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
item.setShared(false);
|
item.setShared(false);
|
||||||
|
@ -86,7 +93,7 @@ public class ItemHandler {
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
if (parent==null)
|
if (parent==null)
|
||||||
parent = ItemHandler.getItem(node.getParent(), Arrays.asList("hl:accounting","jcr:content"));
|
parent = getItem(node.getParent(), Excludes.ALL);
|
||||||
item.setTrashed(parent.isTrashed());
|
item.setTrashed(parent.isTrashed());
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
item.setTrashed(false);
|
item.setTrashed(false);
|
||||||
|
@ -107,7 +114,7 @@ public class ItemHandler {
|
||||||
try{
|
try{
|
||||||
Class<?> returnType = field.getType();
|
Class<?> returnType = field.getType();
|
||||||
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
|
||||||
|
logger.debug("retrieve item - added field {}",field.getName());
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
|
@ -132,10 +139,11 @@ public class ItemHandler {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
|
||||||
T obj = clazz.newInstance();
|
T obj = clazz.newInstance();
|
||||||
for (Field field : retrieveAllFields(clazz)){
|
for (Field field : retrieveAllFields(clazz)){
|
||||||
if (field.isAnnotationPresent(Attribute.class)){
|
if (field.isAnnotationPresent(Attribute.class)){
|
||||||
|
@ -148,7 +156,7 @@ public class ItemHandler {
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.trace("the current node dosn't contain {} property",attribute.value());
|
logger.trace("the current node dosn't contain {} property",attribute.value());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.warn("error setting value",e);
|
logger.warn("error setting value {}",e.getMessage());
|
||||||
}
|
}
|
||||||
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
||||||
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
|
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
|
||||||
|
@ -165,9 +173,9 @@ public class ItemHandler {
|
||||||
|
|
||||||
mapToset.put(prop.getName(), getPropertyValue(prop));
|
mapToset.put(prop.getName(), getPropertyValue(prop));
|
||||||
}catch(PathNotFoundException e){
|
}catch(PathNotFoundException e){
|
||||||
logger.warn("the property {} is not mapped",prop.getName(),e);
|
logger.warn("the property {} is not mapped",prop.getName());
|
||||||
} catch (Exception e ) {
|
} catch (Exception e ) {
|
||||||
logger.warn("error setting value",e);
|
logger.warn("error setting value {}",e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +240,7 @@ public class ItemHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
private static Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
|
||||||
if (returnType.equals(String.class)) return prop.getString();
|
if (returnType.equals(String.class)) return prop.getString();
|
||||||
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
|
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());
|
||||||
if (returnType.equals(Calendar.class)) return prop.getDate();
|
if (returnType.equals(Calendar.class)) return prop.getDate();
|
||||||
|
@ -241,11 +249,7 @@ public class ItemHandler {
|
||||||
if (returnType.equals(Integer.class) || returnType.equals(int.class)) return prop.getLong();
|
if (returnType.equals(Integer.class) || returnType.equals(int.class)) return prop.getLong();
|
||||||
if (returnType.isArray()) {
|
if (returnType.isArray()) {
|
||||||
if (prop.getType()==PropertyType.BINARY) {
|
if (prop.getType()==PropertyType.BINARY) {
|
||||||
byte[] bytes = new byte[32000];
|
byte[] bytes = IOUtils.toByteArray(prop.getBinary().getStream());
|
||||||
|
|
||||||
try (InputStream stream = prop.getBinary().getStream()){
|
|
||||||
stream.read(bytes);
|
|
||||||
}
|
|
||||||
return bytes;
|
return bytes;
|
||||||
} else {
|
} else {
|
||||||
Object[] ret= getArrayValue(prop);
|
Object[] ret= getArrayValue(prop);
|
||||||
|
@ -255,59 +259,6 @@ public class ItemHandler {
|
||||||
throw new Exception(String.format("class %s not recognized",returnType.getName()));
|
throw new Exception(String.format("class %s not recognized",returnType.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes" })
|
|
||||||
private static Value getObjectValue(Class returnType, Object value) throws Exception{
|
|
||||||
if (returnType.equals(String.class)) return new StringValue((String) value);
|
|
||||||
if (returnType.isEnum()) return new StringValue(((Enum) value).toString());
|
|
||||||
if (returnType.equals(Calendar.class)) return new DateValue((Calendar) value);
|
|
||||||
if (returnType.equals(Boolean.class) || returnType.equals(boolean.class)) return new BooleanValue((Boolean) value);
|
|
||||||
if (returnType.equals(Long.class) || returnType.equals(long.class)) return new LongValue((Long) value);
|
|
||||||
if (returnType.equals(Integer.class) || returnType.equals(int.class)) return new LongValue((Long) value);
|
|
||||||
if (returnType.isArray()) {
|
|
||||||
if (returnType.getComponentType().equals(Byte.class)
|
|
||||||
|| returnType.getComponentType().equals(byte.class))
|
|
||||||
return new BinaryValue((byte[]) value);
|
|
||||||
}
|
|
||||||
throw new Exception(String.format("class %s not recognized",returnType.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Object[] getArrayValue(Property prop) throws Exception{
|
|
||||||
Object[] values = new Object[prop.getValues().length];
|
|
||||||
int i = 0;
|
|
||||||
for (Value value : prop.getValues())
|
|
||||||
values[i++] = getSingleValue(value);
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static Object getPropertyValue(Property prop) throws Exception{
|
|
||||||
if (prop.isMultiple()){
|
|
||||||
Object[] values = new Object[prop.getValues().length];
|
|
||||||
int i = 0;
|
|
||||||
for (Value value : prop.getValues())
|
|
||||||
values[i++] = getSingleValue(value);
|
|
||||||
return values;
|
|
||||||
} else
|
|
||||||
return getSingleValue(prop.getValue());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object getSingleValue(Value value) throws Exception{
|
|
||||||
switch (value.getType()) {
|
|
||||||
case PropertyType.DATE:
|
|
||||||
return value.getDate();
|
|
||||||
case PropertyType.BOOLEAN:
|
|
||||||
return value.getBoolean();
|
|
||||||
case PropertyType.LONG:
|
|
||||||
return value.getDate();
|
|
||||||
default:
|
|
||||||
return value.getString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<Field> retrieveAllFields(Class<?> clazz){
|
private static Set<Field> retrieveAllFields(Class<?> clazz){
|
||||||
|
|
||||||
Set<Field> fields = new HashSet<Field>();
|
Set<Field> fields = new HashSet<Field>();
|
||||||
|
@ -319,123 +270,45 @@ public class ItemHandler {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Item> Node createNodeFromItem(Session session, Node parentNode, T item){
|
private Object getPropertyValue(Property prop) throws Exception{
|
||||||
try {
|
if (prop.isMultiple()){
|
||||||
|
Object[] values = new Object[prop.getValues().length];
|
||||||
//TODO: must understand this place is for name or title
|
int i = 0;
|
||||||
String primaryType= classHandler.getNodeType(item.getClass());
|
for (Value value : prop.getValues())
|
||||||
Node newNode = parentNode.addNode(item.getTitle(), primaryType);
|
values[i++] = getSingleValue(value);
|
||||||
//newNode.setPrimaryType(primaryType);
|
return values;
|
||||||
for (Field field : retrieveAllFields(item.getClass())){
|
} else
|
||||||
if (field.isAnnotationPresent(Attribute.class)){
|
return getSingleValue(prop.getValue());
|
||||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
|
||||||
if (attribute.isReadOnly()) continue;
|
|
||||||
field.setAccessible(true);
|
|
||||||
try{
|
|
||||||
//Class<?> returnType = field.getType();
|
|
||||||
newNode.setProperty(attribute.value(), getObjectValue(field.getType(), field.get(item)));
|
|
||||||
|
|
||||||
} catch (Exception e ) {
|
|
||||||
logger.warn("error setting value for attribute "+attribute.value(),e);
|
|
||||||
}
|
|
||||||
} else if (field.isAnnotationPresent(NodeAttribute.class)){
|
|
||||||
NodeAttribute nodeAttribute = field.getAnnotation(NodeAttribute.class);
|
|
||||||
if (nodeAttribute.isReadOnly()) continue;
|
|
||||||
String nodeName = nodeAttribute.value();
|
|
||||||
logger.debug("retrieving field node "+field.getName());
|
|
||||||
field.setAccessible(true);
|
|
||||||
try{
|
|
||||||
iterateItemNodeAttributeFields(field.get(item), newNode, nodeName);
|
|
||||||
} catch (Exception e ) {
|
|
||||||
logger.warn("error setting value",e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newNode;
|
|
||||||
} catch (RepositoryException e) {
|
|
||||||
logger.error("error writing repository",e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void iterateItemNodeAttributeFields(Object object, Node parentNode, String nodeName) throws Exception{
|
private Object getSingleValue(Value value) throws Exception{
|
||||||
|
switch (value.getType()) {
|
||||||
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
|
case PropertyType.DATE:
|
||||||
Node newNode = parentNode.addNode(nodeName, attributeRootNode.value());
|
return value.getDate();
|
||||||
//newNode.setPrimaryType(attributeRootNode.value());
|
case PropertyType.BOOLEAN:
|
||||||
for (Field field : retrieveAllFields(object.getClass())){
|
return value.getBoolean();
|
||||||
if (field.isAnnotationPresent(Attribute.class)){
|
case PropertyType.LONG:
|
||||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
return value.getDate();
|
||||||
if (attribute.isReadOnly()) continue;
|
default:
|
||||||
field.setAccessible(true);
|
return value.getString();
|
||||||
try{
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
Class returnType = field.getType();
|
|
||||||
newNode.setProperty(attribute.value(), getObjectValue(returnType, field.get(object)));
|
|
||||||
} catch (Exception e ) {
|
|
||||||
logger.warn("error setting value",e);
|
|
||||||
}
|
|
||||||
} else if (field.isAnnotationPresent(MapAttribute.class)){
|
|
||||||
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
|
|
||||||
field.setAccessible(true);
|
|
||||||
Map<String, Object> mapToset = (Map<String, Object>)field.get(object);
|
|
||||||
for (Entry<String, Object> entry : mapToset.entrySet())
|
|
||||||
try{
|
|
||||||
newNode.setProperty(entry.getKey(), getObjectValue(entry.getValue().getClass(), entry.getValue()));
|
|
||||||
} catch (Exception e ) {
|
|
||||||
logger.warn("error setting value",e);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (field.isAnnotationPresent(ListNodes.class)){
|
|
||||||
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), object.getClass().getName(), newNode.getName());
|
|
||||||
field.setAccessible(true);
|
|
||||||
List<Object> toSetList = (List<Object>) field.get(object);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (Object obj: toSetList){
|
|
||||||
|
|
||||||
logger.debug("the current node {} has a list",newNode.getName());
|
|
||||||
|
|
||||||
iterateItemNodeAttributeFields(obj,newNode, field.getName()+(i++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <F extends AbstractFileItem> void replaceContent(Session session, Node node, F item){
|
private Object[] getArrayValue(Property prop) throws Exception{
|
||||||
|
Object[] values = new Object[prop.getValues().length];
|
||||||
|
int i = 0;
|
||||||
|
for (Value value : prop.getValues())
|
||||||
|
values[i++] = getSingleValue(value);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkNodeType(Node node, Class<? extends Item> classToCompare) throws BackendGenericError{
|
||||||
try {
|
try {
|
||||||
|
return (node.isNodeType(ClassHandler.instance().getNodeType(classToCompare)));
|
||||||
node.setPrimaryType(item.getClass().getAnnotation(RootNode.class).value());
|
}catch (Throwable e) {
|
||||||
Node contentNode = node.getNode(NodeConstants.CONTENT_NAME);
|
throw new BackendGenericError(e);
|
||||||
contentNode.setPrimaryType(item.getContent().getClass().getAnnotation(AttributeRootNode.class).value());
|
|
||||||
|
|
||||||
node.setProperty(NodeProperty.LAST_MODIFIED.toString(), item.getLastModificationTime());
|
|
||||||
node.setProperty(NodeProperty.LAST_MODIFIED_BY.toString(), item.getLastModifiedBy());
|
|
||||||
node.setProperty(NodeProperty.LAST_ACTION.toString(), ItemAction.UPDATED.name());
|
|
||||||
|
|
||||||
for (Field field : retrieveAllFields(item.getContent().getClass())){
|
|
||||||
if (field.isAnnotationPresent(Attribute.class)){
|
|
||||||
Attribute attribute = field.getAnnotation(Attribute.class);
|
|
||||||
if (attribute.isReadOnly()) continue;
|
|
||||||
field.setAccessible(true);
|
|
||||||
try{
|
|
||||||
//Class<?> returnType = field.getType();
|
|
||||||
contentNode.setProperty(attribute.value(), getObjectValue(field.getType(), field.get(item.getContent())));
|
|
||||||
|
|
||||||
} catch (Exception e ) {
|
|
||||||
logger.warn("error setting value for attribute "+attribute.value(),e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (RepositoryException e) {
|
|
||||||
logger.error("error writing repository",e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
package org.gcube.data.access.storagehub.handlers;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
|
import javax.jcr.Session;
|
||||||
|
|
||||||
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||||
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class TrashHandler {
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(TrashHandler.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AccountingHandler accountingHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AuthorizationChecker authChecker;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Item2NodeConverter item2Node;
|
||||||
|
|
||||||
|
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException{
|
||||||
|
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
||||||
|
//String parentPath = itemToDelete.getParentPath();
|
||||||
|
try {
|
||||||
|
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
||||||
|
Set<String> contentIdsToDelete = new HashSet<>();
|
||||||
|
|
||||||
|
for (Item trashItem: itemsToDelete) {
|
||||||
|
try {
|
||||||
|
Node trashItemNode = ses.getNodeByIdentifier(trashItem.getId());
|
||||||
|
List<Item> trashChildren = Utils.getItemList(trashItemNode, Excludes.GET_ONLY_CONTENT, null, true, null);
|
||||||
|
for (Item itemContentToRetrieve: trashChildren)
|
||||||
|
Utils.getAllContentIds(ses, contentIdsToDelete, itemContentToRetrieve, versionHandler);
|
||||||
|
trashItemNode.remove();
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.warn("error removing item with id {}",trashItem.getId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.debug("content ids to remove are {}",contentIdsToDelete);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: make it as an authorizableTask
|
||||||
|
String user = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
new Thread() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
for (String id: contentIdsToDelete) {
|
||||||
|
try {
|
||||||
|
IClient client = Utils.getStorageClient(user).getClient();
|
||||||
|
client.remove().RFileById(id);
|
||||||
|
log.debug("file with id {} correctly removed on storage",id);
|
||||||
|
}catch(Throwable t) {
|
||||||
|
log.warn("error removing file on storage with id {}",id, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}.start();;
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(trashFolder.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void moveToTrash(Session ses, Node nodeToDelete, Item item) throws RepositoryException, BackendGenericError{
|
||||||
|
log.debug("moving node {} to trash ",item.getId());
|
||||||
|
final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
||||||
|
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
||||||
|
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
|
||||||
|
|
||||||
|
log.debug("preparing thrash item");
|
||||||
|
|
||||||
|
TrashItem trashItem = new TrashItem();
|
||||||
|
trashItem.setDeletedBy(AuthorizationProvider.instance.get().getClient().getId());
|
||||||
|
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
trashItem.setDeletedTime(now);
|
||||||
|
trashItem.setHidden(false);
|
||||||
|
trashItem.setLastAction(ItemAction.CREATED);
|
||||||
|
trashItem.setDescription("trash item of node " + nodeToDelete.getPath());
|
||||||
|
trashItem.setParentId(trashFolder.getIdentifier());
|
||||||
|
trashItem.setParentPath(trashFolder.getPath());
|
||||||
|
//String pathUUid= UUID.randomUUID().toString();
|
||||||
|
trashItem.setTitle(item.getTitle());
|
||||||
|
trashItem.setName(item.getId());
|
||||||
|
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
|
||||||
|
|
||||||
|
trashItem.setOwner(item.getOwner());
|
||||||
|
trashItem.setLastModificationTime(item.getLastModificationTime());
|
||||||
|
trashItem.setLastModifiedBy(item.getLastModifiedBy());
|
||||||
|
|
||||||
|
trashItem.setLenght(0);
|
||||||
|
|
||||||
|
if (item instanceof FolderItem) {
|
||||||
|
trashItem.setFolder(true);
|
||||||
|
}else if (item instanceof AbstractFileItem ) {
|
||||||
|
AbstractFileItem file = (AbstractFileItem) item;
|
||||||
|
if (file.getContent()!=null) {
|
||||||
|
trashItem.setMimeType(file.getContent().getMimeType());
|
||||||
|
trashItem.setLenght(file.getContent().getSize());
|
||||||
|
}
|
||||||
|
trashItem.setFolder(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("creating node");
|
||||||
|
|
||||||
|
Node newTrashItemNode = item2Node.getNode(ses, trashFolder, trashItem);
|
||||||
|
|
||||||
|
ses.save();
|
||||||
|
log.debug("calling jcr move");
|
||||||
|
ses.getWorkspace().move(nodeToDelete.getPath(), Paths.append(Paths.getPath(newTrashItemNode.getPath()),nodeToDelete.getName()).toPath());
|
||||||
|
String mimetype = null;
|
||||||
|
if (item instanceof AbstractFileItem) {
|
||||||
|
if (((AbstractFileItem)item).getContent()!=null)
|
||||||
|
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
||||||
|
else log.warn("the AbstractFileItem with id {} has no content (check it!!)", item.getId());
|
||||||
|
}
|
||||||
|
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, ses.getNodeByIdentifier(item.getParentId()), true);
|
||||||
|
}catch(Throwable t) {
|
||||||
|
throw new BackendGenericError(t);
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(nodeToDelete.getPath());
|
||||||
|
ses.getWorkspace().getLockManager().unlock(trashFolder.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String restoreItem(Session ses, TrashItem item) throws RepositoryException, BackendGenericError, UserNotAuthorizedException{
|
||||||
|
log.debug("restoring node from trash");
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
//final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
||||||
|
Node originalParent = ses.getNodeByIdentifier(item.getOriginalParentId());
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, originalParent.getIdentifier(), false );
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(originalParent.getPath(), true, true, 0,login);
|
||||||
|
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(item.getId()), Excludes.ALL, null, false, null);
|
||||||
|
if (items.size()!=1) {
|
||||||
|
log.warn("a problem occurred restoring item from trash");
|
||||||
|
throw new BackendGenericError("An error occurred on trash item");
|
||||||
|
}
|
||||||
|
Item itemToMove = items.get(0);
|
||||||
|
String newNodePath = Paths.append(Paths.getPath(originalParent.getPath()), itemToMove.getName()).toPath();
|
||||||
|
ses.move(itemToMove.getPath(), newNodePath);
|
||||||
|
Utils.setPropertyOnChangeNode(ses.getNode(newNodePath), login, ItemAction.MOVED);
|
||||||
|
ses.removeItem(item.getPath());
|
||||||
|
ses.save();
|
||||||
|
return ses.getNode(newNodePath).getIdentifier();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import java.util.concurrent.Future;
|
||||||
import javax.jcr.Repository;
|
import javax.jcr.Repository;
|
||||||
import javax.jcr.SimpleCredentials;
|
import javax.jcr.SimpleCredentials;
|
||||||
|
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -32,12 +33,16 @@ public class VRE {
|
||||||
return vreFolder;
|
return vreFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized List<Item> getRecents() throws Exception{
|
public synchronized List<Item> getRecents() throws BackendGenericError{
|
||||||
logger.trace("getting recents");
|
try {
|
||||||
if (result.isDone()) {
|
logger.trace("getting recents");
|
||||||
result = executor.submit(vreQueryRetriever);
|
if (result.isDone()) {
|
||||||
|
result = executor.submit(vreQueryRetriever);
|
||||||
|
}
|
||||||
|
return result.get();
|
||||||
|
}catch(Exception ee) {
|
||||||
|
throw new BackendGenericError(ee);
|
||||||
}
|
}
|
||||||
return result.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import javax.jcr.observation.Event;
|
||||||
import javax.jcr.observation.EventJournal;
|
import javax.jcr.observation.EventJournal;
|
||||||
import javax.jcr.query.Query;
|
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.NodeConstants;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
|
@ -35,6 +36,8 @@ public class VREQueryRetriever implements Callable<List<Item>> {
|
||||||
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
|
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
|
||||||
long lastTimestamp =0;
|
long lastTimestamp =0;
|
||||||
|
|
||||||
|
private Node2ItemConverter node2Item = new Node2ItemConverter();
|
||||||
|
|
||||||
|
|
||||||
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
|
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
|
||||||
super();
|
super();
|
||||||
|
@ -59,7 +62,7 @@ public class VREQueryRetriever implements Callable<List<Item>> {
|
||||||
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
|
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Node node = it.nextNode();
|
Node node = it.nextNode();
|
||||||
Item item =ItemHandler.getItem(node, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
Item item =node2Item.getItem(node, Excludes.EXCLUDE_ACCOUNTING);
|
||||||
cachedList.add(item);
|
cachedList.add(item);
|
||||||
logger.trace("adding item {} with node {}",item.getTitle(), node.getName());
|
logger.trace("adding item {} with node {}",item.getTitle(), node.getName());
|
||||||
}
|
}
|
||||||
|
@ -101,7 +104,7 @@ public class VREQueryRetriever implements Callable<List<Item>> {
|
||||||
Node nodeAdded = ses.getNode(event.getPath());
|
Node nodeAdded = ses.getNode(event.getPath());
|
||||||
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
|
||||||
logger.trace("node added event received with name {}", nodeAdded.getName());
|
logger.trace("node added event received with name {}", nodeAdded.getName());
|
||||||
Item item = ItemHandler.getItem(nodeAdded, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
Item item = node2Item.getItem(nodeAdded, Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
||||||
insertItemInTheRightPlace(item);
|
insertItemInTheRightPlace(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +117,7 @@ public class VREQueryRetriever implements Callable<List<Item>> {
|
||||||
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
|
||||||
String identifier = property.getParent().getIdentifier();
|
String identifier = property.getParent().getIdentifier();
|
||||||
cachedList.removeIf(i -> i.getId().equals(identifier));
|
cachedList.removeIf(i -> i.getId().equals(identifier));
|
||||||
Item item = ItemHandler.getItem(property.getParent(), Arrays.asList(NodeConstants.ACCOUNTING_NAME));
|
Item item = node2Item.getItem(property.getParent(), Excludes.EXCLUDE_ACCOUNTING);
|
||||||
insertItemInTheRightPlace(item);
|
insertItemInTheRightPlace(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import javax.jcr.version.VersionIterator;
|
||||||
import javax.jcr.version.VersionManager;
|
import javax.jcr.version.VersionManager;
|
||||||
|
|
||||||
import org.apache.jackrabbit.JcrConstants;
|
import org.apache.jackrabbit.JcrConstants;
|
||||||
import org.apache.jackrabbit.core.version.VersionManagerImplBase;
|
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
|
||||||
|
|
||||||
public interface ContentHandler {
|
public interface ContentHandler {
|
||||||
|
|
||||||
void initiliseSpecificContent(InputStream is) throws Exception;
|
void initiliseSpecificContent(InputStream is, String fileName) throws Exception;
|
||||||
|
|
||||||
Content getContent();
|
Content getContent();
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ public class GenericFileHandler implements ContentHandler{
|
||||||
Content content = new Content();
|
Content content = new Content();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initiliseSpecificContent(InputStream is) throws Exception {}
|
public void initiliseSpecificContent(InputStream is, String filename) throws Exception {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Content getContent() {
|
public Content getContent() {
|
||||||
|
|
|
@ -1,56 +1,54 @@
|
||||||
package org.gcube.data.access.storagehub.handlers.content;
|
package org.gcube.data.access.storagehub.handlers.content;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.awt.RenderingHints;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
|
||||||
import org.gcube.common.storagehub.model.items.ImageFile;
|
import org.gcube.common.storagehub.model.items.ImageFile;
|
||||||
import org.gcube.common.storagehub.model.items.nodes.ImageContent;
|
import org.gcube.common.storagehub.model.items.nodes.ImageContent;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.slf4j.Logger;
|
||||||
import ij.ImagePlus;
|
import org.slf4j.LoggerFactory;
|
||||||
import ij.io.FileSaver;
|
|
||||||
import ij.process.ImageProcessor;
|
|
||||||
|
|
||||||
@MimeTypeHandler({"image/gif", "image/jpeg","image/png","image/svg+xml"})
|
@MimeTypeHandler({"image/gif", "image/jpeg","image/png","image/svg+xml"})
|
||||||
public class ImageHandler implements ContentHandler{
|
public class ImageHandler implements ContentHandler{
|
||||||
|
|
||||||
private static final int THUMB_MAX_DIM = 50;
|
private static final int THUMB_MAX_DIM = 300;
|
||||||
|
|
||||||
private ImageContent content = new ImageContent();
|
private ImageContent content = new ImageContent();
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ImageHandler.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initiliseSpecificContent(InputStream is) throws Exception {
|
public void initiliseSpecificContent(InputStream is, String fileName) throws Exception {
|
||||||
BufferedImage buf = ImageIO.read(is);
|
Image image = javax.imageio.ImageIO.read(is);
|
||||||
content.setWidth(Long.valueOf(buf.getWidth()));
|
|
||||||
content.setHeight(Long.valueOf(buf.getHeight()));
|
|
||||||
|
|
||||||
ImagePlus image = new ImagePlus("thumbnail", buf);
|
int width = image.getWidth(null);
|
||||||
|
int height = image.getHeight(null);
|
||||||
|
|
||||||
int thumbSize[] = getThumbnailDimension(buf.getWidth(), buf.getHeight());
|
content.setWidth(Long.valueOf(width));
|
||||||
|
content.setHeight(Long.valueOf(height));
|
||||||
|
|
||||||
try(ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream thumbstream = getThumbnailAsPng(image, thumbSize[0], thumbSize[1])){
|
try {
|
||||||
|
int[] dimension = getThumbnailDimension(width, height);
|
||||||
|
|
||||||
byte[] imgbuf = new byte[1024];
|
byte[] buf = transform(image, fileName, dimension[0], dimension[1]).toByteArray();
|
||||||
int read = -1;
|
|
||||||
while ((read=thumbstream.read(imgbuf))!=-1)
|
|
||||||
baos.write(imgbuf, 0, read);
|
|
||||||
|
|
||||||
content.setThumbnailHeight(Long.valueOf(thumbSize[1]));
|
|
||||||
content.setThumbnailWidth(Long.valueOf(thumbSize[0]));
|
content.setThumbnailHeight(Long.valueOf(dimension[1]));
|
||||||
content.setThumbnailData(Base64.getEncoder().encode(baos.toByteArray()));
|
content.setThumbnailWidth(Long.valueOf(dimension[0]));
|
||||||
} catch (Exception e) {
|
content.setThumbnailData(buf);
|
||||||
// TODO: handle exception
|
}catch(Throwable t) {
|
||||||
|
logger.warn("thumbnail for file {} cannot be created ", fileName,t);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -93,29 +91,6 @@ public class ImageHandler implements ContentHandler{
|
||||||
return dimension;
|
return dimension;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private InputStream getThumbnailAsPng(ImagePlus img, int thumbWidth,
|
|
||||||
int thumbHeight) throws IOException {
|
|
||||||
|
|
||||||
InputStream stream = null;
|
|
||||||
ImageProcessor processor = img.getProcessor();
|
|
||||||
try{
|
|
||||||
Image thumb = processor.resize(thumbWidth, thumbHeight).createImage();
|
|
||||||
thumb = thumb.getScaledInstance(thumbWidth,thumbHeight,Image.SCALE_SMOOTH);
|
|
||||||
|
|
||||||
FileSaver fs = new FileSaver(new ImagePlus("",thumb));
|
|
||||||
File tmpThumbFile = File.createTempFile("THUMB", "TMP");
|
|
||||||
tmpThumbFile.deleteOnExit();
|
|
||||||
|
|
||||||
fs.saveAsPng(tmpThumbFile.getAbsolutePath());
|
|
||||||
stream = new FileInputStream(tmpThumbFile);
|
|
||||||
|
|
||||||
}catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageFile buildItem(String name, String description, String login) {
|
public ImageFile buildItem(String name, String description, String login) {
|
||||||
ImageFile item = new ImageFile();
|
ImageFile item = new ImageFile();
|
||||||
|
@ -133,4 +108,28 @@ public class ImageHandler implements ContentHandler{
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ByteArrayOutputStream transform(Image image,
|
||||||
|
String originalFile, int thumbWidth,
|
||||||
|
int thumbHeight)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
|
||||||
|
|
||||||
|
Graphics2D graphics2D = thumbImage.createGraphics();
|
||||||
|
graphics2D.setBackground(Color.WHITE);
|
||||||
|
graphics2D.setPaint(Color.WHITE);
|
||||||
|
graphics2D.fillRect(0, 0, thumbWidth, thumbHeight);
|
||||||
|
graphics2D.setRenderingHint(
|
||||||
|
RenderingHints.KEY_INTERPOLATION,
|
||||||
|
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
|
||||||
|
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
|
||||||
|
|
||||||
|
String ext = FilenameUtils.getExtension(originalFile);
|
||||||
|
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(thumbImage, ext, os);
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class PdfHandler implements ContentHandler {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initiliseSpecificContent(InputStream is) throws Exception {
|
public void initiliseSpecificContent(InputStream is, String fileName) throws Exception {
|
||||||
PdfReader reader = new PdfReader(is);
|
PdfReader reader = new PdfReader(is);
|
||||||
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
|
||||||
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
content.setVersion(String.valueOf(reader.getPdfVersion()));
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.security.AccessControlEntry;
|
import javax.jcr.security.AccessControlEntry;
|
||||||
import javax.jcr.security.Privilege;
|
import javax.jcr.security.Privilege;
|
||||||
|
@ -17,10 +19,14 @@ import javax.ws.rs.WebApplicationException;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveException;
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.storagehub.model.acls.ACL;
|
import org.gcube.common.storagehub.model.acls.ACL;
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
import org.gcube.common.storagehub.model.types.ACLList;
|
import org.gcube.common.storagehub.model.types.ACLList;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
|
@ -72,15 +78,18 @@ public class ACLManager {
|
||||||
acl.setAccessTypes(types);
|
acl.setAccessTypes(types);
|
||||||
acls.add(acl);
|
acls.add(acl);
|
||||||
}
|
}
|
||||||
return new ACLList(acls);
|
|
||||||
}catch (Exception e) {
|
}catch(RepositoryException re){
|
||||||
log.error("error gettign ACL",e);
|
log.error("jcr error extracting archive", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error creating file item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
return new ACLList(acls);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Calendar;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
|
import javax.jcr.security.AccessControlEntry;
|
||||||
import javax.jcr.security.AccessControlManager;
|
import javax.jcr.security.AccessControlManager;
|
||||||
import javax.jcr.security.Privilege;
|
import javax.jcr.security.Privilege;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
@ -15,25 +19,34 @@ import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
|
||||||
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
|
||||||
import org.gcube.common.storagehub.model.acls.AccessType;
|
import org.gcube.common.storagehub.model.acls.AccessType;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
import org.gcube.common.storagehub.model.types.PrimaryNodeType;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||||
|
@ -64,110 +77,349 @@ public class ItemSharing {
|
||||||
@Inject
|
@Inject
|
||||||
VersionHandler versionHandler;
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{id}/share")
|
@Path("{id}/share")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
|
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
|
||||||
InnerMethodName.instance.set("findChildrenByNamePattern");
|
InnerMethodName.instance.set("shareFolder");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
Item item = ItemHandler.getItem(ses.getNodeByIdentifier(id), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.CONTENT_NAME, NodeConstants.METADATA_NAME));
|
//Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
|
||||||
|
|
||||||
if (! (item instanceof FolderItem) && ((FolderItem) item).isShared() && Utils.hasSharedChildren((FolderItem)item, ses) && item.getOwner().equals(login))
|
|
||||||
throw new Exception("item with id "+id+" cannot be shared");
|
|
||||||
|
|
||||||
if (accessType==null)
|
if (accessType==null)
|
||||||
accessType = AccessType.READ_ONLY;
|
accessType = AccessType.READ_ONLY;
|
||||||
|
|
||||||
if (users.isEmpty())
|
if (users==null || users.isEmpty())
|
||||||
throw new Exception("users is empty");
|
throw new InvalidCallParameters("users is empty");
|
||||||
|
|
||||||
|
Node nodeToShare = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
String sharedFolderName = item.getId();
|
boolean alreadyShared = false;
|
||||||
|
|
||||||
String newNodePath = Constants.SHARED_FOLDER_PATH+"/"+sharedFolderName;
|
|
||||||
|
|
||||||
/*ses.getWorkspace().getLockManager().lock(newNodePath, true, true, 0,login);
|
|
||||||
|
|
||||||
try {
|
|
||||||
*/
|
|
||||||
ses.move(item.getPath(),newNodePath);
|
|
||||||
|
|
||||||
Node sharedFolderNode = ses.getNode(newNodePath);
|
|
||||||
|
|
||||||
sharedFolderNode.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
|
||||||
|
|
||||||
Node usersNode =null;
|
|
||||||
if (sharedFolderNode.hasNode("hl:users"))
|
|
||||||
usersNode = sharedFolderNode.getNode("hl:users");
|
|
||||||
else
|
|
||||||
usersNode = sharedFolderNode.addNode("hl:users");
|
|
||||||
|
|
||||||
|
Node sharedFolderNode;
|
||||||
|
if (!node2Item.checkNodeType(nodeToShare, SharedFolder.class))
|
||||||
|
sharedFolderNode= shareFolder(nodeToShare, ses);
|
||||||
|
else {
|
||||||
|
sharedFolderNode = nodeToShare;
|
||||||
|
alreadyShared = true;
|
||||||
|
}
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(newNodePath, true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,login);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
AccessControlManager acm = ses.getAccessControlManager();
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||||
|
|
||||||
//setting data for ADMINISTRATOR
|
if (!alreadyShared) {
|
||||||
org.gcube.common.storagehub.model.Path adminFolderPath = Paths.append(Utils.getHomePath(), item.getName());
|
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
||||||
|
addUserToSharing(sharedFolderNode, ses, login, adminPrivileges, acls);
|
||||||
log.debug("trying to clone dir from {} to {}", sharedFolderNode.getPath(), adminFolderPath.toPath());
|
users.remove(login);
|
||||||
|
|
||||||
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), adminFolderPath.toPath(), false);
|
|
||||||
String adminRootWSId = ses.getNode(Utils.getHomePath().toPath()).getIdentifier();
|
|
||||||
|
|
||||||
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
|
|
||||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, login), adminPrivileges );
|
|
||||||
|
|
||||||
usersNode.setProperty(login, String.format("%s/%s",adminRootWSId,item.getName()));
|
|
||||||
|
|
||||||
users.remove(login);
|
|
||||||
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
|
||||||
for (String user : users) {
|
|
||||||
try {
|
|
||||||
org.gcube.common.storagehub.model.Path userFolderPath = Paths.append(Utils.getHomePath(user), item.getName());
|
|
||||||
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), userFolderPath.toPath(), false);
|
|
||||||
String userRootWSId = ses.getNode(Utils.getHomePath(user).toPath()).getIdentifier();
|
|
||||||
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
|
|
||||||
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,item.getName()));
|
|
||||||
}catch(Throwable t) {
|
|
||||||
log.warn("error sharing folder with user {}",user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Privilege[] userPrivileges = new Privilege[] { acm.privilegeFromName(accessType.getValue()) };
|
||||||
|
for (String user : users)
|
||||||
|
try {
|
||||||
|
addUserToSharing(sharedFolderNode, ses, user, userPrivileges, acls);
|
||||||
|
}catch(Exception e){
|
||||||
|
log.warn("error adding user {} to sharing of folder {}", user, sharedFolderNode.getName());
|
||||||
|
}
|
||||||
|
|
||||||
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
|
|
||||||
accountingHandler.shareFolder(item.getTitle(), users, ses, sharedFolderNode, false);
|
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, false);
|
||||||
|
|
||||||
ses.save();
|
ses.save();
|
||||||
|
|
||||||
return sharedFolderNode.getIdentifier();
|
toReturn = sharedFolderNode.getIdentifier();
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
ses.getWorkspace().getLockManager().unlock(newNodePath);
|
ses.getWorkspace().getLockManager().unlock(sharedFolderNode.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}catch(RepositoryException re){
|
||||||
|
log.error("jcr sharing", re);
|
||||||
}catch(Throwable e){
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||||
log.error("error sharing node with id {}",id,e);
|
}catch(StorageHubException she ){
|
||||||
throw new WebApplicationException(e);
|
log.error("error sharing", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private Node shareFolder(Node node, Session ses) throws RepositoryException, BackendGenericError, StorageHubException{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(node, FolderItem.class) || Utils.hasSharedChildren(node) || !node.getProperty(NodeProperty.OWNER.toString()).getString().equals(login))
|
||||||
|
throw new InvalidItemException("item with id "+id+" cannot be shared");
|
||||||
|
|
||||||
|
String sharedFolderName = node.getIdentifier();
|
||||||
|
|
||||||
|
String newNodePath = Constants.SHARED_FOLDER_PATH+"/"+sharedFolderName;
|
||||||
|
|
||||||
|
ses.move(node.getPath(),newNodePath);
|
||||||
|
|
||||||
|
Node sharedFolderNode = ses.getNode(newNodePath);
|
||||||
|
|
||||||
|
sharedFolderNode.setPrimaryType(PrimaryNodeType.NT_WORKSPACE_SHARED_FOLDER);
|
||||||
|
|
||||||
|
return sharedFolderNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addUserToSharing(Node sharedFolderNode, Session ses, String user, Privilege[] userPrivileges, JackrabbitAccessControlList acls) throws RepositoryException{
|
||||||
|
ses.getWorkspace().clone(ses.getWorkspace().getName(), sharedFolderNode.getPath(), sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), false);
|
||||||
|
String userRootWSId = ses.getNode(Utils.getHomePath(user).toPath()).getIdentifier();
|
||||||
|
acls.addAccessControlEntry(AccessControlUtils.getPrincipal(ses, user), userPrivileges );
|
||||||
|
Node usersNode =null;
|
||||||
|
if (sharedFolderNode.hasNode(NodeConstants.USERS_NAME))
|
||||||
|
usersNode = sharedFolderNode.getNode(NodeConstants.USERS_NAME);
|
||||||
|
else
|
||||||
|
usersNode = sharedFolderNode.addNode(NodeConstants.USERS_NAME);
|
||||||
|
usersNode.setProperty(user, String.format("%s/%s",userRootWSId,sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{id}/unshare")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
public String unshare(@FormDataParam("users") Set<String> users){
|
||||||
|
InnerMethodName.instance.set("unshareFolder");
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
Session ses = null;
|
||||||
|
String toReturn = null;
|
||||||
|
try {
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
Node sharedNode = ses.getNodeByIdentifier(id);
|
||||||
|
Item item = node2Item.getItem(sharedNode, Excludes.ALL);
|
||||||
|
if (!(item instanceof FolderItem) || !((FolderItem) item).isShared() || ((SharedFolder) item).isVreFolder())
|
||||||
|
throw new InvalidItemException("item with id "+id+" cannot be unshared");
|
||||||
|
SharedFolder sharedItem =(SharedFolder) item;
|
||||||
|
|
||||||
|
Set<String> usersInSharedFolder = new HashSet<>(sharedItem.getUsers().getValues().keySet());
|
||||||
|
usersInSharedFolder.removeAll(users);
|
||||||
|
|
||||||
|
if (users==null || users.size()==0 || usersInSharedFolder.size()<=1)
|
||||||
|
return unshareAll(login, ses, sharedItem);
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(sharedNode.getPath(), true, true, 0,login);
|
||||||
|
try {
|
||||||
|
if (users.size()==1 && users.contains(login))
|
||||||
|
toReturn = unshareCaller(login, ses, sharedItem);
|
||||||
|
else toReturn = unsharePartial(users, login, ses, sharedItem);
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(sharedNode.getPath());
|
||||||
|
}
|
||||||
|
}catch(RepositoryException re){
|
||||||
|
log.error("jcr unsharing", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error unsharing", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}finally{
|
||||||
|
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String unshareAll(String login, Session ses, SharedFolder item) throws StorageHubException, BackendGenericError, RepositoryException{
|
||||||
|
|
||||||
|
authChecker.checkAdministratorControl(ses, item);
|
||||||
|
if (!login.equals(item.getOwner()))
|
||||||
|
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare all");
|
||||||
|
|
||||||
|
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(sharedItemNode.getPath(), true, true, 0,login);
|
||||||
|
Node unsharedNode;
|
||||||
|
try {
|
||||||
|
log.debug("user list is empty, I'm going to remove also the shared dir");
|
||||||
|
//TODO: take the admin folder and remove his clone then move the shared folder from share to the user home and change the folder type
|
||||||
|
String adminDirPath = (String)item.getUsers().getValues().get(login);
|
||||||
|
String[] splitString = adminDirPath.split("/");
|
||||||
|
String parentDirectoryId = splitString[0];
|
||||||
|
String directoryName = splitString[1];
|
||||||
|
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||||
|
log.debug("parent node path is {}/{}",parentNode.getPath(), directoryName);
|
||||||
|
|
||||||
|
Node adminNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||||
|
adminNode.removeShare();
|
||||||
|
|
||||||
|
unsharedNode = createUnsharedFolder(ses, parentNode, directoryName, item.getDescription(), login);
|
||||||
|
|
||||||
|
List<Item> itemsToCopy = Utils.getItemList(sharedItemNode, Excludes.ALL, null, true, null);
|
||||||
|
|
||||||
|
for (Item itemCopy: itemsToCopy) {
|
||||||
|
Node itemToCopyNode = ses.getNodeByIdentifier(itemCopy.getId());
|
||||||
|
log.debug("copying {} to {}", itemToCopyNode.getPath(), unsharedNode.getPath());
|
||||||
|
ses.move(itemToCopyNode.getPath(), String.format("%s/%s",unsharedNode.getPath(), itemToCopyNode.getName()));
|
||||||
|
}
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(sharedItemNode.getPath());
|
||||||
|
}
|
||||||
|
sharedItemNode.removeSharedSet();
|
||||||
|
ses.save();
|
||||||
|
log.debug("all the users have been removed, the folder is totally unshared");
|
||||||
|
|
||||||
|
return unsharedNode.getIdentifier();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String unshareCaller(String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException{
|
||||||
|
|
||||||
|
if (login.equals(item.getOwner()))
|
||||||
|
throw new InvalidCallParameters("the callor is the owner, the folder cannot be unshared");
|
||||||
|
|
||||||
|
if (item.getUsers().getValues().get(login)==null)
|
||||||
|
throw new InvalidCallParameters("the folder is not shared with user "+login);
|
||||||
|
|
||||||
|
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
|
||||||
|
|
||||||
|
String parentId = removeSharingForUser(login, ses, item);
|
||||||
|
|
||||||
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||||
|
|
||||||
|
AccessControlEntry entryToDelete= null;
|
||||||
|
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
||||||
|
if (ace.getPrincipal().getName().equals(login)) {
|
||||||
|
entryToDelete = ace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (entryToDelete!=null)
|
||||||
|
acls.removeAccessControlEntry(entryToDelete);
|
||||||
|
|
||||||
|
log.debug("removed Access control entry for user {}",login);
|
||||||
|
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||||
|
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
|
||||||
|
usersNode.remove();
|
||||||
|
Node newUsersNode = sharedItemNode.addNode(NodeConstants.USERS_NAME);
|
||||||
|
|
||||||
|
item.getUsers().getValues().entrySet().stream().filter(entry -> !entry.getKey().equals(login)).forEach(entry-> {try {
|
||||||
|
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("error adding property to shared node users node under "+item.getId());
|
||||||
|
}});
|
||||||
|
|
||||||
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
|
ses.save();
|
||||||
|
|
||||||
|
return parentId;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String unsharePartial(Set<String> usersToUnshare, String login, Session ses, SharedFolder item) throws StorageHubException, RepositoryException {
|
||||||
|
authChecker.checkAdministratorControl(ses, (SharedFolder)item);
|
||||||
|
if (usersToUnshare.contains(item.getOwner()))
|
||||||
|
throw new UserNotAuthorizedException("user "+login+" not authorized to unshare owner");
|
||||||
|
|
||||||
|
Node sharedFolderNode =ses.getNodeByIdentifier(item.getId());
|
||||||
|
|
||||||
|
AccessControlManager acm = ses.getAccessControlManager();
|
||||||
|
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
|
||||||
|
|
||||||
|
for (String user : usersToUnshare) {
|
||||||
|
removeSharingForUser(user, ses, item);
|
||||||
|
|
||||||
|
AccessControlEntry entryToDelete= null;
|
||||||
|
for (AccessControlEntry ace :acls.getAccessControlEntries()) {
|
||||||
|
if (ace.getPrincipal().getName().equals(login)) {
|
||||||
|
entryToDelete = ace;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (entryToDelete!=null)
|
||||||
|
acls.removeAccessControlEntry(entryToDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("removed Access control entry for user {}",login);
|
||||||
|
Node sharedItemNode = ses.getNodeByIdentifier(item.getId());
|
||||||
|
Node usersNode = sharedItemNode.getNode(NodeConstants.USERS_NAME);
|
||||||
|
usersNode.remove();
|
||||||
|
Node newUsersNode = sharedItemNode.addNode(NodeConstants.USERS_NAME);
|
||||||
|
|
||||||
|
item.getUsers().getValues().entrySet().stream().filter(entry -> !usersToUnshare.contains(entry.getKey())).forEach(entry-> {try {
|
||||||
|
newUsersNode.setProperty(entry.getKey(), (String)entry.getValue());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("error adding property to shared node users node under "+item.getId());
|
||||||
|
}});
|
||||||
|
|
||||||
|
acm.setPolicy(sharedFolderNode.getPath(), acls);
|
||||||
|
|
||||||
|
ses.save();
|
||||||
|
|
||||||
|
return item.getId();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String removeSharingForUser(String user, Session ses, SharedFolder item) throws RepositoryException {
|
||||||
|
String userDirPath = (String)item.getUsers().getValues().get(user);
|
||||||
|
if (userDirPath==null) return null;
|
||||||
|
String[] splitString = userDirPath.split("/");
|
||||||
|
String parentDirectoryId = splitString[0];
|
||||||
|
String directoryName = splitString[1];
|
||||||
|
Node parentNode = ses.getNodeByIdentifier(parentDirectoryId);
|
||||||
|
Node userNode = ses.getNode(String.format("%s/%s",parentNode.getPath(), directoryName));
|
||||||
|
userNode.removeShare();
|
||||||
|
accountingHandler.createUnshareFolder(directoryName, ses, parentNode, false);
|
||||||
|
log.debug("directory removed for user {}",user);
|
||||||
|
return parentDirectoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Node createUnsharedFolder(Session ses, Node destinationNode, String name, String description, String login) {
|
||||||
|
FolderItem item = new FolderItem();
|
||||||
|
Calendar now = Calendar.getInstance();
|
||||||
|
item.setName(name);
|
||||||
|
item.setTitle(name);
|
||||||
|
item.setDescription(description);
|
||||||
|
//item.setCreationTime(now);
|
||||||
|
item.setHidden(false);
|
||||||
|
item.setLastAction(ItemAction.CREATED);
|
||||||
|
item.setLastModificationTime(now);
|
||||||
|
item.setLastModifiedBy(login);
|
||||||
|
item.setOwner(login);
|
||||||
|
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
|
Node newNode = item2Node.getNode(ses, destinationNode, item);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +1,67 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import static org.gcube.common.storagehub.model.NodeConstants.ACCOUNTING_NAME;
|
|
||||||
import static org.gcube.common.storagehub.model.NodeConstants.CONTENT_NAME;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.util.Collections;
|
||||||
import java.util.Calendar;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.jcr.ItemNotFoundException;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.PathNotFoundException;
|
import javax.jcr.PathNotFoundException;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveException;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveInputStream;
|
||||||
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
||||||
import org.apache.tika.config.TikaConfig;
|
import org.apache.tika.config.TikaConfig;
|
||||||
import org.apache.tika.detect.Detector;
|
import org.apache.tika.detect.Detector;
|
||||||
import org.apache.tika.io.TikaInputStream;
|
import org.apache.tika.io.TikaInputStream;
|
||||||
import org.apache.tika.metadata.Metadata;
|
import org.apache.tika.metadata.Metadata;
|
||||||
|
import org.gcube.common.authorization.library.AuthorizedTasks;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
|
import org.gcube.common.storagehub.model.items.GCubeItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
|
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.MetaInfo;
|
import org.gcube.data.access.storagehub.MetaInfo;
|
||||||
import org.gcube.data.access.storagehub.MultipleOutputStream;
|
import org.gcube.data.access.storagehub.MultipleOutputStream;
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
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.ContentHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
|
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
|
||||||
|
@ -78,237 +96,318 @@ public class ItemsCreator {
|
||||||
@Inject
|
@Inject
|
||||||
AccountingHandler accountingHandler;
|
AccountingHandler accountingHandler;
|
||||||
|
|
||||||
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
|
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Path("/{id}/create/FOLDER")
|
@Path("/{id}/create/FOLDER")
|
||||||
public Response createItem(@PathParam("id") String id, @PathParam("type") String type,@QueryParam("name") String name, @QueryParam("description") String description){
|
public String createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description) {
|
||||||
InnerMethodName.instance.set(String.format("createItem(%s)",type));
|
InnerMethodName.instance.set("createItem(FOLDER)");
|
||||||
log.info("create generic item called");
|
log.info("create folder item called");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
Item destinationItem = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
//TODO check if it is possible to change all the ACL on a workspace
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
//validate input parameters for Item Type
|
|
||||||
|
|
||||||
//if(!type.equals("FOLDER")) throw new IllegalAccessException("invalid item type");
|
|
||||||
|
|
||||||
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
Node destination = ses.getNodeByIdentifier(id);
|
|
||||||
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
|
|
||||||
|
|
||||||
if (!(destinationItem instanceof FolderItem)) throw new Exception("an Item must be created into a directory");
|
Node destination;
|
||||||
|
try {
|
||||||
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
|
destination = ses.getNodeByIdentifier(id);
|
||||||
|
}catch(ItemNotFoundException inf) {
|
||||||
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
|
throw new IdNotFoundException(id);
|
||||||
|
|
||||||
FolderItem item = new FolderItem();
|
|
||||||
Calendar now = Calendar.getInstance();
|
|
||||||
item.setName(name);
|
|
||||||
item.setTitle(name);
|
|
||||||
item.setDescription(description);
|
|
||||||
//item.setCreationTime(now);
|
|
||||||
item.setHidden(false);
|
|
||||||
item.setLastAction(ItemAction.CREATED);
|
|
||||||
item.setLastModificationTime(now);
|
|
||||||
item.setLastModifiedBy(login);
|
|
||||||
item.setOwner(login);
|
|
||||||
|
|
||||||
//to inherit hidden property
|
|
||||||
//item.setHidden(destinationItem.isHidden());
|
|
||||||
|
|
||||||
log.debug("item prepared, fulfilling content");
|
|
||||||
|
|
||||||
log.debug("content prepared");
|
|
||||||
Node newNode = ItemHandler.createNodeFromItem(ses, destination, item);
|
|
||||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), null, ses, newNode, false);
|
|
||||||
ses.save();
|
|
||||||
log.info("item with id {} correctly created",newNode.getIdentifier());
|
|
||||||
return Response.ok(newNode.getIdentifier()).build();
|
|
||||||
}catch(Exception e){
|
|
||||||
log.error("error creating item", e);
|
|
||||||
throw new WebApplicationException(e);
|
|
||||||
} finally{
|
|
||||||
if (ses!=null){
|
|
||||||
if (destinationItem!=null)
|
|
||||||
try {
|
|
||||||
if (ses.getWorkspace().getLockManager().isLocked(destinationItem.getPath()))
|
|
||||||
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
|
|
||||||
} catch (Throwable t){
|
|
||||||
log.warn("error unlocking {}", destinationItem.getPath(), t);
|
|
||||||
}
|
|
||||||
ses.logout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
||||||
|
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = Utils.createFolderInternally(ses, destination, name, description, login, accountingHandler);
|
||||||
|
ses.save();
|
||||||
|
} finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error creating item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error creating item", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/{id}/create/GCUBEITEM")
|
||||||
|
public String createGcubeItem(@PathParam("id") String id, GCubeItem item) {
|
||||||
|
InnerMethodName.instance.set("createItem(GCUBEITEM)");
|
||||||
|
log.info("create Gcube item called");
|
||||||
|
Session ses = null;
|
||||||
|
String toReturn = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
Node destination;
|
||||||
|
try {
|
||||||
|
destination = ses.getNodeByIdentifier(id);
|
||||||
|
}catch(ItemNotFoundException inf) {
|
||||||
|
throw new IdNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
|
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = Utils.createGcubeItemInternally(ses, destination, item.getName(), item.getDescription(), login, item, accountingHandler);
|
||||||
|
ses.save();
|
||||||
|
} finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
||||||
|
toReturn = newNode.getIdentifier();
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error creating item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error creating item", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
@Path("/{id}/create/FILE")
|
@Path("/{id}/create/FILE")
|
||||||
public Response createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
||||||
@FormDataParam("description") String description,
|
@FormDataParam("description") String description,
|
||||||
@FormDataParam("file") InputStream stream,
|
@FormDataParam("file") InputStream stream,
|
||||||
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||||
InnerMethodName.instance.set("createItem(FILE)");
|
InnerMethodName.instance.set("createItem(FILE)");
|
||||||
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
Item destinationItem = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
if (name==null || name.trim().isEmpty() || description ==null) throw new Exception("name or description are null");
|
if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null");
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
//TODO check if it is possible to change all the ACL on a workspace
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
//TODO: validate input parameters for Item Type
|
|
||||||
Node destination = ses.getNodeByIdentifier(id);
|
Node destination = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
|
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
|
||||||
|
|
||||||
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
if (!(destinationItem instanceof FolderItem)) throw new Exception("an Item must be copyed to another directory");
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
|
|
||||||
ContentHandler handler = getContentHandler(stream , name, destinationItem.getPath());
|
|
||||||
|
|
||||||
AbstractFileItem item =handler.buildItem(name, description, login);
|
|
||||||
|
|
||||||
//to inherit hidden property
|
|
||||||
//item.setHidden(destinationItem.isHidden());
|
|
||||||
|
|
||||||
log.debug("item prepared, fulfilling content");
|
|
||||||
log.debug("content prepared");
|
|
||||||
|
|
||||||
Node newNode;
|
Node newNode;
|
||||||
try {
|
try {
|
||||||
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationItem.getPath()), name).toPath());
|
newNode = createFileItemInternally(ses, destination, stream, name, description, login);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
|
ses.save();
|
||||||
versionHandler.checkoutContentNode(newNode, ses);
|
} finally {
|
||||||
log.trace("replacing content of class {}",item.getContent().getClass());
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
ItemHandler.replaceContent(ses, newNode,item);
|
|
||||||
}catch(PathNotFoundException pnf) {
|
|
||||||
log.info("creating new node");
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
|
|
||||||
newNode = ItemHandler.createNodeFromItem(ses, destination, item);
|
|
||||||
versionHandler.makeVersionableContent(newNode, ses);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
|
|
||||||
|
|
||||||
ses.save();
|
|
||||||
versionHandler.checkinContentNode(newNode, ses);
|
versionHandler.checkinContentNode(newNode, ses);
|
||||||
log.info("file with id {} correctly created",newNode.getIdentifier());
|
log.info("file with id {} correctly created",newNode.getIdentifier());
|
||||||
return Response.ok(newNode.getIdentifier()).build();
|
toReturn = newNode.getIdentifier();
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error creating item", e);
|
log.error("jcr error creating file item", re);
|
||||||
return Response.serverError().build();
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error creating file item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
} finally{
|
} finally{
|
||||||
if (ses!=null){
|
if (ses!=null)
|
||||||
if (destinationItem!=null)
|
|
||||||
try {
|
|
||||||
if (ses.getWorkspace().getLockManager().isLocked(destinationItem.getPath()))
|
|
||||||
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
|
|
||||||
} catch (Throwable t){
|
|
||||||
log.warn("error unlocking {}", destinationItem.getPath(), t);
|
|
||||||
}
|
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return toReturn;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login) throws RepositoryException, UserNotAuthorizedException, BackendGenericError{
|
||||||
|
|
||||||
|
ContentHandler handler = getContentHandler(stream , name, destinationNode.getPath(), login);
|
||||||
|
|
||||||
|
AbstractFileItem item =handler.buildItem(name, description, login);
|
||||||
|
|
||||||
|
//to inherit hidden property
|
||||||
|
//item.setHidden(destinationItem.isHidden());
|
||||||
|
|
||||||
|
log.debug("item prepared, fulfilling content");
|
||||||
|
log.debug("content prepared");
|
||||||
|
|
||||||
|
Node newNode;
|
||||||
|
try {
|
||||||
|
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationNode.getPath()), name).toPath());
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
|
||||||
|
versionHandler.checkoutContentNode(newNode, ses);
|
||||||
|
log.trace("replacing content of class {}",item.getContent().getClass());
|
||||||
|
item2Node.replaceContent(ses, newNode,item, ItemAction.UPDATED);
|
||||||
|
}catch(PathNotFoundException pnf) {
|
||||||
|
log.info("creating new node");
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destinationNode.getIdentifier(), true);
|
||||||
|
newNode = item2Node.getNode(ses, destinationNode, item);
|
||||||
|
versionHandler.makeVersionableContent(newNode, ses);
|
||||||
|
}
|
||||||
|
|
||||||
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("/{id}/create/ARCHIVE")
|
@Path("/{id}/create/ARCHIVE")
|
||||||
public Response uploadArchive(@PathParam("id") String id, @FormDataParam("folderName") String folderName,
|
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
|
||||||
@FormDataParam("file") InputStream stream,
|
@FormDataParam("file") InputStream stream,
|
||||||
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
||||||
InnerMethodName.instance.set("createItem(FILE)");
|
InnerMethodName.instance.set("createItem(ARCHIVE)");
|
||||||
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
Item destinationItem = null;
|
String toReturn = null;
|
||||||
try{
|
try{
|
||||||
if (folderName==null) throw new Exception("new folder name is null");
|
if (parentFolderName==null) throw new InvalidCallParameters("new folder name is null");
|
||||||
|
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
//TODO check if it is possible to change all the ACL on a workspace
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
//TODO: validate input parameters for Item Type
|
|
||||||
Node destination = ses.getNodeByIdentifier(id);
|
Node destination = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
||||||
if (!(destinationItem instanceof FolderItem)) throw new Exception("destination item is not a folder");
|
throw new InvalidItemException("the destination item is not a folder");
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier() , true);
|
||||||
|
|
||||||
ContentHandler handler = getContentHandler(stream , name, destinationItem.getPath());
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), true, true, 0,login);
|
||||||
|
Node parentDirectoryNode = null;
|
||||||
|
|
||||||
AbstractFileItem item =handler.buildItem(name, description, login);
|
|
||||||
|
|
||||||
//to inherit hidden property
|
|
||||||
//item.setHidden(destinationItem.isHidden());
|
|
||||||
|
|
||||||
log.debug("item prepared, fulfilling content");
|
|
||||||
log.debug("content prepared");
|
|
||||||
|
|
||||||
Node newNode;
|
|
||||||
try {
|
try {
|
||||||
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationItem.getPath()), name).toPath());
|
parentDirectoryNode = Utils.createFolderInternally(ses, destination, parentFolderName, "", login, accountingHandler);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
|
|
||||||
versionHandler.checkoutContentNode(newNode, ses);
|
|
||||||
log.trace("replacing content of class {}",item.getContent().getClass());
|
|
||||||
ItemHandler.replaceContent(ses, newNode,item);
|
|
||||||
}catch(PathNotFoundException pnf) {
|
|
||||||
log.info("creating new node");
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
|
|
||||||
newNode = ItemHandler.createNodeFromItem(ses, destination, item);
|
|
||||||
versionHandler.makeVersionableContent(newNode, ses);
|
|
||||||
}
|
|
||||||
|
|
||||||
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
|
Set<Node> fileNodes = new HashSet<>();
|
||||||
|
|
||||||
ses.save();
|
|
||||||
versionHandler.checkinContentNode(newNode, ses);
|
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
||||||
log.info("file with id {} correctly created",newNode.getIdentifier());
|
|
||||||
return Response.ok(newNode.getIdentifier()).build();
|
try (ArchiveInputStream input = new ArchiveStreamFactory()
|
||||||
}catch(Throwable e){
|
.createArchiveInputStream(new BufferedInputStream(stream, 1024*64))){
|
||||||
log.error("error creating item", e);
|
ArchiveEntry entry;
|
||||||
return Response.serverError().build();
|
while ((entry = input.getNextEntry()) != null) {
|
||||||
} finally{
|
if (entry.isDirectory()) {
|
||||||
if (ses!=null){
|
String entirePath = entry.getName();
|
||||||
if (destinationItem!=null)
|
String name = entirePath.replaceAll("(.*/)*(.*)/", "$2");
|
||||||
try {
|
String parentPath = entirePath.replaceAll("(.*/)*(.*)/", "$1");
|
||||||
if (ses.getWorkspace().getLockManager().isLocked(destinationItem.getPath()))
|
log.debug("creating directory with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
||||||
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
|
Node createdNode;
|
||||||
} catch (Throwable t){
|
if (parentPath.isEmpty()) {
|
||||||
log.warn("error unlocking {}", destinationItem.getPath(), t);
|
createdNode = Utils.createFolderInternally(ses, parentDirectoryNode, name, "", login, accountingHandler);
|
||||||
|
}else {
|
||||||
|
Node parentNode = directoryNodeMap.get(parentPath);
|
||||||
|
createdNode = Utils.createFolderInternally(ses, parentNode, name, "", login, accountingHandler);
|
||||||
|
}
|
||||||
|
directoryNodeMap.put(entirePath, createdNode);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
String entirePath = entry.getName();
|
||||||
|
String name = entirePath.replaceAll("(.*/)*(.*)", "$2");
|
||||||
|
String parentPath = entirePath.replaceAll("(.*/)*(.*)", "$1");
|
||||||
|
log.debug("creating file with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
||||||
|
Node fileNode = null;
|
||||||
|
if (parentPath.isEmpty())
|
||||||
|
fileNode = createFileItemInternally(ses, parentDirectoryNode, input, name, "", login);
|
||||||
|
else {
|
||||||
|
Node parentNode = directoryNodeMap.get(parentPath);
|
||||||
|
fileNode = createFileItemInternally(ses, parentNode, input, name, "", login);
|
||||||
|
}
|
||||||
|
fileNodes.add(fileNode);
|
||||||
|
}catch(Exception e) {
|
||||||
|
log.warn("error getting file {}",entry.getName(),e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ses.logout();
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ses.save();
|
||||||
|
for (Node node : fileNodes)
|
||||||
|
versionHandler.checkinContentNode(node, ses);
|
||||||
|
toReturn = parentDirectoryNode.getIdentifier();
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (ses.getWorkspace().getLockManager().isLocked(destination.getPath()))
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
} catch (Throwable t){
|
||||||
|
log.warn("error unlocking {}", destination.getPath(), t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}catch(RepositoryException | ArchiveException | IOException re){
|
||||||
|
log.error("jcr error extracting archive", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error creating file item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
} finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
private ContentHandler getContentHandler(InputStream stream , String name, String path) throws Exception {
|
|
||||||
|
|
||||||
final MultipleOutputStream mos = new MultipleOutputStream(stream, 2);
|
private ContentHandler getContentHandler(InputStream stream , String name, String path, String login) throws BackendGenericError {
|
||||||
|
|
||||||
|
|
||||||
|
final MultipleOutputStream mos;
|
||||||
|
try{
|
||||||
|
mos = new MultipleOutputStream(stream, 2);
|
||||||
|
}catch (IOException e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
|
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
|
||||||
|
|
||||||
|
@ -317,7 +416,7 @@ public class ItemsCreator {
|
||||||
ContentHandler handler =null;
|
ContentHandler handler =null;
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
log.debug("TIMING: reading the mimetype - start");
|
log.debug("TIMING: reading the mimetype - start");
|
||||||
try(BufferedInputStream is1 = new BufferedInputStream(mos.get(), 2048)){
|
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
|
||||||
org.apache.tika.mime.MediaType mediaType = null;
|
org.apache.tika.mime.MediaType mediaType = null;
|
||||||
TikaConfig config = TikaConfig.getDefaultConfig();
|
TikaConfig config = TikaConfig.getDefaultConfig();
|
||||||
Detector detector = config.getDetector();
|
Detector detector = config.getDetector();
|
||||||
|
@ -330,7 +429,7 @@ public class ItemsCreator {
|
||||||
handler = contenthandlerFactory.create(mimeType);
|
handler = contenthandlerFactory.create(mimeType);
|
||||||
|
|
||||||
is1.reset();
|
is1.reset();
|
||||||
handler.initiliseSpecificContent(is1);
|
handler.initiliseSpecificContent(is1, name);
|
||||||
handler.getContent().setMimeType(mimeType);
|
handler.getContent().setMimeType(mimeType);
|
||||||
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
|
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -346,17 +445,22 @@ public class ItemsCreator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MetaInfo call() throws Exception {
|
public MetaInfo call() throws Exception {
|
||||||
try {
|
try(InputStream is1 = mos.get()){
|
||||||
|
String uid = UUID.randomUUID().toString();
|
||||||
|
String remotePath= String.format("%s/%s-%s",path,uid,name);
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
log.debug("TIMING: sending the content to Storage - start");
|
log.debug("TIMING: sending the content to Storage - start");
|
||||||
String remotePath= path+"/"+name;
|
IClient storageClient = Utils.getStorageClient(login).getClient();
|
||||||
String storageId = Utils.getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().put(true).LFile(mos.get()).RFile(remotePath);
|
log.debug("TIMING: getting the client took {} ",System.currentTimeMillis()-start);
|
||||||
long size = Utils.getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().getSize().RFileById(storageId);
|
String storageId =storageClient.put(true).LFile(is1).RFile(remotePath);
|
||||||
|
log.debug("returned storage Id is {} for remotepath {}",storageId, remotePath);
|
||||||
|
log.debug("TIMING: sending the file took {} ",System.currentTimeMillis()-start);
|
||||||
|
long size = storageClient.getSize().RFileById(storageId);
|
||||||
|
log.debug("TIMING: sending the content to Storage - finished in {}",System.currentTimeMillis()-start);
|
||||||
MetaInfo info = new MetaInfo();
|
MetaInfo info = new MetaInfo();
|
||||||
info.setSize(size);
|
info.setSize(size);
|
||||||
info.setStorageId(storageId);
|
info.setStorageId(storageId);
|
||||||
info.setRemotePath(remotePath);
|
info.setRemotePath(remotePath);
|
||||||
log.debug("TIMING: sending the content to Storage - finished in {}",System.currentTimeMillis()-start);
|
|
||||||
return info;
|
return info;
|
||||||
}catch (Throwable e) {
|
}catch (Throwable e) {
|
||||||
log.error("error writing content");
|
log.error("error writing content");
|
||||||
|
@ -366,21 +470,25 @@ public class ItemsCreator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Future<ContentHandler> detectorF = executor.submit(mimeTypeDector);
|
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
|
||||||
Future<MetaInfo> uploaderF = executor.submit(uploader);
|
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
log.debug("TIMING: writing the strem - start");
|
log.debug("TIMING: writing the stream - start");
|
||||||
mos.startWriting();
|
try {
|
||||||
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
|
mos.startWriting();
|
||||||
|
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
|
||||||
|
|
||||||
ContentHandler handler = detectorF.get();
|
ContentHandler handler = detectorF.get();
|
||||||
MetaInfo info = uploaderF.get();
|
MetaInfo info = uploaderF.get();
|
||||||
handler.getContent().setData("jcr:content");
|
handler.getContent().setData(NodeConstants.CONTENT_NAME);
|
||||||
handler.getContent().setStorageId(info.getStorageId());
|
handler.getContent().setStorageId(info.getStorageId());
|
||||||
handler.getContent().setSize(info.getSize());
|
handler.getContent().setSize(info.getSize());
|
||||||
handler.getContent().setRemotePath(info.getRemotePath());
|
handler.getContent().setRemotePath(info.getRemotePath());
|
||||||
return handler;
|
return handler;
|
||||||
|
}catch (Exception e) {
|
||||||
|
throw new BackendGenericError(e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,15 @@ package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
@ -20,43 +18,55 @@ import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.version.Version;
|
import javax.jcr.version.Version;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.FormParam;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.StreamingOutput;
|
import javax.ws.rs.core.StreamingOutput;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.NodeConstants;
|
import org.gcube.common.storagehub.model.NodeConstants;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
||||||
import org.gcube.common.storagehub.model.items.FolderItem;
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.items.SharedFolder;
|
import org.gcube.common.storagehub.model.items.SharedFolder;
|
||||||
import org.gcube.common.storagehub.model.items.TrashItem;
|
|
||||||
import org.gcube.common.storagehub.model.items.VreFolder;
|
import org.gcube.common.storagehub.model.items.VreFolder;
|
||||||
import org.gcube.common.storagehub.model.service.ItemList;
|
import org.gcube.common.storagehub.model.service.ItemList;
|
||||||
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
||||||
|
import org.gcube.common.storagehub.model.service.VersionList;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.contentmanagement.blobstorage.service.IClient;
|
import org.gcube.common.storagehub.model.types.NodeProperty;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
import org.gcube.data.access.storagehub.Constants;
|
import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.Range;
|
import org.gcube.data.access.storagehub.Range;
|
||||||
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
|
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.ClassHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
import org.gcube.data.access.storagehub.handlers.VersionHandler;
|
||||||
import org.gcube.smartgears.utils.InnerMethodName;
|
import org.gcube.smartgears.utils.InnerMethodName;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -86,6 +96,12 @@ public class ItemsManager {
|
||||||
@Inject
|
@Inject
|
||||||
VersionHandler versionHandler;
|
VersionHandler versionHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
TrashHandler trashHandler;
|
||||||
|
|
||||||
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -96,10 +112,13 @@ public class ItemsManager {
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = ItemHandler.getItem(ses.getNodeByIdentifier(id), excludes);
|
toReturn = node2Item.getItem(ses.getNodeByIdentifier(id), excludes);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re){
|
||||||
log.error("error reading the node children of {}",id,e);
|
log.error("jcr error getting item", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -120,10 +139,13 @@ public class ItemsManager {
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
NodeIterator it = ses.getNodeByIdentifier(id).getNodes(name);
|
NodeIterator it = ses.getNodeByIdentifier(id).getNodes(name);
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
toReturn.add(ItemHandler.getItem(it.nextNode(), excludes));
|
toReturn.add(node2Item.getItem(it.nextNode(), excludes));
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re){
|
||||||
log.error("error reading the node children of {} with name pattern",id,name,e);
|
log.error("jcr error searching item", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error searching item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -136,17 +158,22 @@ public class ItemsManager {
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/children/count")
|
@Path("{id}/children/count")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes){
|
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||||
InnerMethodName.instance.set("countById");
|
InnerMethodName.instance.set("countById");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
Long toReturn = null;
|
Long toReturn = null;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden);
|
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch(Throwable e){
|
}catch(RuntimeException | RepositoryException re){
|
||||||
log.error("error reading the node children of {}",id,e);
|
log.error("jcr error counting item", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error counting item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -157,17 +184,20 @@ public class ItemsManager {
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/children")
|
@Path("{id}/children")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes){
|
public ItemList listById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||||
InnerMethodName.instance.set("listById");
|
InnerMethodName.instance.set("listById");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden);
|
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re){
|
||||||
log.error("error reading the node children of {}",id,e);
|
log.error("jcr error getting children", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting children", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -179,17 +209,20 @@ public class ItemsManager {
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/children/paged")
|
@Path("{id}/children/paged")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ItemList listByIdPaged(@QueryParam("showHidden") Boolean showHidden, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("exclude") List<String> excludes){
|
public ItemList listByIdPaged(@QueryParam("showHidden") Boolean showHidden, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
|
||||||
InnerMethodName.instance.set("listByIdPaged");
|
InnerMethodName.instance.set("listByIdPaged");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden);
|
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re){
|
||||||
log.error("error reading the node children of {}",id,e);
|
log.error("jcr error getting paged children", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting paged children", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -199,32 +232,68 @@ public class ItemsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Path("{id}/publiclink")
|
@Path("{id}/publiclink")
|
||||||
public URL getPubliclink() {
|
public URL getPublicLink(@QueryParam("version") String version) {
|
||||||
InnerMethodName.instance.set("getPubliclink");
|
InnerMethodName.instance.set("getPubliclink");
|
||||||
//TODO: check who can call this method
|
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
URL toReturn = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
Item item = ItemHandler.getItem(ses.getNodeByIdentifier(id), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
Node selectedNode = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
if (!(item instanceof AbstractFileItem)) throw new Exception("the select item is not a File");
|
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
||||||
|
|
||||||
AbstractFileItem fileItem = (AbstractFileItem) item;
|
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
|
||||||
|
|
||||||
String url = Utils.getStorageClient(login).getClient().getHttpsUrl().RFileById(fileItem.getContent().getStorageId());
|
|
||||||
return new URL(url);
|
if (version!=null) {
|
||||||
}catch(Throwable e){
|
boolean versionFound = false;
|
||||||
log.error("error reading the node children of {}",id,e);
|
VersionList versions = getVersions();
|
||||||
throw new WebApplicationException(e);
|
for (org.gcube.common.storagehub.model.service.Version v: versions.getItemlist() )
|
||||||
|
if (v.getName().equals(version)) {
|
||||||
|
versionFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!versionFound) throw new InvalidCallParameters("the selected file has no version "+version);
|
||||||
|
}
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(selectedNode.getPath(), false, true, 0,login);
|
||||||
|
try {
|
||||||
|
selectedNode.setProperty(NodeProperty.IS_PUBLIC.toString(), true);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(selectedNode.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = createPublicLink(version, id);
|
||||||
|
|
||||||
|
toReturn = new URL(url);
|
||||||
|
|
||||||
|
}catch(RepositoryException | MalformedURLException re ){
|
||||||
|
log.error("jcr error getting public link", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting public link", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String createPublicLink(String version, String id) {
|
||||||
|
String basepath = context.getInitParameter("resolver-basepath");
|
||||||
|
String filePublicUrl = String.format("%s/%s",basepath, id);
|
||||||
|
if (version!=null)
|
||||||
|
filePublicUrl = String.format("%s/%s", filePublicUrl, version);
|
||||||
|
return filePublicUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -233,26 +302,128 @@ public class ItemsManager {
|
||||||
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
|
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
|
||||||
InnerMethodName.instance.set("getRootSharedFolder");
|
InnerMethodName.instance.set("getRootSharedFolder");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
Item sharedParent= null;
|
||||||
try{
|
try{
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
Item currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(id), excludes);
|
Node currentNode =ses.getNodeByIdentifier(id);
|
||||||
|
Item currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
|
|
||||||
if (!currentItem.isShared())
|
if (!currentItem.isShared())
|
||||||
throw new RuntimeException("this item is not shared");
|
throw new InvalidItemException("this item is not shared");
|
||||||
log.trace("current node is {}",currentItem.getPath());
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
while (!(currentItem instanceof SharedFolder ))
|
|
||||||
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(currentItem.getParentId()), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME, NodeConstants.CONTENT_NAME));
|
|
||||||
|
|
||||||
return new ItemWrapper<Item>(currentItem);
|
while (!node2Item.checkNodeType(currentNode, SharedFolder.class))
|
||||||
|
currentNode = currentNode.getParent();
|
||||||
|
|
||||||
}catch(Throwable e){
|
sharedParent = node2Item.getItem(currentNode, excludes);
|
||||||
log.error("error retrieving shared root folder of node with id {}",id,e);
|
|
||||||
throw new WebApplicationException(e);
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error getting rootSharedFolder", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting rootSharedFolder", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
return new ItemWrapper<Item>(sharedParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}/versions")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public VersionList getVersions(){
|
||||||
|
InnerMethodName.instance.set("getVersions");
|
||||||
|
Session ses = null;
|
||||||
|
List<org.gcube.common.storagehub.model.service.Version> versions = new ArrayList<>();
|
||||||
|
try{
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
Item currentItem = node2Item.getItem(node, Excludes.GET_ONLY_CONTENT);
|
||||||
|
if (!(currentItem instanceof AbstractFileItem))
|
||||||
|
throw new InvalidItemException("this item is not versioned");
|
||||||
|
|
||||||
|
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node, ses);
|
||||||
|
|
||||||
|
for (Version version: jcrVersions) {
|
||||||
|
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
|
||||||
|
versions.add(new org.gcube.common.storagehub.model.service.Version(version.getIdentifier(), version.getName(), version.getCreated(), currentVersion));
|
||||||
|
}
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error retrieving versions", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error retrieving versions", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
return new VersionList(versions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}/versions/{version}/download")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response downloadVersion(@PathParam("version") String versionName){
|
||||||
|
InnerMethodName.instance.set("downloadSpecificVersion");
|
||||||
|
Session ses = null;
|
||||||
|
try{
|
||||||
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
Node node = ses.getNodeByIdentifier(id);
|
||||||
|
Item currentItem = node2Item.getItem(node, Excludes.ALL);
|
||||||
|
if (!(currentItem instanceof AbstractFileItem))
|
||||||
|
throw new InvalidItemException("this item is not a file");
|
||||||
|
|
||||||
|
List<Version> jcrVersions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(id), ses);
|
||||||
|
|
||||||
|
for (Version version: jcrVersions) {
|
||||||
|
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
|
||||||
|
if (version.getName().equals(versionName)) {
|
||||||
|
long size = version.getFrozenNode().getProperty(NodeProperty.SIZE.toString()).getLong();
|
||||||
|
String mimeType = version.getFrozenNode().getProperty(NodeProperty.MIME_TYPE.toString()).getString();
|
||||||
|
String storageId = version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
|
||||||
|
|
||||||
|
final InputStream streamToWrite = Utils.getStorageClient(login).getClient().get().RFileAsInputStream(storageId);
|
||||||
|
|
||||||
|
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
|
||||||
|
String ext = FilenameUtils.getExtension(currentItem.getTitle());
|
||||||
|
|
||||||
|
String fileName = String.format("%s_v%s.%s", oldfilename, version.getName(), ext);
|
||||||
|
|
||||||
|
|
||||||
|
accountingHandler.createReadObj(fileName, ses, node, true);
|
||||||
|
|
||||||
|
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||||
|
|
||||||
|
return Response
|
||||||
|
.ok(so)
|
||||||
|
.header("content-disposition","attachment; filename = \""+fileName+"\"")
|
||||||
|
.header("Content-Length", size)
|
||||||
|
.header("Content-Type", mimeType)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error downloading version", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error downloading version", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
return Response.serverError().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -267,26 +438,32 @@ public class ItemsManager {
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
Item currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(id), excludes);
|
Node currentNode = ses.getNodeByIdentifier(id);
|
||||||
log.trace("current node is {}",currentItem.getPath());
|
Item currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
while (!(currentItem.getPath()+"/").equals(absolutePath.toPath())) {
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
|
while (!(currentNode.getPath()+"/").equals(absolutePath.toPath())) {
|
||||||
if (currentItem instanceof SharedFolder){
|
if (currentItem instanceof SharedFolder){
|
||||||
Map<String, Object> users = ((SharedFolder) currentItem).getUsers().getValues();
|
Map<String, Object> users = ((SharedFolder) currentItem).getUsers().getValues();
|
||||||
String[] user = ((String)users.get(login)).split("/");
|
String[] user = ((String)users.get(login)).split("/");
|
||||||
String parentId = user[0];
|
String parentId = user[0];
|
||||||
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(parentId), excludes);
|
currentNode = ses.getNodeByIdentifier(parentId);
|
||||||
|
currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
|
|
||||||
}else
|
}else {
|
||||||
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(currentItem.getParentId()), excludes);
|
currentNode = currentNode.getParent();
|
||||||
|
currentItem = node2Item.getItem(currentNode, excludes);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.trace("current node is {}",currentNode.getPath());
|
||||||
log.trace("current node is {}",currentItem.getPath());
|
|
||||||
toReturn.add(currentItem);
|
toReturn.add(currentItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error retrieving parents of node with id {}",id,e);
|
log.error("jcr error getting anchestors", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting anchestors", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -302,15 +479,16 @@ public class ItemsManager {
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{id}/download")
|
@Path("{id}/download")
|
||||||
public Response download(){
|
public Response download(@QueryParam("exclude") List<String> excludes){
|
||||||
InnerMethodName.instance.set("downloadById");
|
InnerMethodName.instance.set("downloadById");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
Response response = null;
|
||||||
try{
|
try{
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
final Node node = ses.getNodeByIdentifier(id);
|
final Node node = ses.getNodeByIdentifier(id);
|
||||||
authChecker.checkReadAuthorizationControl(ses, id);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
final Item item = ItemHandler.getItem(node, null);
|
final Item item = node2Item.getItem(node, null);
|
||||||
if (item instanceof AbstractFileItem){
|
if (item instanceof AbstractFileItem){
|
||||||
AbstractFileItem fileItem =(AbstractFileItem) item;
|
AbstractFileItem fileItem =(AbstractFileItem) item;
|
||||||
|
|
||||||
|
@ -320,17 +498,18 @@ public class ItemsManager {
|
||||||
|
|
||||||
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
|
||||||
|
|
||||||
return Response
|
response = Response
|
||||||
.ok(so)
|
.ok(so)
|
||||||
.header("content-disposition","attachment; filename = "+fileItem.getName())
|
.header("content-disposition","attachment; filename = \""+fileItem.getName()+"\"")
|
||||||
.header("Content-Length", fileItem.getContent().getSize())
|
.header("Content-Length", fileItem.getContent().getSize())
|
||||||
|
.header("Content-Type", fileItem.getContent().getMimeType())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
} else if (item instanceof FolderItem){
|
} else if (item instanceof FolderItem){
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler);
|
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler, excludes);
|
||||||
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getPath());
|
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
|
||||||
StreamingOutput so = new StreamingOutput() {
|
StreamingOutput so = new StreamingOutput() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -349,30 +528,103 @@ public class ItemsManager {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return Response
|
response = Response
|
||||||
.ok(so)
|
.ok(so)
|
||||||
.header("content-disposition","attachment; filename = directory.zip")
|
.header("content-disposition","attachment; filename = \""+item.getTitle()+".zip\"")
|
||||||
|
.header("Content-Type", "application/zip")
|
||||||
.header("Content-Length", -1l)
|
.header("Content-Length", -1l)
|
||||||
.build();
|
.build();
|
||||||
}finally {
|
}finally {
|
||||||
if (ses!=null) ses.save();
|
if (ses!=null) ses.save();
|
||||||
}
|
}
|
||||||
} else throw new Exception("item type not supported for download: "+item.getClass());
|
} else throw new InvalidItemException("item type not supported for download: "+item.getClass());
|
||||||
|
|
||||||
}catch(Exception e ){
|
}catch(RepositoryException re ){
|
||||||
log.error("error downloading item content",e);
|
log.error("jcr error download", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error download", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
} finally{
|
} finally{
|
||||||
if (ses!=null) ses.logout();
|
if (ses!=null) ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("{id}/move")
|
@Path("{id}/move")
|
||||||
public Response move(@QueryParam("destinationId") String destinationId, @PathParam("id") String identifier){
|
public String move(@FormParam("destinationId") String destinationId){
|
||||||
InnerMethodName.instance.set("move");
|
InnerMethodName.instance.set("move");
|
||||||
//TODO: check if identifier is The Workspace root, or the thras folder or the VREFolder root or if the item is thrashed
|
//TODO: check if identifier is The Workspace root, or the thras folder or the VREFolder root or if the item is thrashed
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
|
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||||
|
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||||
|
Node originalParent = nodeToMove.getParent();
|
||||||
|
|
||||||
|
Item destinationItem = node2Item.getItem(destination,null);
|
||||||
|
final Item item = node2Item.getItem(nodeToMove, null);
|
||||||
|
|
||||||
|
if (item instanceof SharedFolder)
|
||||||
|
throw new InvalidItemException("shared folder cannot be moved");
|
||||||
|
|
||||||
|
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()) || Constants.FOLDERS_TO_EXLUDE.contains(destinationItem.getTitle()))
|
||||||
|
throw new InvalidItemException("protected folder cannot be moved");
|
||||||
|
|
||||||
|
if (!(destinationItem instanceof FolderItem))
|
||||||
|
throw new InvalidItemException("destination item is not a folder");
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||||
|
try {
|
||||||
|
String uniqueName =(Utils.checkExistanceAndGetUniqueName(ses, destination, nodeToMove.getName()));
|
||||||
|
String newPath = String.format("%s/%s",destination.getPath(), uniqueName);
|
||||||
|
if (item instanceof FolderItem && Utils.hasSharedChildren(nodeToMove))
|
||||||
|
throw new InvalidItemException("folder item with shared children cannot be moved");
|
||||||
|
|
||||||
|
ses.getWorkspace().move(nodeToMove.getPath(), newPath);
|
||||||
|
Utils.setPropertyOnChangeNode(ses.getNode(newPath), login, ItemAction.MOVED);
|
||||||
|
|
||||||
|
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||||
|
|
||||||
|
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting , ses, destination, false);
|
||||||
|
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, originalParent, false);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||||
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error moving item", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error moving item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
} finally{
|
||||||
|
if (ses!=null) {
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{id}/copy")
|
||||||
|
public String copy(@FormParam("destinationId") String destinationId, @FormParam("fileName") String newFileName){
|
||||||
|
InnerMethodName.instance.set("copy");
|
||||||
|
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root or if the item is thrashed
|
||||||
|
Session ses = null;
|
||||||
|
String newFileIdentifier = null;
|
||||||
try{
|
try{
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
//ses = RepositoryInitializer.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
|
//ses = RepositoryInitializer.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
|
||||||
|
@ -380,81 +632,194 @@ public class ItemsManager {
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
|
||||||
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
|
authChecker.checkReadAuthorizationControl(ses, id);
|
||||||
|
|
||||||
final Node nodeToMove = ses.getNodeByIdentifier(identifier);
|
final Node nodeToCopy = ses.getNodeByIdentifier(id);
|
||||||
final Node destination = ses.getNodeByIdentifier(destinationId);
|
final Node destination = ses.getNodeByIdentifier(destinationId);
|
||||||
Item destinationItem = ItemHandler.getItem(destination,null);
|
//Item destinationItem = node2Item.getItem(destination,null);
|
||||||
|
|
||||||
final Item item = ItemHandler.getItem(nodeToMove, null);
|
final Item item = node2Item.getItem(nodeToCopy, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
|
||||||
|
|
||||||
if (item instanceof SharedFolder || item.isHidden() || destinationItem.isHidden())
|
if (item instanceof FolderItem)
|
||||||
throw new Exception("shared folder cannot be moved or cannot not move hidden item");
|
throw new InvalidItemException("folder cannot be copied");
|
||||||
|
|
||||||
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()) || Constants.FOLDERS_TO_EXLUDE.contains(destinationItem.getTitle()))
|
|
||||||
throw new Exception("protected folder cannot be moved");
|
|
||||||
|
|
||||||
|
|
||||||
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
ses.getWorkspace().getLockManager().lock(nodeToCopy.getPath(), true, true, 0,login);
|
||||||
|
try {
|
||||||
|
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, destination, newFileName);
|
||||||
|
String newPath= String.format("%s/%s", destination.getPath(), uniqueName);
|
||||||
|
ses.getWorkspace().copy(nodeToCopy.getPath(), newPath);
|
||||||
|
Node newNode = ses.getNode(newPath);
|
||||||
|
newFileIdentifier = newNode.getIdentifier();
|
||||||
|
//TODO: copy on storage and modify content
|
||||||
|
if (item instanceof AbstractFileItem) {
|
||||||
|
String newStorageID = Utils.getStorageClient(login).getClient().copyFile().from(((AbstractFileItem)item).getContent().getStorageId()).to(newPath);
|
||||||
|
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
|
||||||
|
item2Node.replaceContent(ses, newNode, (AbstractFileItem) item, ItemAction.CLONED);
|
||||||
|
} else
|
||||||
|
Utils.setPropertyOnChangeNode(newNode, login, ItemAction.CLONED);
|
||||||
|
|
||||||
if (item instanceof FolderItem){
|
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
|
||||||
|
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, destination, false);
|
||||||
|
|
||||||
if (Utils.hasSharedChildren((FolderItem) item, ses)) throw new Exception("folder item with shared children cannot be moved");
|
ses.save();
|
||||||
|
|
||||||
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
|
}finally {
|
||||||
}else
|
ses.getWorkspace().getLockManager().unlock(nodeToCopy.getPath());
|
||||||
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: accounting
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error moving item", re);
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
|
}catch(StorageHubException she ){
|
||||||
ses.save();
|
log.error("error moving item", she);
|
||||||
}catch(Exception e){
|
GXOutboundErrorResponse.throwException(she);
|
||||||
log.error("error moving item with id {} in item with id {}",identifier, destinationId,e);
|
|
||||||
throw new WebApplicationException(e);
|
|
||||||
} finally{
|
} finally{
|
||||||
if (ses!=null) {
|
if (ses!=null) {
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Response.ok().build();
|
return newFileIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{id}/rename")
|
||||||
|
public Response rename(@FormParam("newName") String newName){
|
||||||
|
InnerMethodName.instance.set("rename");
|
||||||
|
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root or if the item is thrashed
|
||||||
|
Session ses = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
|
final Node nodeToMove = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
final Item item = node2Item.getItem(nodeToMove, null);
|
||||||
|
|
||||||
|
if (item instanceof SharedFolder)
|
||||||
|
throw new InvalidItemException("shared folder");
|
||||||
|
|
||||||
|
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()))
|
||||||
|
throw new InvalidItemException("protected folder cannot be renamed");
|
||||||
|
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
|
||||||
|
ses.getWorkspace().getLockManager().lock(nodeToMove.getParent().getPath(), false, true, 0,login);
|
||||||
|
try {
|
||||||
|
String uniqueName = Utils.checkExistanceAndGetUniqueName(ses, nodeToMove.getParent(), newName);
|
||||||
|
|
||||||
|
String newPath = String.format("%s/%s", nodeToMove.getParent().getPath(), uniqueName);
|
||||||
|
nodeToMove.setProperty(NodeProperty.TITLE.toString(), uniqueName);
|
||||||
|
Utils.setPropertyOnChangeNode(nodeToMove, login, ItemAction.RENAMED);
|
||||||
|
ses.move(nodeToMove.getPath(), newPath);
|
||||||
|
accountingHandler.createRename(item.getTitle(), uniqueName, ses.getNode(newPath), ses, false);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
|
||||||
|
ses.getWorkspace().getLockManager().unlock(nodeToMove.getParent().getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error moving item", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error moving item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
} finally{
|
||||||
|
if (ses!=null) {
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return Response.ok(id).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/{id}/metadata")
|
||||||
|
public Response setProperties(org.gcube.common.storagehub.model.Metadata metadata){
|
||||||
|
InnerMethodName.instance.set("updateMetadata");
|
||||||
|
|
||||||
|
Session ses = null;
|
||||||
|
|
||||||
|
try{
|
||||||
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
|
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
|
final Node nodeToUpdate = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
|
|
||||||
|
ses.getWorkspace().getLockManager().lock(nodeToUpdate.getPath(), false, true, 0,login);
|
||||||
|
try {
|
||||||
|
item2Node.updateMetadataNode(ses, nodeToUpdate, metadata.getValues(), login);
|
||||||
|
ses.save();
|
||||||
|
}finally {
|
||||||
|
ses.getWorkspace().getLockManager().unlock(nodeToUpdate.getPath());
|
||||||
|
}
|
||||||
|
//TODO: UPDATE accounting
|
||||||
|
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error moving item", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error moving item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
} finally{
|
||||||
|
if (ses!=null) {
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return Response.ok(id).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
public Response deleteItem(@PathParam("id") String identifier){
|
public Response deleteItem(){
|
||||||
InnerMethodName.instance.set("deleteItem");
|
InnerMethodName.instance.set("deleteItem");
|
||||||
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root
|
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root
|
||||||
//TODO: check also that is not already trashed
|
//TODO: check also that is not already trashed
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
try{
|
try{
|
||||||
|
|
||||||
log.info("removing node with id {}", identifier);
|
log.info("removing node with id {}", id);
|
||||||
|
|
||||||
//TODO check if it is possible to change all the ACL on a workspace
|
//TODO check if it is possible to change all the ACL on a workspace
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
|
authChecker.checkWriteAuthorizationControl(ses, id, false);
|
||||||
|
|
||||||
final Node nodeToDelete = ses.getNodeByIdentifier(identifier);
|
final Node nodeToDelete = ses.getNodeByIdentifier(id);
|
||||||
|
|
||||||
Item itemToDelete = ItemHandler.getItem(nodeToDelete, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME, NodeConstants.OWNER_NAME));
|
Item itemToDelete = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
|
||||||
|
|
||||||
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren((FolderItem) itemToDelete, ses)))
|
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
|
||||||
throw new Exception("SharedFolder, VreFolder or folders with shared children cannot be deleted");
|
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
|
||||||
|
|
||||||
log.debug("item is trashed? {}", itemToDelete.isTrashed());
|
log.debug("item is trashed? {}", itemToDelete.isTrashed());
|
||||||
|
|
||||||
if (!itemToDelete.isTrashed())
|
if (!itemToDelete.isTrashed())
|
||||||
moveToTrash(ses, nodeToDelete, itemToDelete);
|
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete);
|
||||||
else
|
else
|
||||||
removeNode(ses, itemToDelete);
|
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
|
||||||
|
|
||||||
}catch(Exception e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error removing item with id {} in Thrash",identifier,e);
|
log.error("jcr error moving item", re);
|
||||||
throw new WebApplicationException(e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error moving item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
} finally{
|
} finally{
|
||||||
if (ses!=null) {
|
if (ses!=null) {
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -464,123 +829,4 @@ public class ItemsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeNode(Session ses, Item itemToDelete) throws Exception{
|
|
||||||
log.debug("removing node");
|
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
String parentPath = itemToDelete.getParentPath();
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(parentPath, true, true, 0,login);
|
|
||||||
Set<String> idsToDelete = new HashSet<>();
|
|
||||||
getAllContentIds(ses, idsToDelete, itemToDelete);
|
|
||||||
ses.removeItem(itemToDelete.getPath());
|
|
||||||
new Thread() {
|
|
||||||
|
|
||||||
private String user = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
for (String id: idsToDelete) {
|
|
||||||
try {
|
|
||||||
IClient client = Utils.getStorageClient(user).getClient();
|
|
||||||
client.remove().RFileById(id);
|
|
||||||
log.debug("file with id {} correctly removed on storage",id);
|
|
||||||
}catch(Throwable t) {
|
|
||||||
log.warn("error removing file on storage with id {}",id, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}.start();;
|
|
||||||
ses.save();
|
|
||||||
}finally {
|
|
||||||
ses.getWorkspace().getLockManager().unlock(parentPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void getAllContentIds(Session ses, Set<String> idsToDelete, Item itemToDelete) throws Exception{
|
|
||||||
if (itemToDelete instanceof AbstractFileItem) {
|
|
||||||
List<Version> versions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(itemToDelete.getId()), ses);
|
|
||||||
|
|
||||||
versions.forEach(v -> {
|
|
||||||
try {
|
|
||||||
String storageId =v.getProperty("hl:storageId").toString();
|
|
||||||
idsToDelete.add(storageId);
|
|
||||||
log.info("retrieved StorageId {} for version {}", storageId, v.getName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("error retreiving sotrageId",e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
idsToDelete.add(((AbstractFileItem) itemToDelete).getContent().getStorageId());
|
|
||||||
}else if (itemToDelete instanceof FolderItem) {
|
|
||||||
List<Item> items = Utils.getItemList(ses.getNodeByIdentifier(itemToDelete.getId()), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME, NodeConstants.OWNER_NAME) , null, true);
|
|
||||||
for (Item item: items)
|
|
||||||
getAllContentIds(ses, idsToDelete, item);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void moveToTrash(Session ses, Node nodeToDelete, Item item) throws Exception{
|
|
||||||
log.debug("moving node to trash");
|
|
||||||
final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
|
|
||||||
|
|
||||||
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
|
|
||||||
try {
|
|
||||||
ses.getWorkspace().getLockManager().lock(trashFolder.getPath(), true, true, 0,login);
|
|
||||||
ses.getWorkspace().getLockManager().lock(nodeToDelete.getPath(), true, true, 0,login);
|
|
||||||
|
|
||||||
log.debug("preparing thrash item");
|
|
||||||
|
|
||||||
TrashItem trashItem = new TrashItem();
|
|
||||||
trashItem.setDeletedBy(AuthorizationProvider.instance.get().getClient().getId());
|
|
||||||
trashItem.setDeletedFrom(nodeToDelete.getParent().getPath());
|
|
||||||
Calendar now = Calendar.getInstance();
|
|
||||||
trashItem.setDeletedTime(now);
|
|
||||||
trashItem.setHidden(false);
|
|
||||||
trashItem.setLastAction(ItemAction.CREATED);
|
|
||||||
trashItem.setDescription("trash item of node " + nodeToDelete.getPath());
|
|
||||||
trashItem.setParentId(trashFolder.getIdentifier());
|
|
||||||
trashItem.setParentPath(trashFolder.getPath());
|
|
||||||
String pathUUid= UUID.randomUUID().toString();
|
|
||||||
trashItem.setTitle(pathUUid);
|
|
||||||
trashItem.setName(pathUUid);
|
|
||||||
trashItem.setOriginalParentId(nodeToDelete.getParent().getIdentifier());
|
|
||||||
|
|
||||||
trashItem.setOwner(item.getOwner());
|
|
||||||
trashItem.setLastModificationTime(item.getLastModificationTime());
|
|
||||||
trashItem.setLastModifiedBy(item.getLastModifiedBy());
|
|
||||||
|
|
||||||
trashItem.setLenght(0);
|
|
||||||
|
|
||||||
if (item instanceof FolderItem)
|
|
||||||
trashItem.setFolder(true);
|
|
||||||
else if (item instanceof AbstractFileItem ) {
|
|
||||||
AbstractFileItem file = (AbstractFileItem) item;
|
|
||||||
trashItem.setMimeType(file.getContent().getMimeType());
|
|
||||||
trashItem.setLenght(file.getContent().getSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("creating node");
|
|
||||||
|
|
||||||
Node newTrashItemNode = ItemHandler.createNodeFromItem(ses, trashFolder, trashItem);
|
|
||||||
|
|
||||||
ses.save();
|
|
||||||
log.debug("calling move into jcr");
|
|
||||||
ses.getWorkspace().move(nodeToDelete.getPath(), Paths.append(Paths.getPath(newTrashItemNode.getPath()),nodeToDelete.getName()).toPath());
|
|
||||||
String mimetype = null;
|
|
||||||
if (item instanceof AbstractFileItem)
|
|
||||||
mimetype = ((AbstractFileItem) item).getContent().getMimeType();
|
|
||||||
accountingHandler.createFolderRemoveObj(item.getName(), item.getClass().getSimpleName(), mimetype, ses, ses.getNodeByIdentifier(item.getParentId()), true);
|
|
||||||
}finally {
|
|
||||||
ses.getWorkspace().getLockManager().unlock(nodeToDelete.getPath());
|
|
||||||
ses.getWorkspace().getLockManager().unlock(trashFolder.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package org.gcube.data.access.storagehub.services;
|
package org.gcube.data.access.storagehub.services;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -9,27 +10,35 @@ import javax.enterprise.context.RequestScoped;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.jcr.Node;
|
import javax.jcr.Node;
|
||||||
import javax.jcr.NodeIterator;
|
import javax.jcr.NodeIterator;
|
||||||
|
import javax.jcr.RepositoryException;
|
||||||
import javax.jcr.Session;
|
import javax.jcr.Session;
|
||||||
import javax.jcr.query.Query;
|
import javax.jcr.query.Query;
|
||||||
import javax.jcr.query.QueryResult;
|
import javax.jcr.query.QueryResult;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.xml.ws.WebServiceException;
|
|
||||||
|
|
||||||
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
||||||
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
import org.gcube.common.scope.impl.ScopeBean;
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
import org.gcube.common.scope.impl.ScopeBean.Type;
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||||
|
import org.gcube.common.storagehub.model.Excludes;
|
||||||
import org.gcube.common.storagehub.model.Paths;
|
import org.gcube.common.storagehub.model.Paths;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
||||||
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
||||||
import org.gcube.common.storagehub.model.expressions.Expression;
|
import org.gcube.common.storagehub.model.expressions.Expression;
|
||||||
import org.gcube.common.storagehub.model.expressions.logical.And;
|
import org.gcube.common.storagehub.model.expressions.logical.And;
|
||||||
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
|
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
|
import org.gcube.common.storagehub.model.items.TrashItem;
|
||||||
import org.gcube.common.storagehub.model.service.ItemList;
|
import org.gcube.common.storagehub.model.service.ItemList;
|
||||||
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
import org.gcube.common.storagehub.model.service.ItemWrapper;
|
||||||
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
||||||
|
@ -37,7 +46,9 @@ import org.gcube.data.access.storagehub.Constants;
|
||||||
import org.gcube.data.access.storagehub.Range;
|
import org.gcube.data.access.storagehub.Range;
|
||||||
import org.gcube.data.access.storagehub.Utils;
|
import org.gcube.data.access.storagehub.Utils;
|
||||||
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
|
import org.gcube.data.access.storagehub.handlers.TrashHandler;
|
||||||
import org.gcube.data.access.storagehub.handlers.VRE;
|
import org.gcube.data.access.storagehub.handlers.VRE;
|
||||||
import org.gcube.data.access.storagehub.handlers.VREManager;
|
import org.gcube.data.access.storagehub.handlers.VREManager;
|
||||||
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
|
||||||
|
@ -69,10 +80,15 @@ public class WorkspaceManager {
|
||||||
@Inject
|
@Inject
|
||||||
VREManager vreManager;
|
VREManager vreManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
TrashHandler trashHandler;
|
||||||
|
|
||||||
@RequestScoped
|
@RequestScoped
|
||||||
@QueryParam("exclude")
|
@QueryParam("exclude")
|
||||||
private List<String> excludes = Collections.emptyList();
|
private List<String> excludes = Collections.emptyList();
|
||||||
|
|
||||||
|
@Inject Node2ItemConverter node2Item;
|
||||||
|
@Inject Item2NodeConverter item2Node;
|
||||||
|
|
||||||
@Path("")
|
@Path("")
|
||||||
@GET
|
@GET
|
||||||
|
@ -87,16 +103,18 @@ public class WorkspaceManager {
|
||||||
|
|
||||||
Item toReturn = null;
|
Item toReturn = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
|
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
Node node = ses.getNode(absolutePath.toPath());
|
Node node = ses.getNode(absolutePath.toPath());
|
||||||
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
|
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
|
||||||
toReturn = ItemHandler.getItem(node, excludes);
|
toReturn = node2Item.getItem(node, excludes);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error reading the node children of {}",absolutePath,e);
|
log.error("jcr error getting workspace item", re);
|
||||||
throw new WebApplicationException("error getting WS folder "+absolutePath.toPath(),e) ;
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting workspace item", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -105,10 +123,10 @@ public class WorkspaceManager {
|
||||||
return new ItemWrapper<Item>(toReturn);
|
return new ItemWrapper<Item>(toReturn);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized VRE getVreFolderItem(Session ses) throws Exception{
|
private synchronized VRE getVreFolderItem(Session ses) throws RepositoryException, BackendGenericError{
|
||||||
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
|
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
|
||||||
if (!bean.is(Type.VRE)) throw new Exception("the current scope is not a VRE");
|
if (!bean.is(Type.VRE)) throw new BackendGenericError("the current scope is not a VRE");
|
||||||
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
|
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
|
||||||
VRE vre = vreManager.getVRE(entireScopeName);
|
VRE vre = vreManager.getVRE(entireScopeName);
|
||||||
if (vre!=null) return vre;
|
if (vre!=null) return vre;
|
||||||
|
@ -117,10 +135,10 @@ public class WorkspaceManager {
|
||||||
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
|
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
|
||||||
NodeIterator it = jcrQuery.execute().getNodes();
|
NodeIterator it = jcrQuery.execute().getNodes();
|
||||||
|
|
||||||
if (!it.hasNext()) throw new Exception("vre folder not found for context "+entireScopeName);
|
if (!it.hasNext()) throw new BackendGenericError("vre folder not found for context "+entireScopeName);
|
||||||
|
|
||||||
Node folder = it.nextNode();
|
Node folder = it.nextNode();
|
||||||
Item vreFolder = ItemHandler.getItem(folder, excludes);
|
Item vreFolder = node2Item.getItem(folder, excludes);
|
||||||
return vreManager.putVRE(vreFolder);
|
return vreManager.putVRE(vreFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,17 +151,21 @@ public class WorkspaceManager {
|
||||||
public ItemWrapper<Item> getVreRootFolder(){
|
public ItemWrapper<Item> getVreRootFolder(){
|
||||||
InnerMethodName.instance.set("getVreRootFolder");
|
InnerMethodName.instance.set("getVreRootFolder");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
Item vreItem = null;
|
||||||
try {
|
try {
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
return new ItemWrapper<Item>(getVreFolderItem(ses).getVreFolder());
|
vreItem = getVreFolderItem(ses).getVreFolder();
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error reading vreNode for context {}",ScopeProvider.instance.get(),e);
|
log.error("jcr error getting vrefolder", re);
|
||||||
throw new WebApplicationException("error retrieving vre folder",e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting vrefolder", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
return new ItemWrapper<Item>(vreItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("vrefolder/recents")
|
@Path("vrefolder/recents")
|
||||||
|
@ -152,23 +174,30 @@ public class WorkspaceManager {
|
||||||
public ItemList getVreFolderRecentsDocument(){
|
public ItemList getVreFolderRecentsDocument(){
|
||||||
InnerMethodName.instance.set("getVreFolderRecents");
|
InnerMethodName.instance.set("getVreFolderRecents");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
List<Item> recentItems = Collections.emptyList();
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
String login = AuthorizationProvider.instance.get().getClient().getId();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
VRE vre = getVreFolderItem(ses);
|
VRE vre = getVreFolderItem(ses);
|
||||||
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
|
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
|
||||||
List<Item> recentItems = vre.getRecents();
|
recentItems = vre.getRecents();
|
||||||
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
|
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
|
||||||
return new ItemList(recentItems);
|
return new ItemList(recentItems);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error reading recents for context {}",ScopeProvider.instance.get(),e);
|
log.error("jcr error getting recents", re);
|
||||||
throw new WebApplicationException("error reading recents",e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error getting recents", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new ItemList(recentItems);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -180,29 +209,98 @@ public class WorkspaceManager {
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
|
||||||
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getHomePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getHomePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
Item item = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Node folder = ses.getNode(trashPath.toPath());
|
Node folder = ses.getNode(trashPath.toPath());
|
||||||
Item item = ItemHandler.getItem(folder, excludes);
|
item = node2Item.getItem(folder, excludes);
|
||||||
|
}catch(RepositoryException re ){
|
||||||
return new ItemWrapper<Item>(item);
|
log.error("jcr error getting trash", re);
|
||||||
}catch(Throwable e){
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
log.error("error reading the node {}",trashPath,e);
|
}catch(StorageHubException she ){
|
||||||
throw new WebApplicationException("error retrieving trash folder",e);
|
log.error("error getting trash", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new ItemWrapper<Item>(item);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("trash/empty")
|
||||||
|
@DELETE
|
||||||
|
public String emptyTrash(){
|
||||||
|
InnerMethodName.instance.set("emptyTrash");
|
||||||
|
Session ses = null;
|
||||||
|
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getHomePath(), Constants.TRASH_ROOT_FOLDER_NAME);
|
||||||
|
String toReturn = null;
|
||||||
|
try{
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
Node trashNode = ses.getNode(trashPath.toPath());
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, trashNode.getIdentifier(), false);
|
||||||
|
List<Item> itemsToDelete = Utils.getItemList(trashNode, Excludes.ALL, null, true, null);
|
||||||
|
trashHandler.removeNodes(ses, itemsToDelete);
|
||||||
|
toReturn = trashNode.getIdentifier();
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("jcr error emptying trash", re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error emptying trash", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
}finally{
|
||||||
|
if (ses!=null)
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Consumes(MediaType.TEXT_PLAIN)
|
||||||
|
@Path("trash/restore")
|
||||||
|
public String restoreItem(String identifier){
|
||||||
|
InnerMethodName.instance.set("restoreItem");
|
||||||
|
Session ses = null;
|
||||||
|
String toReturn = null;
|
||||||
|
try{
|
||||||
|
|
||||||
|
log.info("restoring node with id {}", identifier);
|
||||||
|
|
||||||
|
//TODO check if it is possible to change all the ACL on a workspace
|
||||||
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
|
|
||||||
|
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
|
||||||
|
|
||||||
|
final Node nodeToRestore = ses.getNodeByIdentifier(identifier);
|
||||||
|
|
||||||
|
Item itemToRestore = node2Item.getItem(nodeToRestore, Excludes.ALL);
|
||||||
|
|
||||||
|
if (!(itemToRestore instanceof TrashItem))
|
||||||
|
throw new InvalidItemException("Only trash items can be restored");
|
||||||
|
|
||||||
|
toReturn = trashHandler.restoreItem(ses, (TrashItem)itemToRestore);
|
||||||
|
|
||||||
|
}catch(RepositoryException re ){
|
||||||
|
log.error("error restoring item with id {}",identifier, re);
|
||||||
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error restoring item with id {}",identifier, she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
|
} finally{
|
||||||
|
if (ses!=null) {
|
||||||
|
ses.logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Path("vrefolders")
|
@Path("vrefolders")
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -213,12 +311,14 @@ public class WorkspaceManager {
|
||||||
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false);
|
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("error reading the node children of {}",vrePath,e);
|
log.error("error reading the node children of {}",vrePath, re);
|
||||||
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("error reading the node children of {}",vrePath, she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -233,16 +333,17 @@ public class WorkspaceManager {
|
||||||
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
|
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
|
||||||
InnerMethodName.instance.set("getVreFoldersPaged");
|
InnerMethodName.instance.set("getVreFoldersPaged");
|
||||||
Session ses = null;
|
Session ses = null;
|
||||||
|
|
||||||
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
|
||||||
List<? extends Item> toReturn = null;
|
List<? extends Item> toReturn = null;
|
||||||
try{
|
try{
|
||||||
String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
||||||
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
||||||
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false);
|
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false, null);
|
||||||
}catch(Throwable e){
|
}catch(RepositoryException re ){
|
||||||
log.error("(paged) error reading the node children of {}",vrePath,e);
|
log.error("(paged) error reading the node children of {}",vrePath, re);
|
||||||
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
|
}catch(StorageHubException she ){
|
||||||
|
log.error("(paged) error reading the node children of {}",vrePath, she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
@ -266,13 +367,11 @@ public class WorkspaceManager {
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
|
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
|
||||||
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getHomePath()), expression));
|
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getHomePath()), expression));
|
||||||
//ADD ALSO LIMIT AND OFFSET
|
|
||||||
|
|
||||||
String orderBy = "";
|
String orderBy = "";
|
||||||
if (orderField!=null && orderField.size()>0)
|
if (orderField!=null && orderField.size()>0)
|
||||||
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
|
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
|
||||||
|
|
||||||
|
|
||||||
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
|
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
|
||||||
|
|
||||||
log.info("query sent is {}",sql2Query);
|
log.info("query sent is {}",sql2Query);
|
||||||
|
@ -293,12 +392,13 @@ public class WorkspaceManager {
|
||||||
NodeIterator it = result.getNodes();
|
NodeIterator it = result.getNodes();
|
||||||
|
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
toReturn.add(ItemHandler.getItem(it.nextNode(), null));
|
toReturn.add(node2Item.getItem(it.nextNode(), null));
|
||||||
|
}catch(RepositoryException | IOException re ){
|
||||||
|
log.error("error executing the query", re);
|
||||||
}catch(Throwable e){
|
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
|
||||||
log.error("error executing the query",e);
|
}catch(StorageHubException she ){
|
||||||
throw new WebServiceException("error executing the query", e);
|
log.error("error executing the query", she);
|
||||||
|
GXOutboundErrorResponse.throwException(she);
|
||||||
}finally{
|
}finally{
|
||||||
if (ses!=null)
|
if (ses!=null)
|
||||||
ses.logout();
|
ses.logout();
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
<param-name>admin-pwd</param-name>
|
<param-name>admin-pwd</param-name>
|
||||||
<param-value>gcube2010*onan</param-value>
|
<param-value>gcube2010*onan</param-value>
|
||||||
</context-param>
|
</context-param>
|
||||||
|
<context-param>
|
||||||
|
<param-name>resolver-basepath</param-name>
|
||||||
|
<param-value>https://data1-d.d4science.net/shub</param-value>
|
||||||
|
</context-param>
|
||||||
<servlet>
|
<servlet>
|
||||||
<servlet-name>org.gcube.data.access.storagehub.StorageHub</servlet-name>
|
<servlet-name>org.gcube.data.access.storagehub.StorageHub</servlet-name>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class Expressions {
|
||||||
@Inject
|
@Inject
|
||||||
Evaluators evaluators;
|
Evaluators evaluators;
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import javax.jcr.nodetype.NodeType;
|
||||||
|
|
||||||
import org.gcube.common.storagehub.model.items.Item;
|
import org.gcube.common.storagehub.model.items.Item;
|
||||||
import org.gcube.common.storagehub.model.types.ItemAction;
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
||||||
import org.gcube.data.access.storagehub.handlers.ItemHandler;
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -24,11 +24,6 @@ public class TestFields {
|
||||||
|
|
||||||
Logger logger = LoggerFactory.getLogger(TestFields.class);
|
Logger logger = LoggerFactory.getLogger(TestFields.class);
|
||||||
|
|
||||||
@Test
|
|
||||||
public void replace(){
|
|
||||||
System.out.println("/Home/Giancarlo".replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void iterateOverFields() throws Exception{
|
public void iterateOverFields() throws Exception{
|
||||||
|
|
||||||
|
@ -62,7 +57,7 @@ public class TestFields {
|
||||||
when(node.getParent()).thenReturn(parent);
|
when(node.getParent()).thenReturn(parent);
|
||||||
when(node.getProperty(anyString())).thenReturn(prop);
|
when(node.getProperty(anyString())).thenReturn(prop);
|
||||||
when(node.getNode(anyString())).thenReturn(node);
|
when(node.getNode(anyString())).thenReturn(node);
|
||||||
Item item = ItemHandler.getItem(node, Arrays.asList("hl:accounting","jcr:content"));
|
Item item = new Node2ItemConverter().getItem(node, Arrays.asList("hl:accounting","jcr:content"));
|
||||||
|
|
||||||
Assert.assertTrue(item.isShared());
|
Assert.assertTrue(item.isShared());
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@ import java.awt.image.DataBufferInt;
|
||||||
import java.awt.image.ImageObserver;
|
import java.awt.image.ImageObserver;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
|
||||||
|
@ -14,7 +16,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
public class TestNode {
|
public class TestNode {
|
||||||
|
|
||||||
@Test
|
/*@Test
|
||||||
public void testShared() throws Exception{
|
public void testShared() throws Exception{
|
||||||
|
|
||||||
BufferedImage buf = ImageIO.read(new File("/home/lucio/Downloads/djbattle.png"));
|
BufferedImage buf = ImageIO.read(new File("/home/lucio/Downloads/djbattle.png"));
|
||||||
|
@ -32,7 +34,9 @@ public class TestNode {
|
||||||
|
|
||||||
/*buffered.getGraphics().drawImage(image, 0, 0 , null);
|
/*buffered.getGraphics().drawImage(image, 0, 0 , null);
|
||||||
ImageIO.write(buffered, "png", buffer );
|
ImageIO.write(buffered, "png", buffer );
|
||||||
byte[] imageInByte = buffer.toByteArray();*/
|
byte[] imageInByte = buffer.toByteArray();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue