This commit is contained in:
Lucio Lelii 2018-06-20 14:59:41 +00:00
parent 18ae31e181
commit 0e88826cbf
12 changed files with 487 additions and 265 deletions

View File

@ -11,13 +11,13 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.gcube.data.access</groupId>
<artifactId>storagehub</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.1-SNAPSHOT</version>
<name>storagehub</name>
<packaging>war</packaging>
<properties>
<jackrabbit.version>2.14.0</jackrabbit.version>
<jackrabbit.version>2.16.0</jackrabbit.version>
<tomcat.version>7.0.40</tomcat.version>
<jetty.version>6.1.26</jetty.version>
<tika.version>1.7</tika.version>

View File

@ -1,5 +1,6 @@
package org.gcube.data.access.storagehub;
import static org.gcube.common.storagehub.model.NodeConstants.*;
import java.util.Arrays;
import javax.inject.Singleton;
@ -22,7 +23,7 @@ public class AuthorizationChecker {
public void checkReadAuthorizationControl(Session session, String id) throws Exception{
Node node = session.getNodeByIdentifier(id);
Item item = ItemHandler.getItem(node, Arrays.asList("hl:accounting","jcr:content"));
Item item = ItemHandler.getItem(node, Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
if (item.isShared()) {
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
@ -36,37 +37,46 @@ public class AuthorizationChecker {
private SharedFolder retrieveSharedFolderParent(Item item, Session session) throws Exception{
if (item instanceof SharedFolder) return (SharedFolder)item;
else
return retrieveSharedFolderParent(ItemHandler.getItem(session.getNodeByIdentifier(item.getParentId()), Arrays.asList("hl:accounting","jcr:content")), session);
return retrieveSharedFolderParent(ItemHandler.getItem(session.getNodeByIdentifier(item.getParentId()), Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME)), session);
}
public void checkWriteAuthorizationControl(Session session, String id) throws Exception {
public void checkWriteAuthorizationControl(Session session, String id, boolean isNewItem) throws Exception {
//in case of newItem the id is the parent otherwise the old node to replace
Node node = session.getNodeByIdentifier(id);
Item item = ItemHandler.getItem(node, Arrays.asList("hl:accounting","jcr:content"));
Item item = ItemHandler.getItem(node, Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
if (item.isShared()) {
//put it in a different method
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, node.getPath());
SharedFolder parentShared = retrieveSharedFolderParent(item, session);
JackrabbitAccessControlList accessControlList = AccessControlUtils.getAccessControlList(session, parentShared.getPath());
AccessControlEntry[] entries = accessControlList.getAccessControlEntries();
//put it in a different method
for (AccessControlEntry entry: entries) {
if (entry.getPrincipal().getName().equals(AuthorizationProvider.instance.get().getClient().getId())) {
if (entry.getPrincipal().getName().equals(AuthorizationProvider.instance.get().getClient().getId()) || (parentShared.isVreFolder() && entry.getPrincipal().getName().equals(parentShared.getTitle()))) {
for (Privilege privilege : entry.getPrivileges()){
AccessType access = AccessType.valueOf(privilege.getName());
if (access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId())))
if (isNewItem && access!=AccessType.READ_ONLY)
return;
else throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
else
if (!isNewItem &&
(access==AccessType.ADMINISTRATOR || access==AccessType.WRITE_ALL || (access==AccessType.WRITE_OWNER && item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))))
return;
}
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
}
}
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
} else
if(!item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
if(item.getOwner().equals(AuthorizationProvider.instance.get().getClient().getId()))
return;
throw new IllegalAccessException("Insufficent Provileges to write node with id "+id);
}
/*
/*
private String retrieveOwner(Node node) {
Node nodeOwner;
//get Owner
@ -85,5 +95,5 @@ public class AuthorizationChecker {
}
}
*/
*/
}

View File

@ -7,6 +7,11 @@ import javax.inject.Singleton;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
import javax.jcr.version.VersionManager;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.storagehub.model.items.nodes.accounting.AccountingEntryType;
@ -17,11 +22,12 @@ import org.slf4j.LoggerFactory;
@Singleton
public class AccountingHandler {
/*@Attribute("hl:user")
@Attribute("hl:date")
@Attribute("hl:version")*/
private static final String USER = "hl:user";
private static final String DATE = "hl:date";
private static final String ITEM_NAME = "hl:itemName";
private static final String ITEM_TYPE = "hl:itemType";
private static final String MIME_TYPE = "hl:mimeType";
private static final Logger logger = LoggerFactory.getLogger(AccountingHandler.class);
public void createReadObj(String title, Session ses, Node node, boolean saveHistory ) {
@ -35,19 +41,23 @@ public class AccountingHandler {
Node accountingNodeParent = directoryNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.READ.getNodeTypeDefinition());
accountingNode.setProperty("hl:user", AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty("hl:date", Calendar.getInstance());
accountingNode.setProperty("hl:itemName", title);
/*try {
//VersionManager vManager = ses.getWorkspace().getVersionManager();
//VersionManager versionManager = session.getWorkspace().getVersionManager();
//Version version = versionManager.checkin(node.getPath());
//Version version = vManager.getBaseVersion(node.getNode("jcr:content").getPath());
//accountingNode.setProperty("hl:version", version.getName());
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
try {
VersionManager vManager = ses.getWorkspace().getVersionManager();
VersionHistory history = vManager.getVersionHistory(node.getNode("jcr:content").getPath());
VersionIterator versions = history.getAllVersions();
Version version= null;
while (versions.hasNext()) {
version = versions.nextVersion();
}
if (version!=null)
accountingNode.setProperty("hl:version", version.getName());
}catch(UnsupportedRepositoryOperationException uropex) {
logger.warn("version cannot be retrieved", uropex);
}*/
}
if (saveHistory) ses.save();
} catch (RepositoryException e) {
logger.warn("error trying to retrieve accountign node",e);
@ -65,12 +75,12 @@ public class AccountingHandler {
Node accountingNodeParent = directoryNode.getNode(NodeProperty.ACCOUNTING.toString());
Node accountingNode = accountingNodeParent.addNode(UUID.randomUUID().toString(),AccountingEntryType.ADD.getNodeTypeDefinition());
accountingNode.setProperty("hl:user", AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty("hl:date", Calendar.getInstance());
accountingNode.setProperty("hl:itemName", title);
accountingNode.setProperty("hl:itemType", itemType);
accountingNode.setProperty(USER, AuthorizationProvider.instance.get().getClient().getId());
accountingNode.setProperty(DATE, Calendar.getInstance());
accountingNode.setProperty(ITEM_NAME, title);
accountingNode.setProperty(ITEM_TYPE, itemType);
if (mimeType!=null)
accountingNode.setProperty("hl:mimeType", mimeType);
accountingNode.setProperty(MIME_TYPE, mimeType);
if (saveHistory) ses.save();
} catch (RepositoryException e) {

View File

@ -142,14 +142,13 @@ public class ItemHandler {
@SuppressWarnings("rawtypes")
Class returnType = field.getType();
field.set(obj, getPropertyValue(returnType, node.getProperty(attribute.value())));
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), clazz.getName(), node.getName());
}catch(PathNotFoundException e){
logger.debug("the current node dosn't contain {} property",attribute.value());
logger.trace("the current node dosn't contain {} property",attribute.value());
} catch (Exception e ) {
logger.warn("error setting value",e);
}
} else if (field.isAnnotationPresent(MapAttribute.class)){
//logger.debug("found field {} of type annotated as MapAttribute in class {}", field.getName(), clazz.getName());
logger.trace("found field {} of type annotated as MapAttribute in class {} and node name {}", field.getName(), clazz.getName(), node.getName());
field.setAccessible(true);
String exclude = field.getAnnotation(MapAttribute.class).excludeStartWith();
Map<String, Object> mapToset = new HashMap<String, Object>();
@ -159,9 +158,11 @@ public class ItemHandler {
Property prop = iterator.nextProperty();
if (!exclude.isEmpty() && prop.getName().startsWith(exclude)) continue;
try{
logger.trace("adding {} in the map",prop.getName());
mapToset.put(prop.getName(), getPropertyValue(prop));
}catch(PathNotFoundException e){
logger.debug("the property [] is not mapped",prop.getName());
logger.warn("the property {} is not mapped",prop.getName(),e);
} catch (Exception e ) {
logger.warn("error setting value",e);
}
@ -169,7 +170,7 @@ public class ItemHandler {
}
field.set(obj, mapToset);
} else if (field.isAnnotationPresent(ListNodes.class)){
logger.debug("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), clazz.getName(), node.getName());
logger.trace("found field {} of type annotated as ListNodes in class {} on node {}", field.getName(), clazz.getName(), node.getName());
field.setAccessible(true);
String exclude = field.getAnnotation(ListNodes.class).excludeTypeStartWith();
String include = field.getAnnotation(ListNodes.class).includeTypeStartWith();
@ -193,7 +194,7 @@ public class ItemHandler {
AttributeRootNode attributeRootNode = (AttributeRootNode)subtype.getAnnotation(AttributeRootNode.class);
subTypesMap.put(attributeRootNode.value(), subtype);
}
} else logger.debug("no subtypes found for {}",listType.getName());
} else logger.trace("no subtypes found for {}",listType.getName());
typeToSubtypeMap.put(listType, subTypesMap);
@ -211,7 +212,7 @@ public class ItemHandler {
String primaryType = currentNode.getPrimaryNodeType().getName();
logger.debug("the current node {} has a list",currentNode.getName());
logger.trace("the current node {} has a list",currentNode.getName());
if (!include.isEmpty() && !primaryType.startsWith(include))
continue;

View File

@ -0,0 +1,48 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.jcr.Repository;
import javax.jcr.SimpleCredentials;
import org.gcube.common.storagehub.model.items.Item;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VRE {
private static final Logger logger = LoggerFactory.getLogger(VRE.class);
private Item vreFolder;
private Future<List<Item>> result;
private VREQueryRetriever vreQueryRetriever;
private ExecutorService executor;
public VRE(Item item, Repository repository, SimpleCredentials credentials, ExecutorService executor) {
super();
this.vreFolder = item;
this.executor = executor;
vreQueryRetriever = new VREQueryRetriever(repository, credentials, vreFolder);
result = executor.submit(vreQueryRetriever);
}
public Item getVreFolder() {
return vreFolder;
}
public synchronized List<Item> getRecents() throws Exception{
logger.trace("getting recents");
if (result.isDone()) {
result = executor.submit(vreQueryRetriever);
}
return result.get();
}
}

View File

@ -0,0 +1,59 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.jcr.SimpleCredentials;
import javax.servlet.ServletContext;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.services.RepositoryInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class VREManager {
private static final Logger logger = LoggerFactory.getLogger(VREManager.class);
private Map<String, VRE> vreMap = new HashMap<>();
@Inject
RepositoryInitializer repository;
ExecutorService executor = Executors.newFixedThreadPool(5);
SimpleCredentials credentials;
@Inject
public VREManager(ServletContext context) {
credentials = new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray());
}
public synchronized VRE getVRE(String completeName) {
logger.trace("requesting VRE {}",completeName);
if (vreMap.containsKey(completeName))
return vreMap.get(completeName);
else
return null;
}
public synchronized VRE putVRE(Item vreFolder) {
logger.trace("inserting VRE {}",vreFolder.getTitle());
if (vreMap.containsKey(vreFolder.getTitle())) throw new RuntimeException("something went wrong (vre already present in the map)");
else {
VRE toReturn = new VRE(vreFolder, repository.getRepository(), credentials, executor);
vreMap.put(vreFolder.getTitle(), toReturn);
return toReturn;
}
}
}

View File

@ -0,0 +1,168 @@
package org.gcube.data.access.storagehub.handlers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
import javax.jcr.observation.EventJournal;
import javax.jcr.query.Query;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.data.access.storagehub.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class VREQueryRetriever implements Callable<List<Item>> {
private static final Logger logger = LoggerFactory.getLogger(VREQueryRetriever.class);
private static final int CACHE_DIMENSION = 50;
private Repository repository;
private Credentials credentials;
private Item vreFolder;
List<Item> cachedList = new ArrayList<>(CACHE_DIMENSION);
long lastTimestamp =0;
public VREQueryRetriever(Repository repository, Credentials credentials, Item vreFolder) {
super();
this.repository = repository;
this.credentials = credentials;
this.vreFolder = vreFolder;
}
public List<Item> call() {
logger.trace("executing recents task");
Session ses = null;
if (lastTimestamp==0) {
try {
long start = System.currentTimeMillis();
ses = repository.login(credentials);
String query = String.format("SELECT * FROM [nthl:workspaceLeafItem] AS node WHERE ISDESCENDANTNODE('%s') ORDER BY node.[jcr:lastModified] DESC ",vreFolder.getPath());
logger.trace("query for recents is {}",query);
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
jcrQuery.setLimit(CACHE_DIMENSION);
lastTimestamp = System.currentTimeMillis();
NodeIterator it = jcrQuery.execute().getNodes();
logger.trace("query for recents took {}",System.currentTimeMillis()-start);
while (it.hasNext())
cachedList.add(ItemHandler.getItem(it.nextNode(), Arrays.asList("hl:accounting")));
logger.trace("creating objects took {}",System.currentTimeMillis()-start);
return cachedList.subList(0, 10);
} catch (Exception e) {
logger.error("error querying vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}finally{
if (ses!=null)
ses.logout();
logger.trace("recents task finished");
}
} else {
try {
long timestampToUse = lastTimestamp;
lastTimestamp = System.currentTimeMillis();
long start = System.currentTimeMillis();
ses = repository.login(credentials);
final String[] types = { "nthl:workspaceLeafItem", "nthl:workspaceItem"};
EventJournal journalChanged = ses.getWorkspace().getObservationManager().getEventJournal(Event.PROPERTY_CHANGED^Event.NODE_REMOVED^Event.NODE_MOVED, vreFolder.getPath(), true, null, types);
journalChanged.skipTo(timestampToUse);
while (journalChanged.hasNext()) {
Event event = journalChanged.nextEvent();
switch(event.getType()) {
case Event.PROPERTY_CHANGED:
if (ses.propertyExists(event.getPath())) {
Property property = ses.getProperty(event.getPath());
if (property.getName().equalsIgnoreCase("jcr:lastModified")) {
logger.trace("event property changed on {} with value {} and parent {}",property.getName(), property.getValue().getString(), property.getParent().getPath());
String identifier = property.getParent().getIdentifier();
cachedList.removeIf(i -> i.getId().equals(identifier));
Item item = ItemHandler.getItem(property.getParent(), Arrays.asList("hl:accounting"));
insertItemInTheRightPlace(item);
}
}
break;
case Event.NODE_REMOVED:
logger.trace("node removed event received with type {}", event.getIdentifier());
cachedList.removeIf(i -> {
try {
return i.getId().equals(event.getIdentifier()) && i.getLastModificationTime().getTime().getTime()<event.getDate();
} catch (RepositoryException e) {
return false;
}
});
break;
case Event.NODE_MOVED:
Node nodeMoved = ses.getNode(event.getPath());
logger.trace("node moved event received with type {}", nodeMoved.getPrimaryNodeType());
if (nodeMoved.isNodeType("nthl:workspaceLeafItem")) {
logger.trace("event node moved on {} with path {}",nodeMoved.getName(), nodeMoved.getPath());
String identifier = nodeMoved.getIdentifier();
cachedList.removeIf(i -> i.getId().equals(identifier) && !i.getPath().startsWith(vreFolder.getPath()));
}
break;
default:
throw new Exception("error in event handling");
}
}
if (cachedList.size()>CACHE_DIMENSION)
cachedList.subList(51, cachedList.size()).clear();
logger.trace("retrieving event took {}",System.currentTimeMillis()-start);
return cachedList.subList(0, 10);
} catch (Exception e) {
logger.error("error getting events for vre {}",vreFolder.getTitle(),e);
throw new RuntimeException(e);
}finally{
if (ses!=null)
ses.logout();
}
}
}
private void insertItemInTheRightPlace(Item item) {
Iterator<Item> it = cachedList.iterator();
int index =0;
while (it.hasNext()) {
Item inListItem = it.next();
if (item.getLastModificationTime().getTime().getTime()>=inListItem.getLastModificationTime().getTime().getTime()) break;
index++;
}
if (index<CACHE_DIMENSION)
cachedList.add(index, item);
}
/* @Override
public void onEvent(EventIterator events) {
logger.trace("on event called");
while (events.hasNext()) {
Event event = events.nextEvent();
try {
logger.trace("new event received of type {} on node {}",event.getType(),event.getIdentifier());
} catch (RepositoryException e) {
logger.error("error reading event",e);
}
}
}*/
}

View File

@ -52,6 +52,7 @@ public class VersionHandler {
VersionManager versionManager = session.getWorkspace().getVersionManager();
VersionHistory history = versionManager.getVersionHistory(contentNode.getPath());
VersionIterator iterator = history.getAllVersions();
iterator.skip(1);
while (iterator.hasNext()) {
Version version = iterator.nextVersion();
logger.debug("version name {} with nodeType {}",version.getName(),version.getPrimaryNodeType().getName());

View File

@ -12,7 +12,7 @@ public class ISDescendantEvaluator extends Evaluator<ISDescendant> {
@Override
public String evaluate(ISDescendant expr, Iterable<Evaluator<Expression<?>>> evaluators) {
return String.format("ISDESCENDANTNODE( node , [%s])", expr.getPath().toPath());
return String.format("ISDESCENDANTNODE('%s')", expr.getPath().toPath());
}
@Override

View File

@ -25,7 +25,6 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.tika.config.TikaConfig;
import org.apache.tika.detect.Detector;
@ -50,7 +49,7 @@ import org.gcube.data.access.storagehub.handlers.content.ContentHandler;
import org.gcube.data.access.storagehub.handlers.content.ContentHandlerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.gcube.common.storagehub.model.NodeConstants.*;
@Path("item")
public class ItemsCreator {
@ -80,7 +79,7 @@ public class ItemsCreator {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}/create/{type:(?!FILE)[^/?$]*}")
public Response createItem(@Context UriInfo uriInfo, @PathParam("id") String id, @PathParam("type") String type,@QueryParam("name") String name, @QueryParam("description") String description){
public Response createItem(@PathParam("id") String id, @PathParam("type") String type,@QueryParam("name") String name, @QueryParam("description") String description){
CalledMethodProvider.instance.set(String.format("createItem(%s)",type));
log.info("create generic item called");
Session ses = null;
@ -98,11 +97,11 @@ public class ItemsCreator {
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node destination = ses.getNodeByIdentifier(id);
destinationItem = ItemHandler.getItem(destination,Arrays.asList("hl:accounting","jcr:content"));
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
if (!(destinationItem instanceof FolderItem)) throw new Exception("an Item must be created into a directory");
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId());
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
@ -119,17 +118,16 @@ public class ItemsCreator {
item.setOwner(login);
//to inherit hidden property
item.setHidden(destinationItem.isHidden());
//item.setHidden(destinationItem.isHidden());
log.debug("item prepared, fulfilling content");
log.debug("content prepared");
Node newnode = ItemHandler.createNodeFromItem(ses, destination, item);
accountingHandler.createFolderAddObj(name, type, null, ses, newnode, false);
Node newNode = ItemHandler.createNodeFromItem(ses, destination, item);
accountingHandler.createFolderAddObj(name, type, null, ses, newNode, false);
ses.save();
log.info("item correctly created");
return Response.ok(new ItemWrapper<>(item)).build();
log.info("item with id {} correctly created",newNode.getIdentifier());
return Response.ok(newNode.getIdentifier()).build();
}catch(Exception e){
log.error("error creating item", e);
throw new WebApplicationException(e);
@ -137,7 +135,8 @@ public class ItemsCreator {
if (ses!=null){
if (destinationItem!=null)
try {
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
if (ses.getWorkspace().getLockManager().isLocked(destinationItem.getPath()))
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
} catch (Throwable t){
log.warn("error unlocking {}", destinationItem.getPath(), t);
}
@ -168,10 +167,10 @@ public class ItemsCreator {
//TODO: validate input parameters for Item Type
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node destination = ses.getNodeByIdentifier(id);
destinationItem = ItemHandler.getItem(destination,Arrays.asList("hl:accounting","jcr:content"));
destinationItem = ItemHandler.getItem(destination,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME));
log.debug("destination item path is {}",destinationItem.getPath());
if (!(destinationItem instanceof FolderItem)) throw new Exception("an Item must be copyed to another directory");
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId());
ses.getWorkspace().getLockManager().lock(destinationItem.getPath(), true, true, 0,login);
ContentHandler handler = getContentHandler(stream , name, destinationItem.getPath());
@ -179,7 +178,7 @@ public class ItemsCreator {
AbstractFileItem item =handler.buildItem(name, description, login);
//to inherit hidden property
item.setHidden(destinationItem.isHidden());
//item.setHidden(destinationItem.isHidden());
log.debug("item prepared, fulfilling content");
log.debug("content prepared");
@ -188,11 +187,13 @@ public class ItemsCreator {
try {
newNode = ses.getNode(org.gcube.common.storagehub.model.Paths.append(org.gcube.common.storagehub.model.Paths.getPath(destinationItem.getPath()), name).toPath());
log.info("overwriting the old node");
authChecker.checkWriteAuthorizationControl(ses, newNode.getIdentifier(), false);
versionHandler.checkoutContentNode(newNode, ses);
log.trace("replacing content of class {}",item.getContent().getClass());
ItemHandler.replaceContent(ses, newNode,item);
}catch(PathNotFoundException pnf) {
log.info("creating new node");
authChecker.checkWriteAuthorizationControl(ses, destinationItem.getId(), true);
newNode = ItemHandler.createNodeFromItem(ses, destination, item);
versionHandler.makeVersionableContent(newNode, ses);
}
@ -201,9 +202,8 @@ public class ItemsCreator {
ses.save();
versionHandler.checkinContentNode(newNode, ses);
versionHandler.getContentVersionHistory(newNode, ses);
log.info("item correctly created");
return Response.ok(new ItemWrapper<>(item)).build();
log.info("file with id {} correctly created",newNode.getIdentifier());
return Response.ok(newNode.getIdentifier()).build();
}catch(Throwable e){
log.error("error creating item", e);
return Response.serverError().build();
@ -211,7 +211,8 @@ public class ItemsCreator {
if (ses!=null){
if (destinationItem!=null)
try {
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
if (ses.getWorkspace().getLockManager().isLocked(destinationItem.getPath()))
ses.getWorkspace().getLockManager().unlock(destinationItem.getPath());
} catch (Throwable t){
log.warn("error unlocking {}", destinationItem.getPath(), t);
}

View File

@ -1,5 +1,6 @@
package org.gcube.data.access.storagehub.services;
import static org.gcube.common.storagehub.model.NodeConstants.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
@ -18,7 +19,6 @@ import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.servlet.ServletContext;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
@ -313,8 +313,8 @@ public class ItemsManager {
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray()));
authChecker.checkWriteAuthorizationControl(ses, destinationId);
authChecker.checkWriteAuthorizationControl(ses, identifier);
authChecker.checkWriteAuthorizationControl(ses, destinationId, true);
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
final Node nodeToMove = ses.getNodeByIdentifier(identifier);
final Node destination = ses.getNodeByIdentifier(destinationId);
@ -369,7 +369,7 @@ public class ItemsManager {
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(new SimpleCredentials(context.getInitParameter(Constants.ADMIN_PARAM_NAME),context.getInitParameter(Constants.ADMIN_PARAM_PWD).toCharArray()));
authChecker.checkWriteAuthorizationControl(ses, identifier);
authChecker.checkWriteAuthorizationControl(ses, identifier, false);
final Node nodeToDelete = ses.getNodeByIdentifier(identifier);
final Node trashFolder = ses.getNode(Paths.append(Utils.getHomePath(),Constants.TRASH_ROOT_FOLDER_NAME).toPath());
@ -430,7 +430,7 @@ public class ItemsManager {
private boolean hasSharedChildren(FolderItem item, Session session) throws Exception{
Node currentNode = session.getNodeByIdentifier(item.getId());
for (Item children : Utils.getItemList(currentNode,Arrays.asList("hl:accounting","jcr:content"), null, false)){
for (Item children : Utils.getItemList(currentNode,Arrays.asList(ACCOUNTING_NAME,CONTENT_NAME), null, false)){
if (children instanceof FolderItem)
return (children instanceof SharedFolder) || hasSharedChildren((FolderItem)item, session);
}

View File

@ -13,6 +13,7 @@ import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@ -33,10 +34,13 @@ import org.gcube.common.storagehub.model.expressions.logical.ISDescendant;
import org.gcube.common.storagehub.model.items.Item;
import org.gcube.common.storagehub.model.service.ItemList;
import org.gcube.common.storagehub.model.service.ItemWrapper;
import org.gcube.data.access.storagehub.AuthorizationChecker;
import org.gcube.data.access.storagehub.Constants;
import org.gcube.data.access.storagehub.Range;
import org.gcube.data.access.storagehub.Utils;
import org.gcube.data.access.storagehub.handlers.ItemHandler;
import org.gcube.data.access.storagehub.handlers.VRE;
import org.gcube.data.access.storagehub.handlers.VREManager;
import org.gcube.data.access.storagehub.query.sql2.evaluators.Evaluators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -46,103 +50,148 @@ import com.fasterxml.jackson.databind.ObjectMapper;
@Path("")
public class WorkspaceManager {
private static final Logger log = LoggerFactory.getLogger(WorkspaceManager.class);
@Inject
RepositoryInitializer repository;
@Inject
Evaluators evaluator;
@Inject
AuthorizationChecker authChecker;
@Inject
ServletContext context;
@Inject
VREManager vreManager;
@RequestScoped
@QueryParam("exclude")
private List<String> excludes = Collections.emptyList();
@Path("")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getWorkspace(){
public ItemWrapper<Item> getWorkspace(@QueryParam("relPath") String relPath){
CalledMethodProvider.instance.set("getWorkspace");
Session ses = null;
org.gcube.common.storagehub.model.Path absolutePath = Utils.getHomePath();
org.gcube.common.storagehub.model.Path absolutePath;
if (relPath==null)
absolutePath = Utils.getHomePath();
else absolutePath = Paths.append(Utils.getHomePath(), relPath);
Item toReturn = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
toReturn = ItemHandler.getItem(ses.getNode(absolutePath.toPath()), excludes);
log.trace("time to connect to repo {}",(System.currentTimeMillis()-start));
Node node = ses.getNode(absolutePath.toPath());
authChecker.checkReadAuthorizationControl(ses, node.getIdentifier());
toReturn = ItemHandler.getItem(node, excludes);
}catch(Throwable e){
log.error("error reading the node children of {}",absolutePath,e);
throw new WebApplicationException("error getting WS folder "+absolutePath.toPath(),e) ;
}finally{
if (ses!=null)
ses.logout();
}
return new ItemWrapper<Item>(toReturn);
}
private synchronized VRE getVreFolderItem(Session ses) throws Exception{
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
if (!bean.is(Type.VRE)) throw new Exception("the current scope is not a VRE");
String entireScopeName= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
VRE vre = vreManager.getVRE(entireScopeName);
if (vre!=null) return vre;
else {
String query = String.format("SELECT * FROM [nthl:workspaceItem] As node WHERE node.[jcr:title] like '%s' AND ISDESCENDANTNODE('%s')",entireScopeName, vrePath.toPath());
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
NodeIterator it = jcrQuery.execute().getNodes();
if (!it.hasNext()) throw new Exception("vre folder not found for context "+entireScopeName);
Node folder = it.nextNode();
Item vreFolder = ItemHandler.getItem(folder, excludes);
return vreManager.putVRE(vreFolder);
}
}
@Path("vrefolder")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getVreRootFolder(){
CalledMethodProvider.instance.set("getVreRootFolder");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
try{
try {
String login = AuthorizationProvider.instance.get().getClient().getId();
ScopeBean bean = new ScopeBean(ScopeProvider.instance.get());
if (!bean.is(Type.VRE)) throw new Exception("the current scope is not a VRE");
long start = System.currentTimeMillis();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
String entireScopename= bean.toString().replaceAll("^/(.*)/?$", "$1").replaceAll("/", "-");
String query = String.format("SELECT * FROM [nthl:workspaceItem] As node WHERE node.[jcr:title] like '%s'", entireScopename);
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(query, Constants.QUERY_LANGUAGE);
NodeIterator it = jcrQuery.execute().getNodes();
if (!it.hasNext()) throw new Exception("vre folder not found for context "+bean.toString());
Node folder = it.nextNode();
Item item = ItemHandler.getItem(folder, excludes);
return new ItemWrapper<Item>(item);
return new ItemWrapper<Item>(getVreFolderItem(ses).getVreFolder());
}catch(Throwable e){
log.error("error reading node {}",vrePath,e);
log.error("error reading vreNode for context {}",ScopeProvider.instance.get(),e);
throw new WebApplicationException("error retrieving vre folder",e);
}finally{
if (ses!=null)
ses.logout();
}
}
}
@Path("vrefolder/recents")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemList getVreFolderRecentsDocument(){
CalledMethodProvider.instance.set("getVreFolderRecents");
Session ses = null;
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
VRE vre = getVreFolderItem(ses);
log.trace("VRE retrieved {}",vre.getVreFolder().getTitle());
List<Item> recentItems = vre.getRecents();
log.trace("recents retrieved {}",vre.getVreFolder().getTitle());
return new ItemList(recentItems);
}catch(Throwable e){
log.error("error reading recents for context {}",ScopeProvider.instance.get(),e);
throw new WebApplicationException("error reading recents",e);
}finally{
if (ses!=null)
ses.logout();
}
}
@Path("trash")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemWrapper<Item> getTrashRootFolder(){
CalledMethodProvider.instance.set("getTrashRootFolder");
Session ses = null;
org.gcube.common.storagehub.model.Path trashPath = Paths.append(Utils.getHomePath(), Constants.TRASH_ROOT_FOLDER_NAME);
try{
String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
Node folder = ses.getNode(trashPath.toPath());
Item item = ItemHandler.getItem(folder, excludes);
return new ItemWrapper<Item>(item);
}catch(Throwable e){
log.error("error reading the node {}",trashPath,e);
@ -151,16 +200,16 @@ public class WorkspaceManager {
if (ses!=null)
ses.logout();
}
}
@Path("vrefolders")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemList getVreFolders(){
CalledMethodProvider.instance.set("getVreFolders");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
List<? extends Item> toReturn = null;
try{
@ -169,21 +218,22 @@ public class WorkspaceManager {
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, null, false);
}catch(Throwable e){
log.error("error reading the node children of {}",vrePath,e);
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@Path("vrefolders/paged")
@GET
@Produces(MediaType.APPLICATION_JSON)
public ItemList getVreFoldersPaged(@QueryParam("start") Integer start, @QueryParam("limit") Integer limit){
CalledMethodProvider.instance.set("getVreFoldersPaged");
Session ses = null;
org.gcube.common.storagehub.model.Path vrePath = Paths.append(Utils.getHomePath(), Constants.VRE_FOLDER_PARENT_NAME);
List<? extends Item> toReturn = null;
try{
@ -191,15 +241,18 @@ public class WorkspaceManager {
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
toReturn = Utils.getItemList(ses.getNode(vrePath.toPath()) , excludes, new Range(start, limit), false);
}catch(Throwable e){
log.error("error reading the node children of {}",vrePath,e);
log.error("(paged) error reading the node children of {}",vrePath,e);
throw new WebApplicationException("error reading the node children of "+vrePath.toPath(),e);
}finally{
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
@Path("query")
@GET
@Produces(MediaType.APPLICATION_JSON)
@ -207,41 +260,42 @@ public class WorkspaceManager {
CalledMethodProvider.instance.set("searchItems");
Session ses = null;
List<? extends Item> toReturn = new ArrayList<>();
try{
ObjectMapper mapper = new ObjectMapper();
Expression<Boolean> expression = mapper.readValue(jsonExpr, Expression.class);
String stringExpression = evaluator.evaluate(new And(new ISDescendant(Utils.getHomePath()), expression));
//ADD ALSO LIMIT AND OFFSET
String orderBy = "";
if (orderField!=null && orderField.size()>0)
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
orderBy= String.format("ORDER BY %s", orderField.stream().collect(Collectors.joining(",")).toString());
String sql2Query = String.format("SELECT * FROM [%s] AS node WHERE %s %s ",node, stringExpression,orderBy);
log.info("query sent is {}",sql2Query);
String login = AuthorizationProvider.instance.get().getClient().getId();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
Query jcrQuery = ses.getWorkspace().getQueryManager().createQuery(sql2Query, Constants.QUERY_LANGUAGE);
if (limit!=null && limit!=-1 )
jcrQuery.setLimit(limit);
if (offset!=null && offset!=-1 )
jcrQuery.setOffset(offset);
QueryResult result = jcrQuery.execute();
NodeIterator it = result.getNodes();
while (it.hasNext())
toReturn.add(ItemHandler.getItem(it.nextNode(), excludes));
toReturn.add(ItemHandler.getItem(it.nextNode(), null));
}catch(Throwable e){
log.error("error executing the query",e);
throw new WebServiceException("error executing the query", e);
@ -249,138 +303,8 @@ public class WorkspaceManager {
if (ses!=null)
ses.logout();
}
return new ItemList(toReturn);
}
/*
@POST
@Path("create")
@Consumes({MediaType.MULTIPART_FORM_DATA})
public Response create(@FormDataParam("item") ItemWrapper itemWrapper, @FormDataParam("file") InputStream stream , @FormDataParam("file") FormDataBodyPart fileDetail, @QueryParam("path") String path){
Session ses = null;
log.debug("method create called");
org.gcube.common.storagehub.model.Path absolutePath = Paths.append(Utils.getHomePath(), Paths.getPath(path));
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
//long start = System.currentTimeMillis();
ses = repository.getRepository().login(new SimpleCredentials("workspacerep.imarine","gcube2010*onan".toCharArray()));
log.debug("session retrieved");
ItemHandler handler = new ItemHandler();
Node parentNode = ses.getNode(absolutePath.toPath());
Item item = itemWrapper.getItem();
if (item instanceof AbstractFileItem){
if (stream==null)
throw new Exception("invalid item: file without an input stream is not accepted");
fulfillContent((AbstractFileItem)item, stream, fileDetail, absolutePath.toPath());
}
Calendar now = Calendar.getInstance();
item.setCreationTime(now);
item.setHidden(false);
item.setLastAction(ItemAction.CREATED);
item.setLastModificationTime(now);
item.setLastModifiedBy(login);
item.setOwner(login);
handler.createNodeFromItem(ses, parentNode, item, stream);
ses.save();
}catch(Throwable e){
log.error("error creating file",e);
return Response.serverError().build();
} finally{
if (ses!=null) ses.logout();
}
return Response.ok().build();
}
private void fulfillContent(AbstractFileItem item, InputStream stream , FormDataBodyPart fileDetail, String path) {
if (item instanceof GenericFileItem){
Content content = new Content();
String remotePath= path+"/"+fileDetail.getContentDisposition().getFileName();
content.setData("jcr:content");
content.setRemotePath(remotePath);
content.setSize(fileDetail.getContentDisposition().getSize());
content.setMimeType(fileDetail.getMediaType().toString());
String storageId = Utils.getStorageClient(AuthorizationProvider.instance.get().getClient().getId()).getClient().put(true).LFile(stream).RFile(remotePath);
content.setStorageId(storageId);
((GenericFileItem) item).setContent(content);
} else throw new RuntimeException("type file error");
}
@PUT
@Path("{id}/move")
public Response move(@QueryParam("path") String path, @PathParam("id") String identifier){
Session ses = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
//ses = RepositoryInitializer.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
//TODO check if it is possible to change all the ACL on a workspace
ses = repository.getRepository().login(new SimpleCredentials("workspacerep.imarine","gcube2010*onan".toCharArray()));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
final Node nodeToMove = ses.getNodeByIdentifier(identifier);
final Node destination = ses.getNode(path);
Item destinationItem = ItemHandler.getItem(destination,null);
//TODO for now only owner of the destination folder can move file
if (!destinationItem.getOwner().equals(login)){
/*AccessControlManager accessControlManager = ses.getAccessControlManager();
boolean canWrite = accessControlManager.hasPrivileges(path, new Privilege[] {
accessControlManager.privilegeFromName(Privilege.JCR_ADD_CHILD_NODES)});*/
//if (!canWrite)
/*
throw new IllegalAccessException("Insufficent Provileges to write in "+path);
}
final Item item = ItemHandler.getItem(nodeToMove, null);
if (item instanceof SharedFolder){
throw new Exception("shared item cannot be moved");
}else if (item instanceof FolderItem){
if (hasSharedChildren((FolderItem) item, ses)) throw new Exception("folder item with shared children cannot be moved");
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
}else {
item.setParentId(destinationItem.getId());
ses.getWorkspace().move(nodeToMove.getPath(), destination.getPath()+"/"+nodeToMove.getName());
}
ses.save();
}catch(Exception e){
log.error("error moving item with id {} in path {}",identifier, path,e);
return Response.serverError().build();
} finally{
if (ses!=null) ses.logout();
}
return Response.ok().build();
}
private boolean hasSharedChildren(FolderItem folder, Session session) throws Exception{
Node currentNode = session.getNodeByIdentifier(folder.getId());
for (Item item : Utils.getItemList(currentNode,null)){
if (item instanceof FolderItem)
return (item instanceof SharedFolder) || hasSharedChildren((FolderItem)item, session);
}
return false;
}
@PUT
@Path("{id}/rename")
public Response rename(@QueryParam("newname") String newName, @PathParam("id") String identifier){
Session ses = null;
try{
final String login = AuthorizationProvider.instance.get().getClient().getId();
long start = System.currentTimeMillis();
ses = repository.getRepository().login(new SimpleCredentials(login,Utils.getSecurePassword(login).toCharArray()));
log.info("time to connect to repo {}",(System.currentTimeMillis()-start));
}catch(Exception e){
}
return Response.ok().build();
}
*/
}