2018-05-17 12:51:56 +02:00
|
|
|
package org.gcube.data.access.storagehub.services;
|
|
|
|
|
|
|
|
import java.io.BufferedInputStream;
|
2018-10-25 16:33:23 +02:00
|
|
|
import java.io.IOException;
|
2018-05-17 12:51:56 +02:00
|
|
|
import java.io.InputStream;
|
2019-07-29 16:26:08 +02:00
|
|
|
import java.net.URL;
|
2018-10-25 16:33:23 +02:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.UUID;
|
2018-05-17 12:51:56 +02:00
|
|
|
import java.util.concurrent.Callable;
|
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
|
import java.util.concurrent.Executors;
|
|
|
|
import java.util.concurrent.Future;
|
|
|
|
|
|
|
|
import javax.inject.Inject;
|
2018-10-25 16:33:23 +02:00
|
|
|
import javax.jcr.ItemNotFoundException;
|
2018-05-17 12:51:56 +02:00
|
|
|
import javax.jcr.Node;
|
2018-06-05 15:33:36 +02:00
|
|
|
import javax.jcr.PathNotFoundException;
|
2018-10-25 16:33:23 +02:00
|
|
|
import javax.jcr.RepositoryException;
|
2018-05-17 12:51:56 +02:00
|
|
|
import javax.jcr.Session;
|
2019-02-14 12:01:59 +01:00
|
|
|
import javax.jcr.lock.LockException;
|
2018-05-17 12:51:56 +02:00
|
|
|
import javax.servlet.ServletContext;
|
|
|
|
import javax.ws.rs.Consumes;
|
2018-10-25 16:33:23 +02:00
|
|
|
import javax.ws.rs.FormParam;
|
2018-05-17 12:51:56 +02:00
|
|
|
import javax.ws.rs.POST;
|
|
|
|
import javax.ws.rs.Path;
|
|
|
|
import javax.ws.rs.PathParam;
|
|
|
|
import javax.ws.rs.core.Context;
|
|
|
|
import javax.ws.rs.core.MediaType;
|
2019-03-26 17:09:26 +01:00
|
|
|
import javax.ws.rs.core.Response;
|
2018-05-17 12:51:56 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
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;
|
2018-05-17 12:51:56 +02:00
|
|
|
import org.apache.tika.config.TikaConfig;
|
|
|
|
import org.apache.tika.detect.Detector;
|
|
|
|
import org.apache.tika.io.TikaInputStream;
|
|
|
|
import org.apache.tika.metadata.Metadata;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.authorization.library.AuthorizedTasks;
|
2018-05-17 12:51:56 +02:00
|
|
|
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.gxrest.response.outbound.GXOutboundErrorResponse;
|
|
|
|
import org.gcube.common.storagehub.model.NodeConstants;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.BackendGenericError;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.IdNotFoundException;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.InvalidCallParameters;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.InvalidItemException;
|
2019-03-27 15:51:27 +01:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.ItemLockedException;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.storagehub.model.exceptions.StorageHubException;
|
|
|
|
import org.gcube.common.storagehub.model.exceptions.UserNotAuthorizedException;
|
2018-05-17 12:51:56 +02:00
|
|
|
import org.gcube.common.storagehub.model.items.AbstractFileItem;
|
|
|
|
import org.gcube.common.storagehub.model.items.FolderItem;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.common.storagehub.model.items.GCubeItem;
|
2019-07-05 12:09:16 +02:00
|
|
|
import org.gcube.common.storagehub.model.storages.MetaInfo;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.gcube.common.storagehub.model.types.ItemAction;
|
|
|
|
import org.gcube.data.access.storagehub.AuthorizationChecker;
|
2018-05-17 12:51:56 +02:00
|
|
|
import org.gcube.data.access.storagehub.MultipleOutputStream;
|
|
|
|
import org.gcube.data.access.storagehub.Utils;
|
2018-05-28 12:01:01 +02:00
|
|
|
import org.gcube.data.access.storagehub.accounting.AccountingHandler;
|
2018-07-03 12:15:35 +02:00
|
|
|
import org.gcube.data.access.storagehub.handlers.CredentialHandler;
|
2018-10-25 16:33:23 +02:00
|
|
|
import org.gcube.data.access.storagehub.handlers.Item2NodeConverter;
|
|
|
|
import org.gcube.data.access.storagehub.handlers.Node2ItemConverter;
|
2019-07-05 12:09:16 +02:00
|
|
|
import org.gcube.data.access.storagehub.handlers.StorageBackendHandler;
|
2018-05-17 12:51:56 +02:00
|
|
|
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;
|
2018-07-05 16:26:08 +02:00
|
|
|
import org.gcube.smartgears.utils.InnerMethodName;
|
|
|
|
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
|
|
|
import org.glassfish.jersey.media.multipart.FormDataParam;
|
2018-05-17 12:51:56 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-06-29 16:59:24 +02:00
|
|
|
@Path("items")
|
2018-05-17 12:51:56 +02:00
|
|
|
public class ItemsCreator {
|
|
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class);
|
|
|
|
|
|
|
|
private static ExecutorService executor = Executors.newFixedThreadPool(100);
|
|
|
|
|
|
|
|
@Context ServletContext context;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
@Inject
|
|
|
|
RepositoryInitializer repository;
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
ContentHandlerFactory contenthandlerFactory;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
@Inject
|
|
|
|
VersionHandler versionHandler;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-28 12:01:01 +02:00
|
|
|
@Inject
|
|
|
|
AuthorizationChecker authChecker;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-28 12:01:01 +02:00
|
|
|
@Inject
|
|
|
|
AccountingHandler accountingHandler;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
@Inject Node2ItemConverter node2Item;
|
|
|
|
@Inject Item2NodeConverter item2Node;
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2019-07-05 12:09:16 +02:00
|
|
|
@Inject StorageBackendHandler storageBackend;
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
//@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
|
2018-05-17 12:51:56 +02:00
|
|
|
@POST
|
2018-05-28 12:01:01 +02:00
|
|
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
2018-07-12 15:44:11 +02:00
|
|
|
@Path("/{id}/create/FOLDER")
|
2019-05-06 18:56:22 +02:00
|
|
|
public Response createFolder(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("hidden") boolean hidden) {
|
2018-10-25 16:33:23 +02:00
|
|
|
InnerMethodName.instance.set("createItem(FOLDER)");
|
|
|
|
log.info("create folder item called");
|
2018-05-17 12:51:56 +02:00
|
|
|
Session ses = null;
|
2018-10-25 16:33:23 +02:00
|
|
|
String toReturn = null;
|
2018-05-17 12:51:56 +02:00
|
|
|
try{
|
|
|
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
|
2018-07-03 12:15:35 +02:00
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
Node destination;
|
|
|
|
try {
|
2019-03-27 15:51:27 +01:00
|
|
|
destination = ses.getNodeByIdentifier(id);
|
2019-04-01 17:50:43 +02:00
|
|
|
}catch(RepositoryException inf) {
|
2018-10-25 16:33:23 +02:00
|
|
|
throw new IdNotFoundException(id);
|
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
|
|
throw new InvalidItemException("the destination item is not a folder");
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
|
|
|
|
2019-06-27 15:14:11 +02:00
|
|
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
2018-10-25 16:33:23 +02:00
|
|
|
Node newNode;
|
2019-06-27 15:14:11 +02:00
|
|
|
try {
|
|
|
|
newNode = Utils.createFolderInternally(ses, destination, name, description, hidden, login, accountingHandler);
|
|
|
|
ses.save();
|
|
|
|
} finally {
|
2018-10-25 16:33:23 +02:00
|
|
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
2019-06-27 15:14:11 +02:00
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
|
|
|
toReturn = newNode.getIdentifier();
|
|
|
|
}catch(StorageHubException she ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
2019-04-09 18:10:42 +02:00
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2018-10-25 16:33:23 +02:00
|
|
|
}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();
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
2019-05-06 18:56:22 +02:00
|
|
|
return Response.ok(toReturn).build();
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2019-07-29 16:26:08 +02:00
|
|
|
@POST
|
|
|
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
|
|
|
@Path("/{id}/create/URL")
|
|
|
|
public Response createURL(@PathParam("id") String id, @FormParam("name") String name, @FormParam("description") String description, @FormParam("value") URL value) {
|
|
|
|
InnerMethodName.instance.set("createItem(URL)");
|
|
|
|
log.info("create url called");
|
|
|
|
Session ses = null;
|
|
|
|
String toReturn = null;
|
|
|
|
try{
|
|
|
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
|
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
|
|
|
|
|
|
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
|
|
|
|
|
|
|
|
Node destination;
|
|
|
|
try {
|
|
|
|
destination = ses.getNodeByIdentifier(id);
|
|
|
|
}catch(RepositoryException inf) {
|
|
|
|
throw new IdNotFoundException(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
|
|
throw new InvalidItemException("the destination item is not a folder");
|
|
|
|
|
|
|
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
|
|
|
|
|
|
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
|
|
|
Node newNode;
|
|
|
|
try {
|
|
|
|
newNode = Utils.createURLInternally(ses, destination, name, value, description, login, accountingHandler);
|
|
|
|
ses.save();
|
|
|
|
} finally {
|
|
|
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
|
|
|
}
|
|
|
|
|
|
|
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
|
|
|
toReturn = newNode.getIdentifier();
|
|
|
|
}catch(StorageHubException she ){
|
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
|
|
|
}catch(RepositoryException re ){
|
|
|
|
log.error("jcr error creating item", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
|
|
}finally{
|
|
|
|
if (ses!=null)
|
|
|
|
ses.logout();
|
|
|
|
|
|
|
|
}
|
|
|
|
return Response.ok(toReturn).build();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
@POST
|
|
|
|
@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;
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
try{
|
|
|
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
Node destination;
|
|
|
|
try {
|
2019-03-27 15:51:27 +01:00
|
|
|
destination = ses.getNodeByIdentifier(id);
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(ItemNotFoundException inf) {
|
|
|
|
throw new IdNotFoundException(id);
|
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
|
|
throw new InvalidItemException("the destination item is not a folder");
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier(), true);
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2019-04-15 15:57:12 +02:00
|
|
|
|
2019-04-01 17:50:43 +02:00
|
|
|
Utils.acquireLockWithWait(ses, destination.getPath(), false, login, 10);
|
2019-04-15 15:57:12 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
Node newNode;
|
|
|
|
try {
|
|
|
|
newNode = Utils.createGcubeItemInternally(ses, destination, item.getName(), item.getDescription(), login, item, accountingHandler);
|
|
|
|
ses.save();
|
|
|
|
} finally {
|
|
|
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
|
|
|
}
|
2018-05-17 12:51:56 +02:00
|
|
|
|
2018-06-20 16:59:41 +02:00
|
|
|
log.info("item with id {} correctly created",newNode.getIdentifier());
|
2018-10-25 16:33:23 +02:00
|
|
|
toReturn = newNode.getIdentifier();
|
|
|
|
}catch(StorageHubException she ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(RepositoryException re ){
|
|
|
|
log.error("jcr error creating item", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating item", re));
|
|
|
|
}finally{
|
|
|
|
if (ses!=null)
|
2018-05-17 12:51:56 +02:00
|
|
|
ses.logout();
|
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
return toReturn;
|
2018-05-17 12:51:56 +02:00
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
@POST
|
2018-07-05 16:26:08 +02:00
|
|
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
2018-05-17 12:51:56 +02:00
|
|
|
@Path("/{id}/create/FILE")
|
2018-10-25 16:33:23 +02:00
|
|
|
public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name,
|
2018-07-05 16:26:08 +02:00
|
|
|
@FormDataParam("description") String description,
|
|
|
|
@FormDataParam("file") InputStream stream,
|
|
|
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
|
|
|
InnerMethodName.instance.set("createItem(FILE)");
|
2018-10-25 16:33:23 +02:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
Session ses = null;
|
2018-10-25 16:33:23 +02:00
|
|
|
String toReturn = null;
|
2018-05-17 12:51:56 +02:00
|
|
|
try{
|
2019-02-14 12:01:59 +01:00
|
|
|
if (name==null || name.trim().isEmpty() || description ==null) throw new InvalidCallParameters("name or description are null or empty");
|
2018-05-17 12:51:56 +02:00
|
|
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-07-03 12:15:35 +02:00
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
Node destination = ses.getNodeByIdentifier(id);
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-06-29 16:59:24 +02:00
|
|
|
log.info("create file called with filename {} in dir {} ", name, destination.getPath() );
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
|
|
throw new InvalidItemException("the destination item is not a folder");
|
2019-03-27 15:51:27 +01:00
|
|
|
|
|
|
|
|
2019-02-14 12:01:59 +01:00
|
|
|
log.info("session: {}",ses.toString());
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2019-04-15 15:57:12 +02:00
|
|
|
Node newNode = createFileItemInternally(ses, destination, stream, name, description, login, true);
|
2019-03-13 18:33:24 +01:00
|
|
|
ses.save();
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-06-05 15:33:36 +02:00
|
|
|
versionHandler.checkinContentNode(newNode, ses);
|
2018-06-20 16:59:41 +02:00
|
|
|
log.info("file with id {} correctly created",newNode.getIdentifier());
|
2018-10-25 16:33:23 +02:00
|
|
|
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 ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2019-02-14 12:01:59 +01:00
|
|
|
}catch(Throwable e ){
|
|
|
|
log.error("unexpected error", e);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError(e));
|
|
|
|
}finally{
|
|
|
|
if (ses!=null && ses.isLive()) {
|
|
|
|
log.info("session closed");
|
2018-05-17 12:51:56 +02:00
|
|
|
ses.logout();
|
2019-02-14 12:01:59 +01:00
|
|
|
}
|
2018-05-17 12:51:56 +02:00
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
return toReturn;
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-04-15 15:57:12 +02:00
|
|
|
private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, UserNotAuthorizedException, ItemLockedException, BackendGenericError{
|
2018-10-25 16:33:23 +02:00
|
|
|
|
|
|
|
//to inherit hidden property
|
|
|
|
//item.setHidden(destinationItem.isHidden());
|
|
|
|
|
|
|
|
Node newNode;
|
|
|
|
try {
|
|
|
|
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationNode.getPath()), name).toPath());
|
|
|
|
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
|
2019-05-06 18:56:22 +02:00
|
|
|
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
|
2019-04-15 15:57:12 +02:00
|
|
|
if (withLock) {
|
|
|
|
try {
|
|
|
|
ses.getWorkspace().getLockManager().lock(newNode.getPath(), true, true, 0,login);
|
|
|
|
}catch (LockException le) {
|
|
|
|
throw new ItemLockedException(le);
|
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
}
|
2019-03-26 18:22:04 +01:00
|
|
|
try {
|
|
|
|
versionHandler.checkoutContentNode(newNode, ses);
|
|
|
|
log.trace("replacing content of class {}",item.getContent().getClass());
|
|
|
|
item2Node.replaceContent(newNode,item, ItemAction.UPDATED);
|
|
|
|
accountingHandler.createFileUpdated(item.getTitle(), ses, newNode, false);
|
2019-04-01 17:50:43 +02:00
|
|
|
ses.save();
|
2019-03-26 18:22:04 +01:00
|
|
|
}finally {
|
2019-04-15 15:57:12 +02:00
|
|
|
if (withLock) ses.getWorkspace().getLockManager().unlock(newNode.getPath());
|
2019-03-26 18:22:04 +01:00
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(PathNotFoundException pnf) {
|
|
|
|
authChecker.checkWriteAuthorizationControl(ses, destinationNode.getIdentifier(), true);
|
2019-05-06 18:56:22 +02:00
|
|
|
AbstractFileItem item = fillItemWithContent(stream, name, description, destinationNode.getPath(), login);
|
2019-04-15 15:57:12 +02:00
|
|
|
if (withLock) {
|
|
|
|
try {
|
|
|
|
log.debug("trying to acquire lock");
|
|
|
|
Utils.acquireLockWithWait(ses, destinationNode.getPath(), false, login, 10);
|
|
|
|
}catch (LockException le) {
|
|
|
|
throw new ItemLockedException(le);
|
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
}
|
2019-03-26 18:22:04 +01:00
|
|
|
try {
|
|
|
|
newNode = item2Node.getNode(destinationNode, item);
|
2019-04-01 17:50:43 +02:00
|
|
|
ses.save();
|
2019-03-26 18:22:04 +01:00
|
|
|
}finally {
|
2019-04-15 15:57:12 +02:00
|
|
|
if (withLock) ses.getWorkspace().getLockManager().unlock(destinationNode.getPath());
|
2019-03-26 18:22:04 +01:00
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
versionHandler.makeVersionableContent(newNode, ses);
|
2019-02-27 17:49:55 +01:00
|
|
|
accountingHandler.createFolderAddObj(name, item.getClass().getSimpleName(), item.getContent().getMimeType(), ses, newNode, false);
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
return newNode;
|
2018-05-17 12:51:56 +02:00
|
|
|
}
|
2019-06-27 15:14:11 +02:00
|
|
|
|
2019-05-06 18:56:22 +02:00
|
|
|
private AbstractFileItem fillItemWithContent(InputStream stream, String name, String description, String path, String login) throws BackendGenericError{
|
|
|
|
ContentHandler handler = getContentHandler(stream , name, path, login);
|
|
|
|
AbstractFileItem item =handler.buildItem(name, description, login);
|
|
|
|
return item ;
|
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
|
2018-07-12 15:44:11 +02:00
|
|
|
@POST
|
|
|
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
|
|
|
@Path("/{id}/create/ARCHIVE")
|
2018-10-25 16:33:23 +02:00
|
|
|
public String uploadArchive(@PathParam("id") String id, @FormDataParam("parentFolderName") String parentFolderName,
|
2018-07-12 15:44:11 +02:00
|
|
|
@FormDataParam("file") InputStream stream,
|
|
|
|
@FormDataParam("file") FormDataContentDisposition fileDetail){
|
2018-10-25 16:33:23 +02:00
|
|
|
InnerMethodName.instance.set("createItem(ARCHIVE)");
|
|
|
|
|
2018-07-12 15:44:11 +02:00
|
|
|
Session ses = null;
|
2018-10-25 16:33:23 +02:00
|
|
|
String toReturn = null;
|
2018-07-12 15:44:11 +02:00
|
|
|
try{
|
2018-10-25 16:33:23 +02:00
|
|
|
if (parentFolderName==null) throw new InvalidCallParameters("new folder name is null");
|
|
|
|
|
2018-07-12 15:44:11 +02:00
|
|
|
final String login = AuthorizationProvider.instance.get().getClient().getId();
|
|
|
|
|
|
|
|
ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context));
|
|
|
|
|
|
|
|
Node destination = ses.getNodeByIdentifier(id);
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
if (!node2Item.checkNodeType(destination, FolderItem.class))
|
|
|
|
throw new InvalidItemException("the destination item is not a folder");
|
2018-07-12 15:44:11 +02:00
|
|
|
|
2019-03-27 15:51:27 +01:00
|
|
|
authChecker.checkWriteAuthorizationControl(ses, destination.getIdentifier() , true);
|
2018-07-12 15:44:11 +02:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
try {
|
2019-03-27 15:51:27 +01:00
|
|
|
ses.getWorkspace().getLockManager().lock(destination.getPath(), false, true, 0,login);
|
|
|
|
}catch (LockException le) {
|
|
|
|
throw new ItemLockedException(le);
|
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
|
2019-03-27 15:51:27 +01:00
|
|
|
Node parentDirectoryNode = Utils.createFolderInternally(ses, destination, parentFolderName, "", false, login, accountingHandler);
|
|
|
|
try {
|
|
|
|
if (ses.getWorkspace().getLockManager().isLocked(destination.getPath()))
|
|
|
|
ses.getWorkspace().getLockManager().unlock(destination.getPath());
|
|
|
|
} catch (Throwable t){
|
|
|
|
log.warn("error unlocking {}", destination.getPath(), t);
|
|
|
|
}
|
2018-10-25 16:33:23 +02:00
|
|
|
|
2019-03-27 15:51:27 +01:00
|
|
|
Set<Node> fileNodes = new HashSet<>();
|
|
|
|
|
|
|
|
|
|
|
|
HashMap<String, Node> directoryNodeMap = new HashMap<>();
|
|
|
|
|
|
|
|
try (ArchiveInputStream input = new ArchiveStreamFactory()
|
|
|
|
.createArchiveInputStream(new BufferedInputStream(stream, 1024*64))){
|
|
|
|
ArchiveEntry entry;
|
|
|
|
while ((entry = input.getNextEntry()) != null) {
|
|
|
|
if (entry.isDirectory()) {
|
|
|
|
String entirePath = entry.getName();
|
|
|
|
String name = entirePath.replaceAll("(.*/)*(.*)/", "$2");
|
|
|
|
String parentPath = entirePath.replaceAll("(.*/)*(.*)/", "$1");
|
|
|
|
log.debug("creating directory with entire path {}, name {}, parentPath {} ", entirePath, name, parentPath);
|
|
|
|
Node createdNode;
|
|
|
|
if (parentPath.isEmpty()) {
|
|
|
|
createdNode = Utils.createFolderInternally(ses, parentDirectoryNode, name, "", false, login, accountingHandler);
|
|
|
|
}else {
|
|
|
|
Node parentNode = directoryNodeMap.get(parentPath);
|
|
|
|
createdNode = Utils.createFolderInternally(ses, parentNode, name, "", false, login, accountingHandler);
|
|
|
|
}
|
|
|
|
directoryNodeMap.put(entirePath, createdNode);
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
try {
|
2018-10-25 16:33:23 +02:00
|
|
|
String entirePath = entry.getName();
|
2019-03-27 15:51:27 +01:00
|
|
|
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())
|
2019-04-15 15:57:12 +02:00
|
|
|
fileNode = createFileItemInternally(ses, parentDirectoryNode, input, name, "", login, false);
|
2019-03-27 15:51:27 +01:00
|
|
|
else {
|
2018-10-25 16:33:23 +02:00
|
|
|
Node parentNode = directoryNodeMap.get(parentPath);
|
2019-04-15 15:57:12 +02:00
|
|
|
fileNode = createFileItemInternally(ses, parentNode, input, name, "", login, false);
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
2019-03-27 15:51:27 +01:00
|
|
|
fileNodes.add(fileNode);
|
|
|
|
}catch(Exception e) {
|
|
|
|
log.warn("error getting file {}",entry.getName(),e);
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-12 15:44:11 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-03-27 15:51:27 +01:00
|
|
|
ses.save();
|
|
|
|
for (Node node : fileNodes)
|
|
|
|
versionHandler.checkinContentNode(node, ses);
|
|
|
|
toReturn = parentDirectoryNode.getIdentifier();
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
}catch(RepositoryException | ArchiveException | IOException re){
|
|
|
|
log.error("jcr error extracting archive", re);
|
|
|
|
GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re));
|
|
|
|
}catch(StorageHubException she ){
|
2019-03-26 17:09:26 +01:00
|
|
|
log.error(she.getErrorMessage(), she);
|
|
|
|
GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus()));
|
2018-07-12 15:44:11 +02:00
|
|
|
} finally{
|
2018-10-25 16:33:23 +02:00
|
|
|
if (ses!=null)
|
2018-07-12 15:44:11 +02:00
|
|
|
ses.logout();
|
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
}
|
|
|
|
return toReturn;
|
2018-07-12 15:44:11 +02:00
|
|
|
}
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
private ContentHandler getContentHandler(InputStream stream , String name, String path, String login) throws BackendGenericError {
|
|
|
|
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
final MultipleOutputStream mos;
|
|
|
|
try{
|
|
|
|
mos = new MultipleOutputStream(stream, 2);
|
|
|
|
}catch (IOException e) {
|
|
|
|
throw new BackendGenericError(e);
|
|
|
|
}
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
Callable<ContentHandler> mimeTypeDector = new Callable<ContentHandler>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ContentHandler call() throws Exception {
|
|
|
|
ContentHandler handler =null;
|
2018-07-12 15:44:11 +02:00
|
|
|
long start = System.currentTimeMillis();
|
|
|
|
log.debug("TIMING: reading the mimetype - start");
|
2018-10-25 16:33:23 +02:00
|
|
|
try(InputStream is1 = new BufferedInputStream(mos.get(), 1024*64)){
|
2018-05-17 12:51:56 +02:00
|
|
|
org.apache.tika.mime.MediaType mediaType = null;
|
|
|
|
TikaConfig config = TikaConfig.getDefaultConfig();
|
|
|
|
Detector detector = config.getDetector();
|
|
|
|
TikaInputStream stream = TikaInputStream.get(is1);
|
|
|
|
Metadata metadata = new Metadata();
|
|
|
|
metadata.add(Metadata.RESOURCE_NAME_KEY, name);
|
|
|
|
mediaType = detector.detect(stream, metadata);
|
|
|
|
String mimeType = mediaType.getBaseType().toString();
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
handler = contenthandlerFactory.create(mimeType);
|
2018-07-05 16:26:08 +02:00
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
is1.reset();
|
2019-07-29 16:26:08 +02:00
|
|
|
handler.initiliseSpecificContent(is1, name, mimeType);
|
|
|
|
|
2018-07-12 15:44:11 +02:00
|
|
|
log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start);
|
2018-05-17 12:51:56 +02:00
|
|
|
} catch (Throwable e) {
|
2018-07-05 16:26:08 +02:00
|
|
|
log.error("error retrieving mimeType",e);
|
2018-05-17 12:51:56 +02:00
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
return handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
Callable<MetaInfo> uploader = new Callable<MetaInfo>() {
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public MetaInfo call() throws Exception {
|
2018-10-25 16:33:23 +02:00
|
|
|
try(InputStream is1 = mos.get()){
|
|
|
|
String uid = UUID.randomUUID().toString();
|
|
|
|
String remotePath= String.format("%s/%s-%s",path,uid,name);
|
2019-07-05 12:09:16 +02:00
|
|
|
MetaInfo info = storageBackend.upload(is1, remotePath);
|
2018-07-05 16:26:08 +02:00
|
|
|
return info;
|
|
|
|
}catch (Throwable e) {
|
2019-07-05 12:09:16 +02:00
|
|
|
log.error("error writing content",e );
|
2018-07-05 16:26:08 +02:00
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
|
2018-05-17 12:51:56 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
Future<ContentHandler> detectorF = executor.submit(AuthorizedTasks.bind(mimeTypeDector));
|
|
|
|
Future<MetaInfo> uploaderF = executor.submit(AuthorizedTasks.bind(uploader));
|
|
|
|
|
2018-07-12 15:44:11 +02:00
|
|
|
long start = System.currentTimeMillis();
|
2018-10-25 16:33:23 +02:00
|
|
|
log.debug("TIMING: writing the stream - start");
|
|
|
|
try {
|
|
|
|
mos.startWriting();
|
|
|
|
log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start);
|
2019-03-27 15:51:27 +01:00
|
|
|
|
2018-10-25 16:33:23 +02:00
|
|
|
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);
|
|
|
|
}
|
2018-05-17 12:51:56 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|