- External Folder imporvements - Inbox and Outbox creation

master
lucio.lelii 3 years ago
parent bcbe97f547
commit 2aadb9cce7

@ -35,5 +35,6 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry combineaccessrules="false" kind="src" path="/storagehub-model"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
@ -19,7 +22,10 @@
<wb-module deploy-name="storagehub">
@ -39,7 +45,10 @@
<wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
@ -59,7 +68,10 @@
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
@ -79,7 +91,10 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
@ -99,13 +114,16 @@
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<dependent-module archiveName="storagehub-model-1.0.10-SNASPHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
<dependent-module archiveName="storagehub-model-1.1.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-model/storagehub-model">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module archiveName="storagehub-scripting-util-1.0.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/storagehub-scripting-util/storagehub-scripting-util">
<dependency-type>uses</dependency-type>
</dependent-module>
@ -125,7 +143,10 @@
<property name="context-root" value="storagehub"/>
@ -145,7 +166,10 @@
<property name="java-output-path" value="/storagehub-webapp_BRANCH/target/classes"/>
@ -165,7 +189,10 @@
</wb-module>

@ -273,13 +273,6 @@
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.core/jersey-common -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>

@ -9,6 +9,12 @@ public class Constants {
public static final String PERSONAL_VRES_FOLDER_PARENT_NAME = "VREs";
public static final String INBOX_FOLDER_NAME = "InBox";
public static final String OUTBOX_FOLDER_NAME = "OutBox";
public static final String ATTACHMENTNODE_NAME = "hl:attachments";
public static final String SHARED_WITH_ME_PARENT_NAME = "SharedWithMe";
public static final String SHARED_FOLDER_PATH = "/Share";

@ -19,6 +19,14 @@ public class PathUtil {
return Paths.getPath(String.format("/Home/%s",login));
}
public Path getInboxPath(String login) {
return Paths.append(getHome(login),Constants.INBOX_FOLDER_NAME);
}
public Path getOutboxPath(String login) {
return Paths.append(getHome(login),Constants.OUTBOX_FOLDER_NAME);
}
@Deprecated
private Path getOldTrashPath(String login){
return Paths.append(getWorkspacePath(login),Constants.TRASH_ROOT_FOLDER_NAME);

@ -13,6 +13,7 @@ import org.gcube.data.access.storagehub.services.Impersonable;
import org.gcube.data.access.storagehub.services.ItemSharing;
import org.gcube.data.access.storagehub.services.ItemsCreator;
import org.gcube.data.access.storagehub.services.ItemsManager;
import org.gcube.data.access.storagehub.services.MessageManager;
import org.gcube.data.access.storagehub.services.UserManager;
import org.gcube.data.access.storagehub.services.WorkspaceManager;
import org.gcube.data.access.storagehub.services.admin.ScriptManager;
@ -34,6 +35,7 @@ public class StorageHub extends Application {
classes.add(UserManager.class);
classes.add(GroupManager.class);
classes.add(ScriptManager.class);
classes.add(MessageManager.class);
classes.add(MultiPartFeature.class);
classes.add(SerializableErrorEntityTextWriter.class);
classes.add(MyApplicationListener.class);

@ -1,6 +1,5 @@
package org.gcube.data.access.storagehub;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -8,14 +7,11 @@ import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
@ -24,28 +20,25 @@ import javax.jcr.Session;
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.query.Query;
import javax.jcr.version.Version;
import org.apache.commons.io.FilenameUtils;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.util.Text;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.ExternalLink;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.GCubeItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
@ -79,7 +72,7 @@ public class Utils {
return digest;
}
public static long getItemCount(Node parent, boolean showHidden, Class<? extends Item> nodeType) throws RepositoryException, BackendGenericError{
public static long getItemCount(Node parent, boolean showHidden, Class<? extends RootItem> nodeType) throws RepositoryException, BackendGenericError{
return getItemList(parent, Excludes.ALL, null, showHidden, nodeType).size();
}
@ -108,12 +101,13 @@ public class Utils {
}
public static <T extends Item> List<T> serachByNameOnFolder(Session ses, String user, AuthorizationChecker authChecker, Node parent, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends Item> nodeTypeToInclude, String nameParam) throws RepositoryException, BackendGenericError{
public static <T extends Item> List<T> serachByNameOnFolder(Session ses, String user, AuthorizationChecker authChecker, Node parent, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude, String nameParam) throws RepositoryException, BackendGenericError{
String xpath = String.format("/jcr:root%s//element(*,nthl:workspaceItem)[jcr:like(fn:lower-case(@jcr:title), '%s')]",ISO9075.encodePath(parent.getPath()), nameParam.toLowerCase());
//String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
logger.debug("query for search is {}",xpath);
long start = System.currentTimeMillis();
@SuppressWarnings("deprecation")
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(xpath, Query.XPATH);
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(jcrQuery.execute().getNodes());
logger.debug("[SEARCH] real search took {} millis",(System.currentTimeMillis()-start));
@ -135,11 +129,11 @@ public class Utils {
}
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
public static <T extends Item> List<T> getItemList(Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
return getItemList(null, parent, excludes, range, showHidden, nodeTypeToInclude);
}
public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
public static <T extends Item> List<T> getItemList(Predicate<Node> checker, Node parent, List<String> excludes, Range range, boolean showHidden, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
logger.trace("getting children of node {}", parent.getIdentifier());
long start = System.currentTimeMillis();
NodeChildrenFilterIterator iterator = new NodeChildrenFilterIterator(parent);
@ -147,7 +141,7 @@ public class Utils {
return getItemListFromNodeIterator(checker, iterator, excludes, range, showHidden, false, nodeTypeToInclude);
}
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
private static <T extends Item> List<T> getItemListFromNodeIterator(Predicate<Node> checker, NodeChildrenFilterIterator iterator, List<String> excludes, Range range, boolean showHidden, boolean excludeTrashed, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
List<T> returnList = new ArrayList<T>();
logger.trace("nodeType is {}",nodeTypeToInclude);
@ -194,71 +188,9 @@ public class Utils {
}
public static Deque<Item> getAllNodesForZip(FolderItem directory, Session session, String login, AccountingHandler accountingHandler, List<String> excludes) throws RepositoryException, BackendGenericError{
Deque<Item> queue = new LinkedList<Item>();
Node currentNode = session.getNodeByIdentifier(directory.getId());
queue.push(directory);
Deque<Item> tempQueue = new LinkedList<Item>();
logger.trace("adding directory {}",currentNode.getPath());
for (Item item : Utils.getItemList(currentNode,Excludes.GET_ONLY_CONTENT, null, false, null)){
if (excludes.contains(item.getId())) continue;
if (item instanceof FolderItem)
tempQueue.addAll(getAllNodesForZip((FolderItem) item, session, login, accountingHandler, excludes));
else if (item instanceof AbstractFileItem){
logger.trace("adding file {}",item.getPath());
AbstractFileItem fileItem = (AbstractFileItem) item;
accountingHandler.createReadObj(fileItem.getTitle(), session, session.getNodeByIdentifier(item.getId()), login, false);
queue.addLast(item);
}
}
queue.addAll(tempQueue);
return queue;
}
public static void zipNode(ZipOutputStream zos, Deque<Item> queue, String login, org.gcube.common.storagehub.model.Path originalPath, StorageBackendHandler storageHandler) throws Exception{
logger.trace("originalPath is {}",originalPath.toPath());
org.gcube.common.storagehub.model.Path actualPath = Paths.getPath("");
while (!queue.isEmpty()) {
Item item = queue.pop();
if (item instanceof FolderItem) {
actualPath = Paths.getPath(item.getPath());
logger.trace("actualPath is {}",actualPath.toPath());
String name = Paths.remove(actualPath, originalPath).toPath().replaceFirst("/", "");
logger.trace("writing dir {}",name);
if (name.isEmpty()) continue;
try {
zos.putNextEntry(new ZipEntry(name));
}finally {
zos.closeEntry();
}
} else if (item instanceof AbstractFileItem){
try {
InputStream streamToWrite = storageHandler.download(((AbstractFileItem)item).getContent().getStorageId());
if (streamToWrite == null){
logger.warn("discarding item {} ",item.getName());
continue;
}
try(BufferedInputStream is = new BufferedInputStream(streamToWrite)){
String name = (Paths.remove(actualPath, originalPath).toPath()+item.getName()).replaceFirst("/", "");
logger.trace("writing file {}",name);
zos.putNextEntry(new ZipEntry(name));
copyStream(is, zos);
}catch (Exception e) {
logger.warn("error writing item {}", item.getName(),e);
} finally{
zos.closeEntry();
}
zos.flush();
}catch (Throwable e) {
logger.warn("error reading content for item {}", item.getPath(),e);
}
}
}
zos.close();
}
private static void copyStream(InputStream in, OutputStream out) throws IOException {
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[2048];
int readcount = 0;
while ((readcount=in.read(buffer))!=-1) {
@ -279,34 +211,7 @@ public class Utils {
return false;
}
public static void getAllContentIds(Session ses, Set<String> idsToDelete, Item itemToDelete, VersionHandler versionHandler) throws Exception{
if (itemToDelete instanceof AbstractFileItem) {
Node currentNode = ses.getNodeByIdentifier(itemToDelete.getId());
List<Version> versions = versionHandler.getContentVersionHistory(currentNode, 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) {
//only to be sure to not delete shared content
if (itemToDelete.isShared()) return;
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);

@ -7,7 +7,7 @@ import java.util.Map;
import java.util.Set;
import org.gcube.common.storagehub.model.annotations.RootNode;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -30,32 +30,33 @@ public class ClassHandler {
"nthl:workflowTemplate", "nthl:gCubeMetadata", "nthl:gCubeDocument", "nthl:gCubeDocumentLink", "nthl:gCubeImageDocumentLink", "nthl:gCubePDFDocumentLink",
"nthl:gCubeImageDocument", "nthl:gCubePDFDocument", "nthl:gCubeURLDocument", "nthl:gCubeAnnotation", "nthl:externalResourceLink", "nthl:tabularDataLink");
private Map<String, Class<? extends Item>> classMap = new HashMap<String, Class<? extends Item>>();
private Map<Class<? extends Item>, String> typeMap = new HashMap<Class<? extends Item>, String>();
private Map<String, Class<? extends RootItem>> classMap = new HashMap<String, Class<? extends RootItem>>();
private Map<Class<? extends RootItem>, String> typeMap = new HashMap<Class<? extends RootItem>, String>();
@SuppressWarnings("unchecked")
private ClassHandler() {
Set<Class<?>> classesAnnotated = reflection.getTypesAnnotatedWith(RootNode.class);
for (Class<?> clazz: classesAnnotated ){
if (Item.class.isAssignableFrom(clazz)) {
if (RootItem.class.isAssignableFrom(clazz)) {
String value = clazz.getAnnotation(RootNode.class).value();
log.debug("loading class {} with value {} ", clazz, value );
classMap.put(value, (Class<? extends Item>) clazz);
typeMap.put((Class<? extends Item>) clazz, value);
classMap.put(value, (Class<? extends RootItem>) clazz);
typeMap.put((Class<? extends RootItem>) clazz, value);
}
}
}
public Class<? extends Item> get(String nodeType){
public Class<? extends RootItem> get(String nodeType){
if (classMap.containsKey(nodeType)) return classMap.get(nodeType);
if (deprecatedNode.contains(nodeType)) return Item.class;
if (deprecatedNode.contains(nodeType)) return RootItem.class;
return null;
//throw new RuntimeException("mapping not found for nodetype "+ nodeType);
}
public String getNodeType(Class<? extends Item> clazz){
public String getNodeType(Class<? extends RootItem> clazz){
if (typeMap.containsKey(clazz)) return typeMap.get(clazz);
throw new RuntimeException("mapping not found for nodetype "+ clazz.getSimpleName());
}

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

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

@ -6,6 +6,7 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -14,6 +15,7 @@ import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import javax.jcr.version.Version;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.storagehub.model.Excludes;
@ -26,6 +28,8 @@ import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.PathUtil;
@ -33,6 +37,7 @@ import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -61,8 +66,10 @@ public class TrashHandler {
@Inject
PathUtil pathUtil;
@Inject FolderPluginHandler managerHandler;
@Inject
StorageBackendHandler storageHandler;
FolderPluginHandler folderHandler;
public void removeNodes(Session ses, List<Item> itemsToDelete) throws RepositoryException, StorageHubException{
log.debug("defnitively removing nodes with ids {}",itemsToDelete);
@ -78,34 +85,55 @@ public class TrashHandler {
}
}
private void retrieveContentsToDelete(Set<AbstractFileItem> itemsToDelete, Item itemToDelete) throws Exception{
if (itemToDelete instanceof AbstractFileItem) {
itemsToDelete.add(((AbstractFileItem) itemToDelete));
}else if (itemToDelete instanceof FolderItem) {
//only to be sure to not delete shared content
if (itemToDelete.isShared()) return;
List<Item> items = Utils.getItemList((Node) itemToDelete, Excludes.GET_ONLY_CONTENT , null, true, null);
for (Item item: items)
retrieveContentsToDelete(itemsToDelete, item);
}
}
private void removeNodesInternally(Session ses, Item itemToDelete, boolean onlyContent) throws RepositoryException, StorageHubException {
try {
Set<String> contentIdsToDelete = new HashSet<>();
Set<AbstractFileItem> itemsToDelete = new HashSet<>();
Node nodeToDelete = ses.getNodeByIdentifier(itemToDelete.getId());
if (itemToDelete instanceof TrashItem) {
List<Item> trashChildren = Utils.getItemList(nodeToDelete, Excludes.GET_ONLY_CONTENT, null, true, null);
for (Item itemContentToRetrieve: trashChildren)
Utils.getAllContentIds(ses, contentIdsToDelete, itemContentToRetrieve, versionHandler);
} else {
Utils.getAllContentIds(ses, contentIdsToDelete, itemToDelete, versionHandler);
}
retrieveContentsToDelete(itemsToDelete, itemContentToRetrieve);
} else
retrieveContentsToDelete(itemsToDelete, itemToDelete);
if (!onlyContent)
nodeToDelete.remove();
log.debug("content ids to remove are {}",contentIdsToDelete);
String ids = itemsToDelete.stream().map((i) -> i.getId()).collect(Collectors.joining(","));
log.debug("content ids to remove are {}",ids);
Runnable deleteFromStorageRunnable = AuthorizedTasks.bind(new Runnable() {
@Override
public void run() {
for (String id: contentIdsToDelete) {
for (AbstractFileItem item: itemsToDelete ) {
try {
storageHandler.delete(id);
log.debug("file with id {} correctly removed on storage",id);
FolderManager manager = folderHandler.getFolderManager(item);
manager.getStorageBackend().onDelete(item.getContent());
List<Version> versions = versionHandler.getContentVersionHistory((Node)item.getRelatedNode());
for (Version version: versions) {
Content content = node2Item.getContent(version);
manager.getStorageBackend().onDelete(content);
}
log.debug("file with id {} correctly removed from storage {}",item.getId(), manager.getClass().getSimpleName());
}catch(Throwable t) {
log.warn("error removing file on storage with id {}",id, t);
log.warn("error removing file with id {} from storage",item.getId(), t);
}
}
}
@ -120,6 +148,7 @@ public class TrashHandler {
}
}
public void moveToTrash(Session ses, Node nodeToDelete, Item item, String login) throws RepositoryException, BackendGenericError{
log.debug("moving node {} to trash ",item.getId());

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

@ -35,6 +35,7 @@ import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.NodeChildrenFilterIterator;
@ -48,7 +49,7 @@ public class Item2NodeConverter {
private static final Logger logger = LoggerFactory.getLogger(Item2NodeConverter.class);
public <T extends Item> Node getNode(Node parentNode, T item){
public <T extends RootItem> Node getNode(Node parentNode, T item){
try {
String primaryType= ClassHandler.instance().getNodeType(item.getClass());
Node newNode = parentNode.addNode(Text.escapeIllegalJcrChars(item.getName()), primaryType);

@ -7,20 +7,16 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
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.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.lock.LockException;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
@ -29,24 +25,26 @@ import org.apache.tika.detect.Detector;
import org.apache.tika.io.TikaInputStream;
import org.apache.tika.metadata.Metadata;
import org.gcube.common.authorization.library.AuthorizedTasks;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.NodeConstants;
import org.gcube.common.storagehub.model.Paths;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.storages.MetaInfo;
import org.gcube.common.storagehub.model.storages.StorageBackend;
import org.gcube.common.storagehub.model.types.ItemAction;
import org.gcube.common.storagehub.model.types.NodeProperty;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.MultipleOutputStream;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
@ -56,13 +54,14 @@ import org.gcube.data.access.storagehub.handlers.items.builders.FileCreationPara
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.GCubeItemCreationParameters;
import org.gcube.data.access.storagehub.handlers.items.builders.URLCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class ItemHandler {
@Inject
AccountingHandler accountingHandler;
@ -71,11 +70,12 @@ public class ItemHandler {
@Inject
AuthorizationChecker authChecker;
@Inject
VersionHandler versionHandler;
@Inject StorageBackendHandler storageBackend;
@Inject
FolderPluginHandler pluginHandler;
private static ExecutorService executor = Executors.newFixedThreadPool(100);
@ -142,8 +142,7 @@ public class ItemHandler {
private Node create(FileCreationParameters params, Node destination) throws Exception{
Node newNode = createFileItemInternally(params.getSession(), destination, params.getStream(), params.getName(), params.getDescription(), params.getUser(), true);
params.getSession().save();
versionHandler.checkinContentNode(newNode, params.getSession());
versionHandler.checkinContentNode(newNode);
log.info("file with id {} correctly created",newNode.getIdentifier());
return newNode;
}
@ -195,7 +194,7 @@ public class ItemHandler {
Node parentNode = directoryNodeMap.get(parentPath);
if (parentNode ==null)
parentNode = createPath(parentPath, directoryNodeMap, parentDirectoryNode, params.getSession(), params.getUser());
fileNode = createFileItemInternally(params.getSession(), parentNode, input, name, "", params.getUser(), false);
}
fileNodes.add(fileNode);
@ -209,7 +208,7 @@ public class ItemHandler {
params.getSession().save();
for (Node node : fileNodes)
versionHandler.checkinContentNode(node, params.getSession());
versionHandler.checkinContentNode(node);
return parentDirectoryNode;
}
@ -246,13 +245,28 @@ public class ItemHandler {
return newNode;
}
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, UserNotAuthorizedException, ItemLockedException, BackendGenericError{
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, StorageHubException{
Node newNode;
try {
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationNode.getPath()), name).toPath());
FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL);
FolderManager folderManager = pluginHandler.getFolderManager(destinationItem);
StorageBackend storageBackend = folderManager.getStorageBackend();
String relativePath = destinationNode.getPath();
if (destinationItem.isExternalManaged())
relativePath = relativePath.replace(folderManager.getRootFolder().getPath(), "");
String newNodePath = Paths.append(Paths.getPath(destinationNode.getPath()), name).toPath();
if (ses.nodeExists(newNodePath)) {
if (!folderManager.manageVersion())
throw new InvalidCallParameters("storage for plugin "+folderManager.getClass().getName()+" doesn't support versioning");
newNode = ses.getNode(newNodePath);
authChecker.checkWriteAuthorizationControl(ses, login, newNode.getIdentifier(), false);
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath,login);
item.setHidden(destinationNode.getProperty(NodeProperty.HIDDEN.toString()).getBoolean());
if (withLock) {
try {
@ -262,7 +276,7 @@ public class ItemHandler {
}
}
try {
versionHandler.checkoutContentNode(newNode, ses);
versionHandler.checkoutContentNode(newNode);
log.trace("replacing content of class {}",item.getContent().getClass());
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, login, false);
@ -270,9 +284,10 @@ public class ItemHandler {
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
}
}catch(PathNotFoundException pnf) {
}
else {
authChecker.checkWriteAuthorizationControl(ses, login, destinationNode.getIdentifier(), true);
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
AbstractFileItem item = fillItemWithContent(stream, storageBackend, name, description, relativePath, login);
if (withLock) {
try {
log.debug("trying to acquire lock");
@ -288,20 +303,22 @@ public class ItemHandler {
}finally {
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
}
versionHandler.makeVersionableContent(newNode, ses);
versionHandler.makeVersionableContent(newNode);
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, login, destinationNode, false);
}
return newNode;
}
private AbstractFileItem fillItemWithContent(InputStream stream, String name, String description, String path, String login) throws BackendGenericError{
ContentHandler handler = getContentHandler(stream , name, path, login);
private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name, String description, String relPath, String login) throws BackendGenericError{
ContentHandler handler = getContentHandler(stream, storageBackend, name, relPath, login);
AbstractFileItem item =handler.buildItem(name, description, login);
return item ;
}
private ContentHandler getContentHandler(InputStream stream , String name, String path, String login) throws BackendGenericError {
private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError {
final MultipleOutputStream mos;
@ -348,9 +365,7 @@ public class ItemHandler {
@Override
public MetaInfo call() throws Exception {
try(InputStream is1 = mos.get()){
String uid = UUID.randomUUID().toString();
String remotePath= String.format("%s/%s-%s",path,uid,name);
MetaInfo info = storageBackend.upload(is1, remotePath);
MetaInfo info = storageBackend.upload(is1, relPath, name);
return info;
}catch (Throwable e) {
log.error("error writing content",e );

@ -12,8 +12,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.inject.Singleton;
import javax.jcr.Node;
@ -28,16 +26,20 @@ import javax.jcr.Value;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.annotations.Attribute;
import org.gcube.common.storagehub.model.annotations.AttributeRootNode;
import org.gcube.common.storagehub.model.annotations.ListNodes;
import org.gcube.common.storagehub.model.annotations.MapAttribute;
import org.gcube.common.storagehub.model.annotations.NodeAttribute;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.items.ExternalFolder;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.RootItem;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.TrashItem;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.messages.Message;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.reflections.Configuration;
import org.reflections.Reflections;
@ -54,7 +56,7 @@ public class Node2ItemConverter {
private static HashMap<Class<?>, Map<String, Class>> typeToSubtypeMap = new HashMap<>();
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends Item> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
public <T extends Item> T getFilteredItem(Node node, List<String> excludes, Class<? extends RootItem> nodeTypeToInclude) throws RepositoryException, BackendGenericError{
@SuppressWarnings("unchecked")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return null;
@ -71,22 +73,29 @@ public class Node2ItemConverter {
@SuppressWarnings("unchecked")
Class<T> classToHandle = (Class<T>)ClassHandler.instance().get(node.getPrimaryNodeType().getName());
if (classToHandle==null) return null;
/*Node nodeToRetrieve= node;
if (SharedFolder.class.isAssignableFrom(classToHandle)) {
NodeIterator it= node.getSharedSet();
while (it.hasNext()) {
Node sharedNode = it.nextNode();
if (sharedNode.getPath().startsWith(Utils.getWorkspacePath().toPath())) {
nodeToRetrieve = sharedNode;
}
}
}*/
T item = retrieveItem(node, excludes, classToHandle);
item.setRelatedNode(node);
return item;
}
public Content getContent(Node node) throws RepositoryException, BackendGenericError{
Content content = new Content();
setGenericFields(node, Content.class, content);
return content;
}
public Message getMessageItem(Node node) throws RepositoryException{
Message msg = new Message();
try {
Node attachmentNode = node.getNode(Constants.ATTACHMENTNODE_NAME);
msg.setWithAttachments(attachmentNode.hasNodes());
}catch (Throwable e) {
msg.setWithAttachments(false);
}
setRooItemCommonFields(node, Collections.emptyList(), Message.class, msg);
return msg;
}
private <T extends Item> T retrieveItem(Node node, List<String> excludes, Class<T> classToHandle) throws RepositoryException, BackendGenericError{
T item;
@ -95,13 +104,6 @@ public class Node2ItemConverter {
}catch (Exception e) {
throw new BackendGenericError(e);
}
item.setId(node.getIdentifier());
item.setName(Text.unescapeIllegalJcrChars(node.getName()));
item.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
item.setLocked(node.isLocked());
item.setPrimaryType(node.getPrimaryNodeType().getName());
try {
item.setShared(SharedFolder.class.isInstance(item) ||
@ -117,20 +119,58 @@ public class Node2ItemConverter {
item.setTrashed(false);
}
try {
item.setExternalManaged(hasTypedParent(node, ExternalFolder.class));
}catch (Exception e) {
item.setExternalManaged(false);
}
item.setLocked(node.isLocked());
setRooItemCommonFields(node, excludes, classToHandle, item);
return item;
}
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
if(node==null) return false;
return checkNodeType(node, parentType) || hasTypedParent(node.getParent(), parentType);
}
private <T extends RootItem> void setRooItemCommonFields(Node node, List<String> excludes, Class<T> classToHandle, T instance) throws RepositoryException{
try{
item.setParentId(node.getParent().getIdentifier());
item.setParentPath(node.getParent().getPath());
instance.setParentId(node.getParent().getIdentifier());
instance.setParentPath(node.getParent().getPath());
}catch (Throwable e) {
logger.trace("Root node doesn't have a parent");
}
instance.setRelatedNode(node);
instance.setId(node.getIdentifier());
instance.setName(Text.unescapeIllegalJcrChars(node.getName()));
instance.setPath(Text.unescapeIllegalJcrChars(node.getPath()));
instance.setPrimaryType(node.getPrimaryNodeType().getName());
setGenericFields(node, classToHandle, instance);
}
private <T> void setGenericFields(Node node, Class<T> classToHandle, T instance){
for (Field field : retrieveAllFields(classToHandle)){
if (field.isAnnotationPresent(Attribute.class)){
Attribute attribute = field.getAnnotation(Attribute.class);
field.setAccessible(true);
try{
Class<?> returnType = field.getType();
field.set(item, getPropertyValue(returnType, node.getProperty(attribute.value())));
field.set(instance, getPropertyValue(returnType, node.getProperty(attribute.value())));
logger.trace("retrieve item - added field {}",field.getName());
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} property",attribute.value());
@ -140,13 +180,12 @@ public class Node2ItemConverter {
} else if (field.isAnnotationPresent(NodeAttribute.class)){
String fieldNodeName = field.getAnnotation(NodeAttribute.class).value();
//for now it excludes only first level node
if (excludes!=null && excludes.contains(fieldNodeName)) continue;
logger.trace("retrieving field node "+field.getName());
field.setAccessible(true);
try{
Node fieldNode = node.getNode(fieldNodeName);
logger.trace("looking in node {} searched with {}",fieldNode.getName(),fieldNodeName);
field.set(item, iterateNodeAttributeFields(field.getType(), fieldNode));
field.set(instance, iterateNodeAttributeFields(field.getType(), fieldNode));
}catch(PathNotFoundException e){
logger.trace("the current node dosn't contain {} node",fieldNodeName);
} catch (Exception e ) {
@ -156,19 +195,8 @@ public class Node2ItemConverter {
}
}
return item;
}
private <T extends Item> boolean hasTypedParent(Node node, Class<T> parentType) throws BackendGenericError, RepositoryException{
if(node==null) return false;
return checkNodeType(node, parentType) || hasTypedParent(node.getParent(), parentType);
}
private <T> T iterateNodeAttributeFields(Class<T> clazz, Node node) throws Exception{
T obj = clazz.newInstance();
for (Field field : retrieveAllFields(clazz)){
@ -264,7 +292,7 @@ public class Node2ItemConverter {
return obj;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({ "unchecked" })
private Object getPropertyValue(Class returnType, Property prop) throws Exception{
if (returnType.equals(String.class)) return prop.getString();
if (returnType.isEnum()) return Enum.valueOf(returnType, prop.getString());

@ -1,29 +0,0 @@
package org.gcube.data.access.storagehub.handlers.plugins;
import java.util.Map;
import java.util.stream.Collectors;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.plugins.ExternalFolderManagerConnector;
@Singleton
public class ExternalFolderPluginHandler {
@Inject
private Instance<ExternalFolderManagerConnector> connectors;
private Map<String, ExternalFolderManagerConnector> connectorsMap;
ExternalFolderPluginHandler(){
connectorsMap = connectors.stream().collect(Collectors.toMap(ExternalFolderManagerConnector::getName, e -> e ));
}
public ExternalFolderManagerConnector getConnector(String name) throws PluginNotFoundException {
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
return connectorsMap.get(name);
}
}

@ -0,0 +1,80 @@
package org.gcube.data.access.storagehub.handlers.plugins;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.gcube.common.storagehub.model.Excludes;
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.items.ExternalFolder;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.plugins.FolderManagerConnector;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.storage.backend.impl.GcubeFolderManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class FolderPluginHandler {
private static Logger log = LoggerFactory.getLogger(FolderPluginHandler.class);
@Inject
Node2ItemConverter node2Item;
private GcubeFolderManager defaultManager = new GcubeFolderManager();
public FolderManager getDefault() {
return defaultManager;
}
@Inject
Instance<FolderManagerConnector> connectors;
private Map<String, FolderManagerConnector> connectorsMap;
FolderPluginHandler(){
if (connectors !=null)
connectorsMap = connectors.stream().collect(Collectors.toMap(FolderManagerConnector::getName, e -> e ));
else {
log.info("connectors are null");
connectorsMap = Collections.emptyMap();
}
}
public FolderManagerConnector getConnector(String name) throws PluginNotFoundException {
if (!connectorsMap.containsKey(name)) throw new PluginNotFoundException("plugin "+name+" not found");
return connectorsMap.get(name);
}
public FolderManager getFolderManager(Item item) throws PluginInitializationException, PluginNotFoundException, RepositoryException, BackendGenericError{
if (!item.isExternalManaged())
return defaultManager;
Session session = ((Node)item.getRelatedNode()).getSession();
Item parent = null;
do {
String parentId = item.getParentId();
Node node = session.getNodeByIdentifier(parentId);
parent = node2Item.getItem(node, Excludes.ALL);
if (parent !=null && parent instanceof ExternalFolder) {
ExternalFolder extParent = (ExternalFolder) parent;
String plugin = extParent.getManagedBy();
Map<String, Object> parameters = extParent.getConnectionParameters().getMap();
return getConnector(plugin).connect(extParent, parameters);
}
} while (parent!=null);
throw new BackendGenericError("selected external managed item doesn't have a parent external folder");
}
}

@ -0,0 +1,28 @@
package org.gcube.data.access.storagehub.handlers.plugins;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class OperationMediator {
@Inject
FolderPluginHandler folderHandler;
/*
boolean onMove(Item source, Item destination, Session session) throws PluginInitializationException, PluginNotFoundException, BackendGenericError, RepositoryException{
FolderManager sourceFolderManager = folderHandler.getFolderManager(source);
FolderManager destinationFolderManager = folderHandler.getFolderManager(destination);
if (source instanceof FolderItem) {
destinationFolderManager.onCreatedFolder((FolderItem) source);
session.move(source.getPath(), destination.getPath());
sourceFolderManager.onDeletingFolder((FolderItem) source);
} else if (source instanceof AbstractFileItem){
}
}
*/
}

@ -35,6 +35,7 @@ import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.ExternalFolder;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;

@ -57,12 +57,16 @@ import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
import org.gcube.common.storagehub.model.exceptions.PluginInitializationException;
import org.gcube.common.storagehub.model.exceptions.PluginNotFoundException;
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
import org.gcube.common.storagehub.model.items.AbstractFileItem;
import org.gcube.common.storagehub.model.items.FolderItem;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.items.SharedFolder;
import org.gcube.common.storagehub.model.items.VreFolder;
import org.gcube.common.storagehub.model.items.nodes.Content;
import org.gcube.common.storagehub.model.plugins.FolderManager;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.common.storagehub.model.service.VersionList;
@ -78,12 +82,13 @@ import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
import org.gcube.data.access.storagehub.exception.MyAuthException;
import org.gcube.data.access.storagehub.handlers.ClassHandler;
import org.gcube.data.access.storagehub.handlers.CompressHandler;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.VersionHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
@ -122,9 +127,14 @@ public class ItemsManager extends Impersonable{
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject StorageBackendHandler storageBackend;
@Inject
FolderPluginHandler folderPluginHandler;
@Inject
CompressHandler compressHandler;
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
@ -215,11 +225,24 @@ public class ItemsManager extends Impersonable{
return null;
}
@Deprecated
@GET
@Path("{id}/items/{name}")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
public ItemList findChildrenByNamePatternInPath(@QueryParam("exclude") List<String> excludes, @PathParam("name") String name){
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
@GET
@Path("{id}/items")
@Produces(MediaType.APPLICATION_JSON)
public ItemList findChildrenByNamePattern(@QueryParam("exclude") List<String> excludes, @QueryParam("name") String name){
InnerMethodName.instance.set("findChildrenByNamePattern");
return _findChildrenByNamePattern(excludes, name);
}
public ItemList _findChildrenByNamePattern(List<String> excludes, String name){
Session ses = null;
List<Item> toReturn = new ArrayList<>();
try{
@ -255,11 +278,11 @@ public class ItemsManager extends Impersonable{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@GET
@Path("{id}/children/count")
@Produces(MediaType.APPLICATION_JSON)
@ -624,7 +647,7 @@ public class ItemsManager extends Impersonable{
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not versioned");
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node, ses);
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
for (Version version: jcrVersions) {
boolean currentVersion = ((AbstractFileItem)currentItem).getContent().getStorageId().equals(version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString());
@ -674,16 +697,15 @@ public class ItemsManager extends Impersonable{
if (!(currentItem instanceof AbstractFileItem))
throw new InvalidItemException("this item is not a file");
List<Version> jcrVersions = versionHandler.getContentVersionHistory(ses.getNodeByIdentifier(id), ses);
List<Version> jcrVersions = versionHandler.getContentVersionHistory(node);
for (Version version: jcrVersions) {
log.debug("retrieved version id {}, name {}", version.getIdentifier(), version.getName());
if (version.getName().equals(versionName)) {
long size = version.getFrozenNode().getProperty(NodeProperty.SIZE.toString()).getLong();
String mimeType = version.getFrozenNode().getProperty(NodeProperty.MIME_TYPE.toString()).getString();
String storageId = version.getFrozenNode().getProperty(NodeProperty.STORAGE_ID.toString()).getString();
Content content = node2Item.getContent(version);
final InputStream streamToWrite = storageBackend.download(storageId);
FolderManager folderManager = folderPluginHandler.getFolderManager((AbstractFileItem) currentItem);
final InputStream streamToWrite = folderManager.getStorageBackend().download(content);
String oldfilename = FilenameUtils.getBaseName(currentItem.getTitle());
String ext = FilenameUtils.getExtension(currentItem.getTitle());
@ -698,8 +720,8 @@ public class ItemsManager extends Impersonable{
return Response
.ok(so)
.header("content-disposition","attachment; filename = "+fileName)
.header("Content-Length", size)
.header("Content-Type", mimeType)
.header("Content-Length", content.getSize())
.header("Content-Type", content.getMimeType())
.build();
}
}
@ -779,7 +801,7 @@ public class ItemsManager extends Impersonable{
} else if (item instanceof FolderItem){
try {
final Deque<Item> allNodes = Utils.getAllNodesForZip((FolderItem)item, ses, currentUser, accountingHandler, excludes);
final Deque<Item> allNodes = compressHandler.getAllNodesForZip((FolderItem)item, ses, currentUser, accountingHandler, excludes);
final org.gcube.common.storagehub.model.Path originalPath = Paths.getPath(item.getParentPath());
StreamingOutput so = new StreamingOutput() {
@ -790,7 +812,7 @@ public class ItemsManager extends Impersonable{
long start = System.currentTimeMillis();
zos.setLevel(Deflater.BEST_COMPRESSION);
log.debug("writing StreamOutput");
Utils.zipNode(zos, allNodes, currentUser, originalPath, storageBackend);
compressHandler.zipNode(zos, allNodes, currentUser, originalPath);
log.debug("StreamOutput written in {}",(System.currentTimeMillis()-start));
} catch (Exception e) {
log.error("error writing stream",e);
@ -825,9 +847,11 @@ public class ItemsManager extends Impersonable{
return response;
}
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException {
private Response downloadFileInternal(Session ses, AbstractFileItem fileItem, String login, boolean withAccounting) throws RepositoryException, PluginInitializationException, PluginNotFoundException, BackendGenericError {
final InputStream streamToWrite = storageBackend.download(fileItem.getContent().getStorageId());
FolderManager folderManager = folderPluginHandler.getFolderManager(fileItem);
final InputStream streamToWrite = folderManager.getStorageBackend().download(fileItem.getContent());
if (withAccounting)
accountingHandler.createReadObj(fileItem.getTitle(), ses, (Node) fileItem.getRelatedNode(), login, true);
@ -877,11 +901,8 @@ public class ItemsManager extends Impersonable{
if (!(destinationItem instanceof FolderItem))
throw new InvalidItemException("destination item is not a folder");
boolean movingSharedItemOutside = item.isShared() && (!destinationItem.isShared() || !getSharedParentNode(nodeToMove).getIdentifier().equals(getSharedParentNode(destination).getIdentifier()));
try {
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,currentUser);
ses.getWorkspace().getLockManager().lock(nodeToMove.getPath(), true, true, 0,currentUser);
@ -899,7 +920,9 @@ public class ItemsManager extends Impersonable{
if (movingSharedItemOutside)
item2Node.updateOwnerOnSubTree(nodeToMove, currentUser);
//folderHandler.onMove(source, destination);
accountingHandler.createFolderAddObj(uniqueName, item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, destination, false);
accountingHandler.createFolderRemoveObj(item.getTitle(), item.getClass().getSimpleName(), mimeTypeForAccounting, ses, currentUser, originalParent, false);
ses.save();
@ -958,9 +981,12 @@ public class ItemsManager extends Impersonable{
Node newNode = ses.getNode(newPath);
newFileIdentifier = newNode.getIdentifier();
//TODO: folderHandler.onCopy(source, destination);
if (item instanceof AbstractFileItem) {
FolderManager manager = folderPluginHandler.getFolderManager(item);
((AbstractFileItem) item).getContent().setRemotePath(newPath);
String newStorageID = storageBackend.copy((AbstractFileItem) item);
String newStorageID = manager.getStorageBackend().onCopy((AbstractFileItem) item);
((AbstractFileItem) item).getContent().setStorageId(newStorageID);
item2Node.replaceContent(newNode, (AbstractFileItem) item, ItemAction.CLONED);
}
@ -1213,6 +1239,9 @@ public class ItemsManager extends Impersonable{
if (itemToDelete instanceof SharedFolder || itemToDelete instanceof VreFolder || (itemToDelete instanceof FolderItem && Utils.hasSharedChildren(nodeToDelete)))
throw new InvalidItemException("SharedFolder, VreFolder or folders with shared children cannot be deleted");
if (itemToDelete.isExternalManaged() && !force)
throw new InvalidItemException("External managed Items cannot be moved to Trash");
log.debug("item is trashed? {}", itemToDelete.isTrashed());
if (!itemToDelete.isTrashed() && !force) {

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

@ -194,7 +194,15 @@ public class UserManager {
//creating Vre container folder
FolderCreationParameters vreFolderParameters = FolderCreationParameters.builder().name(Constants.PERSONAL_VRES_FOLDER_PARENT_NAME).description("vre folder container of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(vreFolderParameters, null);
//creating inbox folder
FolderCreationParameters inboxFolderParameters = FolderCreationParameters.builder().name(Constants.INBOX_FOLDER_NAME).description("inbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(inboxFolderParameters, null);
//creating outbox folder
FolderCreationParameters outboxFolderParameters = FolderCreationParameters.builder().name(Constants.OUTBOX_FOLDER_NAME).description("outbox of "+user).author(user).on(userHome.getIdentifier()).with(session).build();
Utils.createFolderInternally(outboxFolderParameters, null);
session.save();
}catch(StorageHubException she ){
log.error(she.getErrorMessage(), she);

@ -42,11 +42,11 @@ import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.StorageHubAppllicationManager;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
import org.gcube.data.access.storagehub.handlers.TrashHandler;
import org.gcube.data.access.storagehub.handlers.items.Item2NodeConverter;
import org.gcube.data.access.storagehub.handlers.items.Node2ItemConverter;
import org.gcube.data.access.storagehub.handlers.items.builders.FolderCreationParameters;
import org.gcube.data.access.storagehub.handlers.plugins.FolderPluginHandler;
import org.gcube.data.access.storagehub.handlers.vres.VRE;
import org.gcube.data.access.storagehub.handlers.vres.VREManager;
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
@ -57,7 +57,7 @@ import org.slf4j.LoggerFactory;
@Path("")
@Path("/")
@ManagedBy(StorageHubAppllicationManager.class)
public class WorkspaceManager extends Impersonable{
@ -90,11 +90,11 @@ public class WorkspaceManager extends Impersonable{
@Inject Node2ItemConverter node2Item;
@Inject Item2NodeConverter item2Node;
@Inject StorageBackendHandler storageBackend;
@Inject
FolderPluginHandler folderHandler;
@Path("")
@Path("/")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
@ -410,7 +410,7 @@ public class WorkspaceManager extends Impersonable{
@GET
public String getTotalItemsCount(){
InnerMethodName.instance.set("getTotalItemsCount");
return storageBackend.getTotalItemsCount();
return folderHandler.getDefault().getStorageBackend().getTotalItemsCount();
}
@ -418,7 +418,7 @@ public class WorkspaceManager extends Impersonable{
@GET
public String getTotalVolume(){
InnerMethodName.instance.set("getTotalSize");
return storageBackend.getTotalVolume();
return folderHandler.getDefault().getStorageBackend().getTotalSizeStored();
}

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

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

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

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

@ -25,7 +25,7 @@ The projects leading to this software have received funding from a series of
Version
--------------------------------------------------
1.3.0-SNAPSHOT (20210407-065343)
1.3.0-SNAPSHOT (20210504-093803)
Please see the file named "changelog.xml" in this directory for the release notes.

Loading…
Cancel
Save