diff --git a/CHANGELOG.md b/CHANGELOG.md index af805d6..007e5c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v1.5.0-SNAPSHOT] - [2021-10-15] + + + ## [v1.4.0] - [2021-10-07] - slow query removed from VRE retrieving and recents diff --git a/src/main/java/org/gcube/data/access/storagehub/MultipleOutputStream.java b/src/main/java/org/gcube/data/access/storagehub/MultipleOutputStream.java index 07936d9..1bdb051 100644 --- a/src/main/java/org/gcube/data/access/storagehub/MultipleOutputStream.java +++ b/src/main/java/org/gcube/data/access/storagehub/MultipleOutputStream.java @@ -25,7 +25,7 @@ public class MultipleOutputStream { this.is = is; - logger.debug("requested {} piped streams ",number); + logger.debug("UPLOAD: requested {} piped streams ",number); pipedInStreams = new MyPipedInputStream[number]; pipedOutStreams = new MyPipedOututStream[number]; @@ -39,6 +39,8 @@ public class MultipleOutputStream { public void startWriting() throws IOException{ + logger.debug("UPLOAD: started writing multiple streams"); + BufferedInputStream bis = new BufferedInputStream(is); byte[] buf = new byte[1024*64]; int read=-1; @@ -49,7 +51,8 @@ public class MultipleOutputStream { pipedOutStreams[i].write(buf, 0, read); } } - + + logger.trace("UPLOAD: written byte "+writeTot); writeTot+= read; if (allOutStreamClosed()) @@ -64,7 +67,7 @@ public class MultipleOutputStream { } } - logger.debug("total written {} ",writeTot); + logger.debug("UPLOAD: total written {} ",writeTot); } diff --git a/src/main/java/org/gcube/data/access/storagehub/handlers/items/ItemHandler.java b/src/main/java/org/gcube/data/access/storagehub/handlers/items/ItemHandler.java index 9b1c82d..dd7c1e6 100644 --- a/src/main/java/org/gcube/data/access/storagehub/handlers/items/ItemHandler.java +++ b/src/main/java/org/gcube/data/access/storagehub/handlers/items/ItemHandler.java @@ -247,7 +247,9 @@ public class ItemHandler { } private Node createFileItemInternally(Session ses, Node destinationNode, InputStream stream, String name, String description, String login, boolean withLock) throws RepositoryException, StorageHubException{ - + + log.debug("UPLOAD: starting preparing file"); + Node newNode; FolderItem destinationItem = node2Item.getItem(destinationNode, Excludes.ALL); FolderManager folderManager = pluginHandler.getFolderManager(destinationItem); @@ -314,14 +316,16 @@ public class ItemHandler { private AbstractFileItem fillItemWithContent(InputStream stream, StorageBackend storageBackend, String name, String description, String relPath, String login) throws BackendGenericError{ + log.debug("UPLOAD: filling content"); ContentHandler handler = getContentHandler(stream, storageBackend, name, relPath, login); AbstractFileItem item =handler.buildItem(name, description, login); return item ; } private ContentHandler getContentHandler(InputStream stream, StorageBackend storageBackend, String name, String relPath, String login) throws BackendGenericError { - - + + log.debug("UPLOAD: handling content"); + final MultipleOutputStream mos; try{ mos = new MultipleOutputStream(stream, 2); @@ -351,7 +355,7 @@ public class ItemHandler { is1.reset(); handler.initiliseSpecificContent(is1, name, mimeType); - log.trace("TIMING: reading the mimetype - finished in {}",System.currentTimeMillis()-start); + log.debug("UPLOAD: reading the mimetype - finished in {}",System.currentTimeMillis()-start); } catch (Throwable e) { log.error("error retrieving mimeType",e); throw new RuntimeException(e); @@ -366,7 +370,9 @@ public class ItemHandler { @Override public MetaInfo call() throws Exception { try(InputStream is1 = mos.get()){ + log.debug("UPLOAD: upload on storage - start"); MetaInfo info = storageBackend.upload(is1, relPath, name); + log.debug("UPLOAD: upload on storage - stop"); return info; }catch (Throwable e) { log.error("error writing content",e ); @@ -380,13 +386,13 @@ public class ItemHandler { Future uploaderF = executor.submit(AuthorizedTasks.bind(uploader)); long start = System.currentTimeMillis(); - log.debug("TIMING: writing the stream - start"); + log.debug("UPLOAD: writing the stream - start"); try { mos.startWriting(); - log.debug("TIMING: writing the stream - finished in {}",System.currentTimeMillis()-start); - + ContentHandler handler = detectorF.get(); MetaInfo info = uploaderF.get(); + log.debug("UPLOAD: writing the stream - finished in {}",System.currentTimeMillis()-start); handler.getContent().setData(NodeConstants.CONTENT_NAME); handler.getContent().setStorageId(info.getStorageId()); handler.getContent().setSize(info.getSize()); diff --git a/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java b/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java index 8cbcdf2..aea21d9 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/ItemsCreator.java @@ -2,17 +2,20 @@ package org.gcube.data.access.storagehub.services; import java.io.IOException; import java.io.InputStream; +import java.net.URI; import java.net.URL; import javax.inject.Inject; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -44,12 +47,12 @@ import org.slf4j.LoggerFactory; public class ItemsCreator extends Impersonable{ private static final Logger log = LoggerFactory.getLogger(ItemsCreator.class); - + @Context ServletContext context; - + RepositoryInitializer repository = StorageHubAppllicationManager.repository; - + @Inject ItemHandler itemHandler; @@ -116,7 +119,7 @@ public class ItemsCreator extends Impersonable{ } return Response.ok(toReturn).build(); } - + @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Path("/{id}/create/URL") @@ -127,7 +130,7 @@ public class ItemsCreator extends Impersonable{ String toReturn = null; try{ ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - + ItemsParameterBuilder builder = URLCreationParameters.builder().name(name).description(description).url(value).on(id).with(ses).author(currentUser); toReturn = itemHandler.create(builder.build()); @@ -147,8 +150,8 @@ public class ItemsCreator extends Impersonable{ } return Response.ok(toReturn).build(); } - - + + @POST @Consumes(MediaType.APPLICATION_JSON) @Path("/{id}/create/GCUBEITEM") @@ -161,7 +164,7 @@ public class ItemsCreator extends Impersonable{ try{ ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); ItemsParameterBuilder builder = GCubeItemCreationParameters.builder().item(item).on(id).with(ses).author(currentUser); - + toReturn = itemHandler.create(builder.build()); }catch(StorageHubException she ){ log.error(she.getErrorMessage(), she); @@ -181,24 +184,26 @@ public class ItemsCreator extends Impersonable{ @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Path("/{id}/create/FILE") - public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name, - @FormDataParam("description") String description, - @FormDataParam("file") InputStream stream, - @FormDataParam("file") FormDataContentDisposition fileDetail){ - InnerMethodName.instance.set("createItem(FILE)"); + public String createFileItemFromUrl(@PathParam("id") String id, @FormParam("name") String name, + @FormParam("description") String description, + @FormParam("url") String url){ + InnerMethodName.instance.set("createItem(FILEFromUrl)"); Session ses = null; String toReturn = null; try{ - + + log.debug("UPLOAD: call started"); ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); - ItemsParameterBuilder builder = FileCreationParameters.builder().name(name).description(description).stream(stream).fileDetails(fileDetail) - .on(id).with(ses).author(currentUser); - - toReturn = itemHandler.create(builder.build()); - + try(InputStream stream = new URI(url).toURL().openStream()){ + ItemsParameterBuilder builder = FileCreationParameters.builder().name(name).description(description).stream(stream) + .on(id).with(ses).author(currentUser); + log.debug("UPLOAD: item prepared"); + toReturn = itemHandler.create(builder.build()); + } + log.debug("UPLOAD: call finished"); }catch(RepositoryException re ){ log.error("jcr error creating file item", re); GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re)); @@ -218,9 +223,118 @@ public class ItemsCreator extends Impersonable{ } - - + @POST + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + @Path("/{id}/create/FILE") + public String createFileItemStream(@PathParam("id") String id, @QueryParam("name") String name, + @QueryParam("description") String description, @Context HttpServletRequest request){ + InnerMethodName.instance.set("createItem(FILEByStream)"); + + Session ses = null; + String toReturn = null; + try{ + + log.debug("UPLOAD: call started"); + ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + ItemsParameterBuilder builder = FileCreationParameters.builder().name(name).description(description).stream(request.getInputStream()) + .on(id).with(ses).author(currentUser); + log.debug("UPLOAD: item prepared"); + toReturn = itemHandler.create(builder.build()); + log.debug("UPLOAD: call finished"); + }catch(RepositoryException re ){ + log.error("jcr error creating file item", re); + GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re)); + }catch(StorageHubException she ){ + log.error(she.getErrorMessage(), she); + GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); + }catch(Throwable e ){ + log.error("unexpected error", e); + GXOutboundErrorResponse.throwException(new BackendGenericError(e)); + }finally{ + if (ses!=null && ses.isLive()) { + log.info("session closed"); + ses.logout(); + } + } + return toReturn; + + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Path("/{id}/create/FILE") + public String createFileItem(@PathParam("id") String id, @FormDataParam("name") String name, + @FormDataParam("description") String description, + @FormDataParam("file") InputStream stream, + @FormDataParam("file") FormDataContentDisposition fileDetail){ + InnerMethodName.instance.set("createItem(FILE)"); + + Session ses = null; + String toReturn = null; + try{ + + log.debug("UPLOAD: call started"); + ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + ItemsParameterBuilder builder = FileCreationParameters.builder().name(name).description(description).stream(stream).fileDetails(fileDetail) + .on(id).with(ses).author(currentUser); + log.debug("UPLOAD: item prepared"); + toReturn = itemHandler.create(builder.build()); + log.debug("UPLOAD: call finished"); + }catch(RepositoryException re ){ + log.error("jcr error creating file item", re); + GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error creating file item", re)); + }catch(StorageHubException she ){ + log.error(she.getErrorMessage(), she); + GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); + }catch(Throwable e ){ + log.error("unexpected error", e); + GXOutboundErrorResponse.throwException(new BackendGenericError(e)); + }finally{ + if (ses!=null && ses.isLive()) { + log.info("session closed"); + ses.logout(); + } + } + return toReturn; + + } + + + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Path("/{id}/create/ARCHIVE") + public String uploadArchiveFromURL(@PathParam("id") String id, @FormParam("parentFolderName") String parentFolderName, + @FormParam("url") String url){ + InnerMethodName.instance.set("createItem(ARCHIVEFromURL)"); + + Session ses = null; + String toReturn = null; + try{ + ses = repository.getRepository().login(CredentialHandler.getAdminCredentials(context)); + try(InputStream stream = new URI(url).toURL().openStream()){ + ItemsParameterBuilder builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(stream) + .on(id).with(ses).author(currentUser); + toReturn = itemHandler.create(builder.build()); + } + + }catch(RepositoryException | ArchiveException | IOException re){ + log.error("jcr error extracting archive", re); + GXOutboundErrorResponse.throwException(new BackendGenericError("jcr error extracting archive", re)); + }catch(StorageHubException she ){ + log.error(she.getErrorMessage(), she); + GXOutboundErrorResponse.throwException(she, Response.Status.fromStatusCode(she.getStatus())); + }catch(Throwable e ){ + log.error("unexpected error", e); + GXOutboundErrorResponse.throwException(new BackendGenericError(e)); + } finally{ + if (ses!=null) + ses.logout(); + + } + return toReturn; + } + @POST @@ -238,7 +352,7 @@ public class ItemsCreator extends Impersonable{ ItemsParameterBuilder builder = ArchiveStructureCreationParameter.builder().parentName(parentFolderName).stream(stream).fileDetails(fileDetail) .on(id).with(ses).author(currentUser); - + toReturn = itemHandler.create(builder.build()); }catch(RepositoryException | ArchiveException | IOException re){ @@ -259,6 +373,6 @@ public class ItemsCreator extends Impersonable{ } - + } diff --git a/src/main/java/org/gcube/data/access/storagehub/services/MessageManager.java b/src/main/java/org/gcube/data/access/storagehub/services/MessageManager.java index ce0a4b2..4699edc 100644 --- a/src/main/java/org/gcube/data/access/storagehub/services/MessageManager.java +++ b/src/main/java/org/gcube/data/access/storagehub/services/MessageManager.java @@ -128,9 +128,10 @@ public class MessageManager extends Impersonable{ Message message = node2Item.getMessageItem(messageNode); Node personalNode = checkRights(currentUser, message); - if (countSharedSet(messageNode)>1) - personalNode.removeShare(); - else { + if (countSharedSet(messageNode)>1) { + log.debug("removing node message "+personalNode.getPath()); + personalNode.remove(); + }else { if (message.isWithAttachments()) { Node attachmentNode = messageNode.getNode(Constants.ATTACHMENTNODE_NAME); List attachments = Utils.getItemList(attachmentNode, Excludes.GET_ONLY_CONTENT, null, true, AbstractFileItem.class); @@ -139,6 +140,7 @@ public class MessageManager extends Impersonable{ messageNode.removeSharedSet(); } ses.save(); + log.debug("removing node message saved"); }catch (ItemNotFoundException e) { log.error("id {} not found",id,e); GXOutboundErrorResponse.throwException(new IdNotFoundException(id, e), Status.NOT_FOUND); @@ -345,7 +347,7 @@ public class MessageManager extends Impersonable{ NodeIterator nodeIt = node.getNodes(); while(nodeIt.hasNext()) { Node child = nodeIt.nextNode(); - log.info("message type "+child.getPrimaryNodeType().getName()); + log.trace("message type "+child.getPrimaryNodeType().getName()); Message message = node2Item.getMessageItem(child); if (message == null) { log.info("message discarded"); @@ -375,13 +377,13 @@ public class MessageManager extends Impersonable{ 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())) + if (messageNode.getPath().startsWith(pathUtil.getInboxPath(user).toPath())) return messageNode; NodeIterator nodeIt = messageNode.getSharedSet(); while (nodeIt.hasNext()) { Node node = nodeIt.nextNode(); - if (node.getPath().startsWith(pathUtil.getWorkspacePath(currentUser).toPath())) + if (node.getPath().startsWith(pathUtil.getInboxPath(user).toPath())) personalNode = node; } if (personalNode == null &&