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:
Lucio Lelii 2018-10-25 14:33:23 +00:00
parent 6185b1563b
commit 70581080f4
28 changed files with 2318 additions and 983 deletions

34
pom.xml
View File

@ -47,12 +47,12 @@
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
<groupId>org.gcube.core</groupId>
<artifactId>common-smartgears</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>common-authorization</artifactId>
@ -85,17 +85,17 @@
<version>5.5.6</version>
</dependency>
<dependency>
<groupId>gov.nih.imagej</groupId>
<artifactId>imagej</artifactId>
<version>1.47</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>gxRest</artifactId>
<version>[1.0.0-SNAPSHOT,2.0.0-SNAPSHOT)</version>
</dependency>
<!-- JCR dependencies -->
<dependency>
@ -214,9 +214,21 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-simple</artifactId>

View File

@ -1,10 +1,9 @@
package org.gcube.data.access.storagehub;
import static org.gcube.common.storagehub.model.NodeConstants.*;
import java.util.Arrays;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.Privilege;
@ -12,70 +11,124 @@ import javax.jcr.security.Privilege;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.Excludes;
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.SharedFolder;
import org.gcube.data.access.storagehub.handlers.ItemHandler;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
@Singleton
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);
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()) {
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
if (!parentShared.getUsers().getValues().containsKey(AuthorizationProvider.instance.get().getClient().getId()))
throw new IllegalAccessException("Insufficent Provileges to read node with id "+id);
} else if (!item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
throw new IllegalAccessException("Insufficent Provileges to read node with id "+id);
SharedFolder parentShared = node2Item.getItem(retrieveSharedFolderParent(node, session), Excludes.EXCLUDE_ACCOUNTING);
if (!parentShared.getUsers().getValues().containsKey(login))
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
} else if (!item.getOwner().equals(login))
throw new UserNotAuthorizedException("Insufficent Provileges for user "+login+" to read node with id "+id);
}
private SharedFolder retrieveSharedFolderParent(Item item, Session session) throws Exception{
if (item instanceof SharedFolder) return (SharedFolder)item;
private Node retrieveSharedFolderParent(Node node, Session session) throws BackendGenericError, RepositoryException{
if (node2Item.checkNodeType(node, SharedFolder.class)) return node;
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
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()) {
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentShared.getPath());
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(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()){
AccessType access = AccessType.fromValue(privilege.getName());
if (isNewItem && access!=AccessType.READ_ONLY)
return;
else
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;
}
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
if(item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
if(item.getOwner().equals(login))
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) {
Node nodeOwner;

View File

@ -19,4 +19,6 @@ public class Constants {
public static final String ADMIN_PARAM_PWD ="admin-pwd";
public static final List<String> FOLDERS_TO_EXLUDE = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
public static final List<String> PROTECTED_FOLDER = Arrays.asList(Constants.VRE_FOLDER_PARENT_NAME, Constants.TRASH_ROOT_FOLDER_NAME);
}

View File

@ -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;
}
}

View File

@ -19,16 +19,16 @@ public class MultipleOutputStream {
private MyPipedOututStream[] pipedOutStreams;
private int index=0;
public MultipleOutputStream(InputStream is, int number) throws IOException{
this.is = is;
logger.debug("requested {} piped streams ",number);
pipedInStreams = new MyPipedInputStream[number];
pipedOutStreams = new MyPipedOututStream[number];
for (int i =0; i<number; i++) {
pipedOutStreams[i] = new MyPipedOututStream();
pipedInStreams[i] = new MyPipedInputStream(pipedOutStreams[i]);
@ -36,34 +36,35 @@ public class MultipleOutputStream {
}
public void startWriting() throws Exception{
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);
}
}
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();
public void startWriting() throws IOException{
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buf = new byte[1024*64];
int read=-1;
int writeTot = 0;
while ((read =bis.read(buf))!=-1){
for (int i=0; i< pipedInStreams.length; i++) {
if (!pipedInStreams[i].isClosed()) {
pipedOutStreams[i].write(buf, 0, read);
}
}
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);
}
@ -80,7 +81,7 @@ public class MultipleOutputStream {
if (index>=pipedInStreams.length) return null;
return pipedInStreams[index++];
}
public class MyPipedOututStream extends PipedOutputStream{

View File

@ -1,37 +1,46 @@
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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
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.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
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.contentmanager.storageclient.wrapper.AccessType;
import org.gcube.contentmanager.storageclient.wrapper.MemoryType;
import org.gcube.contentmanager.storageclient.wrapper.StorageClient;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.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.LoggerFactory;
@ -40,7 +49,7 @@ public class Utils {
public final static String SERVICE_NAME = "home-library";
public final static String SERVICE_CLASS = "org.gcube.portlets.user";
private static final String FOLDERS_TYPE = "nthl:workspaceItem";
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
public static String getSecurePassword(String user) throws Exception {
@ -61,54 +70,48 @@ public class Utils {
}
return digest;
}
public static long getItemCount(Node parent, boolean showHidden) throws Exception{
NodeIterator iterator = parent.getNodes();
long count=0;
while (iterator.hasNext()){
Node current = iterator.nextNode();
if (isToExclude(current, showHidden))
continue;
count++;
}
return count;
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
}
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>();
long start = System.currentTimeMillis();
NodeIterator iterator = parent.getNodes();
logger.trace("time to get iterator {}",(System.currentTimeMillis()-start));
logger.trace("nodeType is {}",nodeTypeToInclude);
int count =0;
logger.trace("selected range is {}", range);
Node2ItemConverter node2Item= new Node2ItemConverter();
while (iterator.hasNext()){
Node current = iterator.nextNode();
if (isToExclude(current, showHidden))
continue;
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);
}
count++;
}
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:"))) ||
(!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())));
(!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())));
}
public static org.gcube.common.storagehub.model.Path getHomePath(){
return Paths.getPath(String.format("/Home/%s/Workspace",AuthorizationProvider.instance.get().getClient().getId()));
}
@ -116,21 +119,22 @@ public class Utils {
public static org.gcube.common.storagehub.model.Path getHomePath(String login){
return Paths.getPath(String.format("/Home/%s/Workspace",login));
}
public static StorageClient getStorageClient(String login){
return new StorageClient(SERVICE_CLASS, SERVICE_NAME, login, AccessType.SHARED, MemoryType.PERSISTENT);
}
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>();
Node currentNode = session.getNodeByIdentifier(directory.getId());
queue.push(directory);
Deque<Item> tempQueue = new LinkedList<Item>();
logger.debug("adding directory {}",directory.getPath());
for (Item item : Utils.getItemList(currentNode,null, null, false)){
logger.debug("adding directory {}",currentNode.getPath());
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
if (excludes.contains(item.getId())) continue;
if (item instanceof FolderItem)
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler));
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, accountingHandler, excludes));
else if (item instanceof AbstractFileItem){
logger.debug("adding file {}",item.getPath());
AbstractFileItem fileItem = (AbstractFileItem) item;
@ -150,31 +154,39 @@ public class Utils {
Item item = queue.pop();
if (item instanceof FolderItem) {
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("/", "");
logger.trace("writing dir {}",name);
zos.putNextEntry(new ZipEntry(name));
zos.closeEntry();
} 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);
logger.debug("writing dir {}",name);
if (name.isEmpty()) continue;
try {
zos.putNextEntry(new ZipEntry(name));
copyStream(is, zos);
}catch (Exception e) {
logger.warn("error writing item {}", item.getName(),e);
} finally{
}finally {
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 {
@ -184,14 +196,127 @@ public class Utils {
out.write(buffer, 0, readcount);
}
}
public static boolean hasSharedChildren(FolderItem item, Session session) throws Exception{
Node currentNode = session.getNodeByIdentifier(item.getId());
for (Item children : Utils.getItemList(currentNode,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME), null, false)){
if (children instanceof FolderItem)
return (children instanceof SharedFolder) || hasSharedChildren((FolderItem)children, session);
public static boolean hasSharedChildren(Node node) throws RepositoryException, BackendGenericError{
Node2ItemConverter node2Item = new Node2ItemConverter();
NodeIterator children = node.getNodes();
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;
}
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());
}
}

View File

@ -29,6 +29,10 @@ public class AccountingHandler {
private static final String ITEM_TYPE = "hl:itemType";
private static final String MIME_TYPE = "hl:mimeType";
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);
@ -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 {
if (!sharedNode.hasNode(NodeProperty.ACCOUNTING.toString())){
@ -131,4 +135,44 @@ public class AccountingHandler {
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);
}
}
}

View File

@ -14,13 +14,21 @@ public class ClassHandler {
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 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>();
public ClassHandler() {
private ClassHandler() {
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
for (Class<?> clazz: classesAnnotated ){

View File

@ -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;
}
}
}

View File

@ -10,9 +10,9 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
@ -20,52 +20,59 @@ import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import org.apache.commons.io.IOUtils;
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.NodeConstants;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.annotations.Attribute;
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
import org.gcube.common.storagehub.model.annotations.ListNodes;
import org.gcube.common.storagehub.model.annotations.MapAttribute;
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
import org.gcube.common.storagehub.model.annotations.RootNode;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
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.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ItemHandler {
private static final Logger logger = LoggerFactory.getLogger(ItemHandler.class);
private static ClassHandler classHandler = new ClassHandler();
@Singleton
public class Node2ItemConverter {
private static final Logger logger = LoggerFactory.getLogger(Node2ItemConverter.class);
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")
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.setName(Text.unescapeIllegalJcrChars(node.getName()));
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
item.setLocked(node.isLocked());
item.setPrimaryType(node.getPrimaryNodeType().getName());
Item parent = null ;
@ -74,7 +81,7 @@ public class ItemHandler {
item.setShared(true);
}else {
try {
parent = ItemHandler.getItem(node.getParent(), Arrays.asList("hl:accounting","jcr:content"));
parent = getItem(node.getParent(), Excludes.ALL);
item.setShared(parent.isShared());
} catch(Exception e) {
item.setShared(false);
@ -86,7 +93,7 @@ public class ItemHandler {
else {
try {
if (parent==null)
parent = ItemHandler.getItem(node.getParent(), Arrays.asList("hl:accounting","jcr:content"));
parent = getItem(node.getParent(), Excludes.ALL);
item.setTrashed(parent.isTrashed());
} catch(Exception e) {
item.setTrashed(false);
@ -107,7 +114,7 @@ public class ItemHandler {
try{
Class<?> returnType = field.getType();
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
logger.debug("retrieve item - added field {}",field.getName());
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) {
@ -132,10 +139,11 @@ public class ItemHandler {
}
}
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();
for (Field field : retrieveAllFields(clazz)){
if (field.isAnnotationPresent(Attribute.class)){
@ -148,7 +156,7 @@ public class ItemHandler {
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) {
logger.warn("error setting value",e);
logger.warn("error setting value {}",e.getMessage());
}
} else if (field.isAnnotationPresent(MapAttribute.class)){
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
@ -162,12 +170,12 @@ public class ItemHandler {
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
try{
logger.trace("adding {} in the map",prop.getName());
mapToset.put(prop.getName(), getPropertyValue(prop));
}catch(PathNotFoundException e){
logger.warn("the property {} is not mapped",prop.getName(),e);
logger.warn("the property {} is not mapped",prop.getName());
} 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" })
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.isEnum()) return Enum.valueOf(returnType, prop.getString());
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.isArray()) {
if (prop.getType()==PropertyType.BINARY) {
byte[] bytes = new byte[32000];
try (InputStream stream = prop.getBinary().getStream()){
stream.read(bytes);
}
byte[] bytes = IOUtils.toByteArray(prop.getBinary().getStream());
return bytes;
} else {
Object[] ret= getArrayValue(prop);
@ -255,59 +259,6 @@ public class ItemHandler {
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){
Set<Field> fields = new HashSet<Field>();
@ -318,124 +269,46 @@ public class ItemHandler {
}while ((currentClass =currentClass.getSuperclass())!=null);
return fields;
}
private 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());
public static <T extends Item> Node createNodeFromItem(Session session, Node parentNode, T item){
}
private 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 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 {
//TODO: must understand this place is for name or title
String primaryType= classHandler.getNodeType(item.getClass());
Node newNode = parentNode.addNode(item.getTitle(), 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();
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{
AttributeRootNode attributeRootNode = object.getClass().getAnnotation(AttributeRootNode.class);
Node newNode = parentNode.addNode(nodeName, attributeRootNode.value());
//newNode.setPrimaryType(attributeRootNode.value());
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();
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++));
}
}
return (node.isNodeType(ClassHandler.instance().getNodeType(classToCompare)));
}catch (Throwable e) {
throw new BackendGenericError(e);
}
}
public static <F extends AbstractFileItem> void replaceContent(Session session, Node node, F item){
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(), 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);
}
}
}

View File

@ -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();
}
}

View File

@ -7,6 +7,7 @@ import java.util.concurrent.Future;
import javax.jcr.Repository;
import javax.jcr.SimpleCredentials;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.Item;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,12 +15,12 @@ import org.slf4j.LoggerFactory;
public class VRE {
private static final Logger logger = LoggerFactory.getLogger(VRE.class);
private Item vreFolder;
private Future<List<Item>> result;
private VREQueryRetriever vreQueryRetriever;
private ExecutorService executor;
public VRE(Item item, Repository repository, SimpleCredentials credentials, ExecutorService executor) {
super();
this.vreFolder = item;
@ -27,20 +28,24 @@ public class VRE {
vreQueryRetriever = new VREQueryRetriever(repository, credentials, vreFolder);
result = executor.submit(vreQueryRetriever);
}
public Item getVreFolder() {
return vreFolder;
}
public synchronized List<Item> getRecents() throws Exception{
logger.trace("getting recents");
if (result.isDone()) {
result = executor.submit(vreQueryRetriever);
public synchronized List<Item> getRecents() throws BackendGenericError{
try {
logger.trace("getting recents");
if (result.isDone()) {
result = executor.submit(vreQueryRetriever);
}
return result.get();
}catch(Exception ee) {
throw new BackendGenericError(ee);
}
return result.get();
}
}

View File

@ -17,6 +17,7 @@ import javax.jcr.observation.Event;
import javax.jcr.observation.EventJournal;
import javax.jcr.query.Query;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
@ -28,13 +29,15 @@ public class VREQueryRetriever implements Callable<List<Item>> {
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
private static final int CACHE_DIMENSION = 50;
private Repository repository;
private Credentials credentials;
private Item vreFolder;
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
long lastTimestamp =0;
private Node2ItemConverter node2Item = new Node2ItemConverter();
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
super();
@ -59,7 +62,7 @@ public class VREQueryRetriever implements Callable<List<Item>> {
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
while (it.hasNext()) {
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);
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());
if (nodeAdded.isNodeType("nthl:workspaceLeafItem")) {
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);
}
}
@ -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());
String identifier = property.getParent().getIdentifier();
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);
}
}

View File

@ -13,7 +13,6 @@ import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.core.version.VersionManagerImplBase;
import org.gcube.common.storagehub.model.NodeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -7,7 +7,7 @@ import org.gcube.common.storagehub.model.items.nodes.Content;
public interface ContentHandler {
void initiliseSpecificContent(InputStream is) throws Exception;
void initiliseSpecificContent(InputStream is, String fileName) throws Exception;
Content getContent();

View File

@ -12,7 +12,7 @@ public class GenericFileHandler implements ContentHandler{
Content content = new Content();
@Override
public void initiliseSpecificContent(InputStream is) throws Exception {}
public void initiliseSpecificContent(InputStream is, String filename) throws Exception {}
@Override
public Content getContent() {

View File

@ -1,57 +1,55 @@
package org.gcube.data.access.storagehub.handlers.content;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Calendar;
import javax.imageio.ImageIO;
import org.apache.commons.io.FilenameUtils;
import org.gcube.common.storagehub.model.annotations.MimeTypeHandler;
import org.gcube.common.storagehub.model.items.ImageFile;
import org.gcube.common.storagehub.model.items.nodes.ImageContent;
import org.gcube.common.storagehub.model.types.ItemAction;
import ij.ImagePlus;
import ij.io.FileSaver;
import ij.process.ImageProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@MimeTypeHandler({"image/gif", "image/jpeg","image/png","image/svg+xml"})
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 static final Logger logger = LoggerFactory.getLogger(ImageHandler.class);
@Override
public void initiliseSpecificContent(InputStream is) throws Exception {
BufferedImage buf = ImageIO.read(is);
content.setWidth(Long.valueOf(buf.getWidth()));
content.setHeight(Long.valueOf(buf.getHeight()));
ImagePlus image = new ImagePlus("thumbnail", buf);
int thumbSize[] = getThumbnailDimension(buf.getWidth(), buf.getHeight());
try(ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream thumbstream = getThumbnailAsPng(image, thumbSize[0], thumbSize[1])){
public void initiliseSpecificContent(InputStream is, String fileName) throws Exception {
Image image = javax.imageio.ImageIO.read(is);
byte[] imgbuf = new byte[1024];
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.setThumbnailData(Base64.getEncoder().encode(baos.toByteArray()));
} catch (Exception e) {
// TODO: handle exception
}
int width = image.getWidth(null);
int height = image.getHeight(null);
content.setWidth(Long.valueOf(width));
content.setHeight(Long.valueOf(height));
try {
int[] dimension = getThumbnailDimension(width, height);
byte[] buf = transform(image, fileName, dimension[0], dimension[1]).toByteArray();
content.setThumbnailHeight(Long.valueOf(dimension[1]));
content.setThumbnailWidth(Long.valueOf(dimension[0]));
content.setThumbnailData(buf);
}catch(Throwable t) {
logger.warn("thumbnail for file {} cannot be created ", fileName,t);
}
}
@ -93,29 +91,6 @@ public class ImageHandler implements ContentHandler{
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
public ImageFile buildItem(String name, String description, String login) {
ImageFile item = new ImageFile();
@ -133,4 +108,28 @@ public class ImageHandler implements ContentHandler{
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;
}
}

View File

@ -24,7 +24,7 @@ public class PdfHandler implements ContentHandler {
@Override
public void initiliseSpecificContent(InputStream is) throws Exception {
public void initiliseSpecificContent(InputStream is, String fileName) throws Exception {
PdfReader reader = new PdfReader(is);
content.setNumberOfPages(Long.valueOf(reader.getNumberOfPages()));
content.setVersion(String.valueOf(reader.getPdfVersion()));

View File

@ -1,10 +1,12 @@
package org.gcube.data.access.storagehub.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
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.MediaType;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
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.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.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
@ -72,15 +78,18 @@ public class ACLManager {
acl.setAccessTypes(types);
acls.add(acl);
}
return new ACLList(acls);
}catch (Exception e) {
log.error("error gettign ACL",e);
throw new WebApplicationException(e);
}catch(RepositoryException 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 new ACLList(acls);
}

View File

@ -1,12 +1,16 @@
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 javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.security.AccessControlEntry;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.ServletContext;
@ -15,25 +19,34 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.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.Paths;
import org.gcube.common.storagehub.model.acls.AccessType;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.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.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.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.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.smartgears.utils.InnerMethodName;
import org.glassfish.jersey.media.multipart.FormDataParam;
@ -63,111 +76,350 @@ public class ItemSharing {
@Inject
VersionHandler versionHandler;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@PUT
@Path("{id}/share")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String share(@FormDataParam("users") Set<String> users, @FormDataParam("defaultAccessType") AccessType accessType){
InnerMethodName.instance.set("findChildrenByNamePattern");
InnerMethodName.instance.set("shareFolder");
Session ses = null;
String toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkWriteAuthorizationControl(ses, id, false);
Item item = ItemHandler.getItem(ses.getNodeByIdentifier(id), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.CONTENT_NAME, NodeConstants.METADATA_NAME));
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");
//Item item = node2Item.getItem(ses.getNodeByIdentifier(id), Excludes.ALL);
if (accessType==null)
accessType = AccessType.READ_ONLY;
if (users.isEmpty())
throw new Exception("users is empty");
String sharedFolderName = item.getId();
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");
if (users==null || users.isEmpty())
throw new InvalidCallParameters("users is empty");
Node nodeToShare = ses.getNodeByIdentifier(id);
boolean alreadyShared = false;
Node sharedFolderNode;
if (!node2Item.checkNodeType(nodeToShare, SharedFolder.class))
sharedFolderNode= shareFolder(nodeToShare, ses);
else {
sharedFolderNode = nodeToShare;
alreadyShared = true;
}
ses.save();
ses.getWorkspace().getLockManager().lock(newNodePath, true, true, 0,login);
ses.getWorkspace().getLockManager().lock(sharedFolderNode.getPath(), true, true, 0,login);
try {
AccessControlManager acm = ses.getAccessControlManager();
JackrabbitAccessControlList acls = AccessControlUtils.getAccessControlList(acm, sharedFolderNode.getPath());
//setting data for ADMINISTRATOR
org.gcube.common.storagehub.model.Path adminFolderPath = Paths.append(Utils.getHomePath(), item.getName());
log.debug("trying to clone dir from {} to {}", sharedFolderNode.getPath(), adminFolderPath.toPath());
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);
}
if (!alreadyShared) {
Privilege[] adminPrivileges = new Privilege[] { acm.privilegeFromName(AccessType.ADMINISTRATOR.getValue()) };
addUserToSharing(sharedFolderNode, ses, login, adminPrivileges, acls);
users.remove(login);
}
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);
accountingHandler.shareFolder(item.getTitle(), users, ses, sharedFolderNode, false);
accountingHandler.createShareFolder(sharedFolderNode.getProperty(NodeProperty.TITLE.toString()).getString(), users, ses, sharedFolderNode, false);
ses.save();
return sharedFolderNode.getIdentifier();
toReturn = sharedFolderNode.getIdentifier();
} finally {
ses.getWorkspace().getLockManager().unlock(newNodePath);
ses.getWorkspace().getLockManager().unlock(sharedFolderNode.getPath());
}
}catch(Throwable e){
log.error("error sharing node with id {}",id,e);
throw new WebApplicationException(e);
}catch(RepositoryException re){
log.error("jcr sharing", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
}catch(StorageHubException she ){
log.error("error sharing", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
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;
}
}

View File

@ -1,49 +1,67 @@
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.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.storagehub.model.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.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.items.Item;
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.MetaInfo;
import org.gcube.data.access.storagehub.MultipleOutputStream;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.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.content.ContentHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
@ -78,237 +96,318 @@ public class ItemsCreator {
@Inject
AccountingHandler accountingHandler;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
@POST
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("/{id}/create/FOLDER")
public Response createItem(@PathParam("id") String id, @PathParam("type") String type,@QueryParam("name") String name, @QueryParam("description") String description){
InnerMethodName.instance.set(String.format("createItem(%s)",type));
log.info("create generic item called");
public String createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description) {
InnerMethodName.instance.set("createItem(FOLDER)");
log.info("create folder item called");
Session ses = null;
Item destinationItem = null;
String toReturn = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
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));
//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));
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");
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,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());
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();
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.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
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
@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("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition fileDetail){
InnerMethodName.instance.set("createItem(FILE)");
Session ses = null;
Item destinationItem = null;
String toReturn = null;
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();
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
//TODO: validate input parameters for Item Type
Node destination = ses.getNodeByIdentifier(id);
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
if (!(destinationItem instanceof FolderItem)) throw new Exception("an Item must be copyed to another directory");
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, 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");
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
Node newNode;
try {
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationItem.getPath()), name).toPath());
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);
newNode = createFileItemInternally(ses, destination, stream, name, description, login);
ses.save();
} finally {
ses.getWorkspace().getLockManager().unlock(destination.getPath());
}
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
ses.save();
versionHandler.checkinContentNode(newNode, ses);
log.info("file with id {} correctly created",newNode.getIdentifier());
return Response.ok(newNode.getIdentifier()).build();
}catch(Throwable e){
log.error("error creating item", e);
return Response.serverError().build();
toReturn = newNode.getIdentifier();
}catch(RepositoryException re ){
log.error("jcr error creating file item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re));
}catch(StorageHubException she ){
log.error("error creating file item", she);
GXOutboundErrorResponse.throwException(she);
} 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);
}
if (ses!=null)
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
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
@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") FormDataContentDisposition fileDetail){
InnerMethodName.instance.set("createItem(FILE)");
InnerMethodName.instance.set("createItem(ARCHIVE)");
Session ses = null;
Item destinationItem = null;
String toReturn = null;
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();
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
//TODO: validate input parameters for Item Type
Node destination = ses.getNodeByIdentifier(id);
if (!node2Item.checkNodeType(destination, FolderItem.class))
throw new InvalidItemException("the destination item is not a folder");
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier() , true);
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
if (!(destinationItem instanceof FolderItem)) throw new Exception("destination item is not a folder");
ses.getWorkspace().getLockManager().lock(destination.getPath(), true, true, 0,login);
Node parentDirectoryNode = null;
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, 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;
try {
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationItem.getPath()), name).toPath());
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);
}
parentDirectoryNode = Utils.createFolderInternally(ses, destination, parentFolderName, "", login, accountingHandler);
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
Set<Node> fileNodes = new HashSet<>();
ses.save();
versionHandler.checkinContentNode(newNode, ses);
log.info("file with id {} correctly created",newNode.getIdentifier());
return Response.ok(newNode.getIdentifier()).build();
}catch(Throwable e){
log.error("error creating item", e);
return Response.serverError().build();
} 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);
HashMap<String, Node> directoryNodeMap = new HashMap<>();
try (ArchiveInputStream input = new ArchiveStreamFactory()
.createArchiveInputStream(new BufferedInputStream(stream, 1024*64))){
ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {
if (entry.isDirectory()) {
String entirePath = entry.getName();
String name = entirePath.replaceAll("(.*/)*(.*)/", "$2");
String parentPath = entirePath.replaceAll("(.*/)*(.*)/", "$1");
log.debug("creating directory with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
Node createdNode;
if (parentPath.isEmpty()) {
createdNode = Utils.createFolderInternally(ses, parentDirectoryNode, name, "", 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>() {
@ -317,7 +416,7 @@ public class ItemsCreator {
ContentHandler handler =null;
long start = System.currentTimeMillis();
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;
TikaConfig config = TikaConfig.getDefaultConfig();
Detector detector = config.getDetector();
@ -330,7 +429,7 @@ public class ItemsCreator {
handler = contenthandlerFactory.create(mimeType);
is1.reset();
handler.initiliseSpecificContent(is1);
handler.initiliseSpecificContent(is1, name);
handler.getContent().setMimeType(mimeType);
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
} catch (Throwable e) {
@ -346,17 +445,22 @@ public class ItemsCreator {
@Override
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();
log.debug("TIMING: sending the content to Storage - start");
String remotePath= path+"/"+name;
String storageId = Utils.getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().put(true).LFile(mos.get()).RFile(remotePath);
long size = Utils.getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().getSize().RFileById(storageId);
IClient storageClient = Utils.getStorageClient(login).getClient();
log.debug("TIMING: getting the client took {} ",System.currentTimeMillis()-start);
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();
info.setSize(size);
info.setStorageId(storageId);
info.setRemotePath(remotePath);
log.debug("TIMING: sending the content to Storage - finished in {}",System.currentTimeMillis()-start);
return info;
}catch (Throwable e) {
log.error("error writing content");
@ -366,21 +470,25 @@ public class ItemsCreator {
}
};
Future<ContentHandler> detectorF = executor.submit(mimeTypeDector);
Future<MetaInfo> uploaderF = executor.submit(uploader);
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
long start = System.currentTimeMillis();
log.debug("TIMING: writing the strem - start");
mos.startWriting();
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
ContentHandler handler = detectorF.get();
MetaInfo info = uploaderF.get();
handler.getContent().setData("jcr:content");
handler.getContent().setStorageId(info.getStorageId());
handler.getContent().setSize(info.getSize());
handler.getContent().setRemotePath(info.getRemotePath());
return handler;
log.debug("TIMING: writing the stream - start");
try {
mos.startWriting();
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
ContentHandler handler = detectorF.get();
MetaInfo info = uploaderF.get();
handler.getContent().setData(NodeConstants.CONTENT_NAME);
handler.getContent().setStorageId(info.getStorageId());
handler.getContent().setSize(info.getSize());
handler.getContent().setRemotePath(info.getRemotePath());
return handler;
}catch (Exception e) {
throw new BackendGenericError(e);
}
}

View File

@ -2,17 +2,15 @@ package org.gcube.data.access.storagehub.services;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.zip.Deflater;
import java.util.zip.ZipOutputStream;
@ -20,43 +18,55 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.version.Version;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.io.FilenameUtils;
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.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.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
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.service.ItemList;
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.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.Constants;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.SingleFileStreamingOutput;
import org.gcube.data.access.storagehub.Utils;
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.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.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
@ -85,7 +95,13 @@ public class ItemsManager {
@Inject
VersionHandler versionHandler;
@Inject
TrashHandler trashHandler;
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
@ -96,10 +112,13 @@ public class ItemsManager {
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
toReturn = ItemHandler.getItem(ses.getNodeByIdentifier(id), excludes);
}catch(Throwable e){
log.error("error reading the node children of {}",id,e);
throw new WebApplicationException(e);
toReturn = node2Item.getItem(ses.getNodeByIdentifier(id), excludes);
}catch(RepositoryException re){
log.error("jcr error getting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
}catch(StorageHubException she ){
log.error("error getting item", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -120,10 +139,13 @@ public class ItemsManager {
authChecker.checkReadAuthorizationControl(ses, id);
NodeIterator it = ses.getNodeByIdentifier(id).getNodes(name);
while (it.hasNext())
toReturn.add(ItemHandler.getItem(it.nextNode(), excludes));
}catch(Throwable e){
log.error("error reading the node children of {} with name pattern",id,name,e);
throw new WebApplicationException(e);
toReturn.add(node2Item.getItem(it.nextNode(), excludes));
}catch(RepositoryException re){
log.error("jcr error searching item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error searching item", re));
}catch(StorageHubException she ){
log.error("error searching item", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -131,22 +153,27 @@ public class ItemsManager {
return new ItemList(toReturn);
}
@GET
@Path("{id}/children/count")
@Produces(MediaType.APPLICATION_JSON)
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes){
public Long countById(@QueryParam("showHidden") Boolean showHidden, @QueryParam("exclude") List<String> excludes, @QueryParam("onlyType") String nodeType){
InnerMethodName.instance.set("countById");
Session ses = null;
Long toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden);
}catch(Throwable e){
log.error("error reading the node children of {}",id,e);
throw new WebApplicationException(e);
toReturn = Utils.getItemCount(ses.getNodeByIdentifier(id), showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch(RuntimeException | RepositoryException re){
log.error("jcr error counting item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error counting item", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -157,17 +184,20 @@ public class ItemsManager {
@GET
@Path("{id}/children")
@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");
Session ses = null;
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden);
}catch(Throwable e){
log.error("error reading the node children of {}",id,e);
throw new WebApplicationException(e);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, null, showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch(RepositoryException re){
log.error("jcr error getting children", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting children", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -179,17 +209,20 @@ public class ItemsManager {
@GET
@Path("{id}/children/paged")
@Produces(MediaType.APPLICATION_JSON)
public ItemList listByIdPaged(@QueryParam("showHidden") Boolean showHidden, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("exclude") List<String> excludes){
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");
Session ses = null;
List<? extends Item> toReturn = null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden);
}catch(Throwable e){
log.error("error reading the node children of {}",id,e);
throw new WebApplicationException(e);
toReturn = Utils.getItemList(ses.getNodeByIdentifier(id), excludes, new Range(start, limit),showHidden==null?false:showHidden, nodeType!=null ? ClassHandler.instance().get(nodeType) : null);
}catch(RepositoryException re){
log.error("jcr error getting paged children", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting paged children", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -199,32 +232,68 @@ public class ItemsManager {
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}/publiclink")
public URL getPubliclink() {
public URL getPublicLink(@QueryParam("version") String version) {
InnerMethodName.instance.set("getPubliclink");
//TODO: check who can call this method
Session ses = null;
URL toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
Item item = ItemHandler.getItem(ses.getNodeByIdentifier(id), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
Node selectedNode = ses.getNodeByIdentifier(id);
Item item = node2Item.getItem(selectedNode, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME));
if (!(item instanceof AbstractFileItem)) throw new Exception("the select item is not a File");
if (!(item instanceof AbstractFileItem)) throw new InvalidCallParameters("the choosen item is not a File");
AbstractFileItem fileItem = (AbstractFileItem) item;
if (version!=null) {
boolean versionFound = false;
VersionList versions = getVersions();
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);
String url = Utils.getStorageClient(login).getClient().getHttpsUrl().RFileById(fileItem.getContent().getStorageId());
return new URL(url);
}catch(Throwable e){
log.error("error reading the node children of {}",id,e);
throw new WebApplicationException(e);
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{
if (ses!=null)
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
@ -233,26 +302,128 @@ public class ItemsManager {
public ItemWrapper<Item> getRootSharedFolder(@QueryParam("exclude") List<String> excludes){
InnerMethodName.instance.set("getRootSharedFolder");
Session ses = null;
Item sharedParent= null;
try{
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
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())
throw new RuntimeException("this item is not shared");
log.trace("current node is {}",currentItem.getPath());
while (!(currentItem instanceof SharedFolder ))
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(currentItem.getParentId()), Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME, NodeConstants.CONTENT_NAME));
throw new InvalidItemException("this item is not shared");
log.trace("current node is {}",currentNode.getPath());
return new ItemWrapper<Item>(currentItem);
}catch(Throwable e){
log.error("error retrieving shared root folder of node with id {}",id,e);
throw new WebApplicationException(e);
while (!node2Item.checkNodeType(currentNode, SharedFolder.class))
currentNode = currentNode.getParent();
sharedParent = node2Item.getItem(currentNode, excludes);
}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{
if (ses!=null)
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
@ -267,26 +438,32 @@ public class ItemsManager {
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
authChecker.checkReadAuthorizationControl(ses, id);
Item currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(id), excludes);
log.trace("current node is {}",currentItem.getPath());
while (!(currentItem.getPath()+"/").equals(absolutePath.toPath())) {
Node currentNode = ses.getNodeByIdentifier(id);
Item currentItem = node2Item.getItem(currentNode, excludes);
log.trace("current node is {}",currentNode.getPath());
while (!(currentNode.getPath()+"/").equals(absolutePath.toPath())) {
if (currentItem instanceof SharedFolder){
Map<String, Object> users = ((SharedFolder) currentItem).getUsers().getValues();
String[] user = ((String)users.get(login)).split("/");
String parentId = user[0];
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(parentId), excludes);
currentNode = ses.getNodeByIdentifier(parentId);
currentItem = node2Item.getItem(currentNode, excludes);
}else
currentItem = ItemHandler.getItem(ses.getNodeByIdentifier(currentItem.getParentId()), excludes);
}else {
currentNode = currentNode.getParent();
currentItem = node2Item.getItem(currentNode, excludes);
}
log.trace("current node is {}",currentItem.getPath());
log.trace("current node is {}",currentNode.getPath());
toReturn.add(currentItem);
}
}catch(Throwable e){
log.error("error retrieving parents of node with id {}",id,e);
throw new WebApplicationException(e);
}catch(RepositoryException re ){
log.error("jcr error getting anchestors", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting anchestors", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -297,20 +474,21 @@ public class ItemsManager {
return new ItemList(toReturn);
}
@GET
@Path("{id}/download")
public Response download(){
public Response download(@QueryParam("exclude") List<String> excludes){
InnerMethodName.instance.set("downloadById");
Session ses = null;
Response response = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
final Node node = ses.getNodeByIdentifier(id);
authChecker.checkReadAuthorizationControl(ses, id);
final Item item = ItemHandler.getItem(node, null);
final Item item = node2Item.getItem(node, null);
if (item instanceof AbstractFileItem){
AbstractFileItem fileItem =(AbstractFileItem) item;
@ -320,17 +498,18 @@ public class ItemsManager {
StreamingOutput so = new SingleFileStreamingOutput(streamToWrite);
return Response
response = Response
.ok(so)
.header("content-disposition","attachment; filename = "+fileItem.getName())
.header("content-disposition","attachment; filename = \""+fileItem.getName()+"\"")
.header("Content-Length", fileItem.getContent().getSize())
.header("Content-Type", fileItem.getContent().getMimeType())
.build();
} else if (item instanceof FolderItem){
try {
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler);
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getPath());
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, accountingHandler, excludes);
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
StreamingOutput so = new StreamingOutput() {
@Override
@ -349,30 +528,103 @@ public class ItemsManager {
}
};
return Response
response = Response
.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)
.build();
}finally {
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 ){
log.error("error downloading item content",e);
throw new WebApplicationException(e);
}catch(RepositoryException re ){
log.error("jcr error download", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error download", she);
GXOutboundErrorResponse.throwException(she);
} finally{
if (ses!=null) ses.logout();
}
return response;
}
@PUT
@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");
//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;
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{
final String login = AuthorizationProvider.instance.get().getClient().getId();
//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));
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);
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())
throw new Exception("shared folder cannot be moved or cannot not move hidden item");
if (Constants.FOLDERS_TO_EXLUDE.contains(item.getTitle()) || Constants.FOLDERS_TO_EXLUDE.contains(destinationItem.getTitle()))
throw new Exception("protected folder cannot be moved");
if (item instanceof FolderItem)
throw new InvalidItemException("folder cannot be copied");
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,login);
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, 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);
String mimeTypeForAccounting = (item instanceof AbstractFileItem)? ((AbstractFileItem) item).getContent().getMimeType(): null;
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, destination, false);
ses.save();
if (item instanceof FolderItem){
}finally {
ses.getWorkspace().getLockManager().unlock(nodeToCopy.getPath());
ses.getWorkspace().getLockManager().unlock(destination.getPath());
}
if (Utils.hasSharedChildren((FolderItem) item, ses)) throw new Exception("folder item with shared children cannot be moved");
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
}else
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
//TODO: accounting
ses.getWorkspace().getLockManager().unlock(nodeToMove.getPath());
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
ses.save();
}catch(Exception e){
log.error("error moving item with id {} in item with id {}",identifier, destinationId,e);
throw new WebApplicationException(e);
}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().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
@Path("{id}")
public Response deleteItem(@PathParam("id") String identifier){
public Response deleteItem(){
InnerMethodName.instance.set("deleteItem");
//TODO: check if identifier is The Workspace root, or the trash folder or the VREFolder root
//TODO: check also that is not already trashed
Session ses = null;
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
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 = node2Item.getItem(nodeToDelete, Excludes.GET_ONLY_CONTENT);
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
Item itemToDelete = ItemHandler.getItem(nodeToDelete, Arrays.asList(NodeConstants.ACCOUNTING_NAME, NodeConstants.METADATA_NAME, NodeConstants.OWNER_NAME));
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren((FolderItem) itemToDelete, ses)))
throw new Exception("SharedFolder, VreFolder or folders with shared children cannot be deleted");
log.debug("item is trashed? {}", itemToDelete.isTrashed());
if (!itemToDelete.isTrashed())
moveToTrash(ses, nodeToDelete, itemToDelete);
else
removeNode(ses, itemToDelete);
}catch(Exception e){
log.error("error removing item with id {} in Thrash",identifier,e);
throw new WebApplicationException(e);
if (!itemToDelete.isTrashed())
trashHandler.moveToTrash(ses, nodeToDelete, itemToDelete);
else
trashHandler.removeNodes(ses, Collections.singletonList(itemToDelete));
}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();
@ -463,124 +828,5 @@ public class ItemsManager {
return Response.ok().build();
}
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());
}
}
}

View File

@ -1,5 +1,6 @@
package org.gcube.data.access.storagehub.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -9,27 +10,35 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.xml.ws.WebServiceException;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.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.logical.And;
import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.data.access.storagehub.AuthorizationChecker;
@ -37,7 +46,9 @@ import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.Utils;
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.VREManager;
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
@ -69,10 +80,15 @@ public class WorkspaceManager {
@Inject
VREManager vreManager;
@Inject
TrashHandler trashHandler;
@RequestScoped
@QueryParam("exclude")
private List<String> excludes = Collections.emptyList();
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Path("")
@GET
@ -87,16 +103,18 @@ public class WorkspaceManager {
Item toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
Node node = ses.getNode(absolutePath.toPath());
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
toReturn = ItemHandler.getItem(node, excludes);
}catch(Throwable e){
log.error("error reading the node children of {}",absolutePath,e);
throw new WebApplicationException("error getting WS folder "+absolutePath.toPath(),e) ;
toReturn = node2Item.getItem(node, excludes);
}catch(RepositoryException re ){
log.error("jcr error getting workspace item", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting workspace item", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -105,10 +123,10 @@ public class WorkspaceManager {
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);
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("/", "-");
VRE vre = vreManager.getVRE(entireScopeName);
if (vre!=null) return vre;
@ -117,10 +135,10 @@ public class WorkspaceManager {
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
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();
Item vreFolder = ItemHandler.getItem(folder, excludes);
Item vreFolder = node2Item.getItem(folder, excludes);
return vreManager.putVRE(vreFolder);
}
@ -133,17 +151,21 @@ public class WorkspaceManager {
public ItemWrapper<Item> getVreRootFolder(){
InnerMethodName.instance.set("getVreRootFolder");
Session ses = null;
Item vreItem = null;
try {
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
return new ItemWrapper<Item>(getVreFolderItem(ses).getVreFolder());
}catch(Throwable e){
log.error("error reading vreNode for context {}",ScopeProvider.instance.get(),e);
throw new WebApplicationException("error retrieving vre folder",e);
vreItem = getVreFolderItem(ses).getVreFolder();
}catch(RepositoryException re ){
log.error("jcr error getting vrefolder", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting vrefolder", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
}
}
return new ItemWrapper<Item>(vreItem);
}
@Path("vrefolder/recents")
@ -152,23 +174,30 @@ public class WorkspaceManager {
public ItemList getVreFolderRecentsDocument(){
InnerMethodName.instance.set("getVreFolderRecents");
Session ses = null;
List<Item> recentItems = Collections.emptyList();
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
VRE vre = getVreFolderItem(ses);
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
List<Item> recentItems = vre.getRecents();
recentItems = vre.getRecents();
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
return new ItemList(recentItems);
}catch(Throwable e){
log.error("error reading recents for context {}",ScopeProvider.instance.get(),e);
throw new WebApplicationException("error reading recents",e);
}catch(RepositoryException re ){
log.error("jcr error getting recents", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting recents", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(recentItems);
}
@ -180,29 +209,98 @@ public class WorkspaceManager {
Session ses = null;
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getHomePath(), Constants.TRASH_ROOT_FOLDER_NAME);
Item item = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node folder = ses.getNode(trashPath.toPath());
Item item = ItemHandler.getItem(folder, excludes);
return new ItemWrapper<Item>(item);
}catch(Throwable e){
log.error("error reading the node {}",trashPath,e);
throw new WebApplicationException("error retrieving trash folder",e);
item = node2Item.getItem(folder, excludes);
}catch(RepositoryException re ){
log.error("jcr error getting trash", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error getting trash", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
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")
@GET
@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);
List<? extends Item> toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false);
}catch(Throwable e){
log.error("error reading the node children of {}",vrePath,e);
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false, null);
}catch(RepositoryException re ){
log.error("error reading the node children of {}",vrePath, re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error reading the node children of {}",vrePath, she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -233,16 +333,17 @@ public class WorkspaceManager {
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
InnerMethodName.instance.set("getVreFoldersPaged");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
List<? extends Item> toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false);
}catch(Throwable e){
log.error("(paged) error reading the node children of {}",vrePath,e);
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false, null);
}catch(RepositoryException re ){
log.error("(paged) error reading the node children of {}",vrePath, re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("(paged) error reading the node children of {}",vrePath, she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();
@ -266,13 +367,11 @@ public class WorkspaceManager {
ObjectMapper mapper = new ObjectMapper();
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getHomePath()), expression));
//ADD ALSO LIMIT AND OFFSET
String orderBy = "";
if (orderField!=null && orderField.size()>0)
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
log.info("query sent is {}",sql2Query);
@ -293,12 +392,13 @@ public class WorkspaceManager {
NodeIterator it = result.getNodes();
while (it.hasNext())
toReturn.add(ItemHandler.getItem(it.nextNode(), null));
}catch(Throwable e){
log.error("error executing the query",e);
throw new WebServiceException("error executing the query", e);
toReturn.add(node2Item.getItem(it.nextNode(), null));
}catch(RepositoryException | IOException re ){
log.error("error executing the query", re);
GXOutboundErrorResponse.throwException(new BackendGenericError(re));
}catch(StorageHubException she ){
log.error("error executing the query", she);
GXOutboundErrorResponse.throwException(she);
}finally{
if (ses!=null)
ses.logout();

View File

@ -8,7 +8,10 @@
<param-name>admin-pwd</param-name>
<param-value>gcube2010*onan</param-value>
</context-param>
<context-param>
<param-name>resolver-basepath</param-name>
<param-value>https://data1-d.d4science.net/shub</param-value>
</context-param>
<servlet>
<servlet-name>org.gcube.data.access.storagehub.StorageHub</servlet-name>

View File

@ -23,6 +23,7 @@ public class Expressions {
@Inject
Evaluators evaluators;
@Test
public void test() {

View File

@ -13,7 +13,7 @@ import javax.jcr.nodetype.NodeType;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.handlers.ItemHandler;
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
@ -24,11 +24,6 @@ public class TestFields {
Logger logger = LoggerFactory.getLogger(TestFields.class);
@Test
public void replace(){
System.out.println("/Home/Giancarlo".replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-"));
}
@Test
public void iterateOverFields() throws Exception{
@ -62,10 +57,10 @@ public class TestFields {
when(node.getParent()).thenReturn(parent);
when(node.getProperty(anyString())).thenReturn(prop);
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());
}
}

View File

@ -7,6 +7,8 @@ import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import java.io.File;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
@ -14,7 +16,7 @@ import org.junit.Test;
public class TestNode {
@Test
/*@Test
public void testShared() throws Exception{
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);
ImageIO.write(buffered, "png", buffer );
byte[] imageInByte = buffer.toByteArray();*/
}
byte[] imageInByte = buffer.toByteArray();
}*/
}

Binary file not shown.