X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=server%2Fruntime%2Forg.argeo.server.jcr%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fjcr%2FJcrUtils.java;h=2176e757cacac3141eb2e7c90a39302e085e0a8b;hb=3a3d316af102ba410d1d9e6de349d0c8f7ac044f;hp=442e70d777577aa19403064f6f8b1780f7ad3696;hpb=72b40d55c0481e506ba9eabd6fcd684ef23e2f5a;p=lgpl%2Fargeo-commons.git diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java index 442e70d77..2176e757c 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2012 Mathieu Baudier + * Copyright (C) 2007-2012 Argeo GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -195,6 +195,10 @@ public class JcrUtils implements ArgeoJcrConstants { } } + /* + * PATH UTILITIES + */ + /** Make sure that: starts with '/', do not end with '/', do not have '//' */ public static String normalizePath(String path) { List tokens = tokenize(path); @@ -221,6 +225,21 @@ public class JcrUtils implements ArgeoJcrConstants { return path.toString(); } + /** + * Creates a path from a UUID (e.g. 6ebda899-217d-4bf1-abe4-2839085c8f3c => + * 6ebda899-217d/4bf1/abe4/2839085c8f3c/). '/' at the end, not the beginning + */ + public static String uuidAsPath(String uuid) { + StringBuffer path = new StringBuffer(uuid.length()); + String[] tokens = uuid.split("-"); + for (int i = 0; i < tokens.length; i++) { + path.append(tokens[i]); + if (i != 0) + path.append('/'); + } + return path.toString(); + } + /** * The provided data as a path ('/' at the end, not the beginning) * @@ -281,11 +300,34 @@ public class JcrUtils implements ArgeoJcrConstants { throw new ArgeoException("Path " + path + " cannot end with '/'"); int index = path.lastIndexOf('/'); if (index < 0) - throw new ArgeoException("Cannot find last path element for " - + path); + return path; return path.substring(index + 1); } + /** + * Call {@link Node#getName()} without exceptions (useful in super + * constructors). + */ + public static String getNameQuietly(Node node) { + try { + return node.getName(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get name from " + node, e); + } + } + + /** + * Call {@link Node#getProperty(String)} without exceptions (useful in super + * constructors). + */ + public static String getStringPropertyQuietly(Node node, String propertyName) { + try { + return node.getProperty(propertyName).getString(); + } catch (RepositoryException e) { + throw new ArgeoException("Cannot get name from " + node, e); + } + } + /** * Routine that get the child with this name, adding id it does not already * exist @@ -378,6 +420,48 @@ public class JcrUtils implements ArgeoJcrConstants { return mkdirs(session, path, type, null, false); } + /** + * Create sub nodes relative to a parent node + * + * @param nodeType + * the type of the leaf node + */ + public static Node mkdirs(Node parentNode, String relativePath, + String nodeType) { + return mkdirs(parentNode, relativePath, nodeType, null); + } + + /** + * Create sub nodes relative to a parent node + * + * @param nodeType + * the type of the leaf node + */ + public static Node mkdirs(Node parentNode, String relativePath, + String nodeType, String intermediaryNodeType) { + List tokens = tokenize(relativePath); + Node currParent = parentNode; + try { + for (int i = 0; i < tokens.size(); i++) { + String name = tokens.get(i); + if (currParent.hasNode(name)) { + currParent = currParent.getNode(name); + } else { + if (i != (tokens.size() - 1)) {// intermediary + currParent = currParent.addNode(name, + intermediaryNodeType); + } else {// leaf + currParent = currParent.addNode(name, nodeType); + } + } + } + return currParent; + } catch (RepositoryException e) { + throw new ArgeoException("Cannot mkdirs relative path " + + relativePath + " from " + parentNode, e); + } + } + /** * Synchronized and save is performed, to avoid race conditions in * initializers leading to duplicate nodes. @@ -1123,14 +1207,26 @@ public class JcrUtils implements ArgeoJcrConstants { } } - /** Update lastModified recursively until this parent. */ + /** + * Update lastModified recursively until this parent. + * + * @param node + * the node + * @param untilPath + * the base path, null is equivalent to "/" + */ public static void updateLastModifiedAndParents(Node node, String untilPath) { try { - if (!node.getPath().startsWith(untilPath)) + if (untilPath != null && !node.getPath().startsWith(untilPath)) throw new ArgeoException(node + " is not under " + untilPath); updateLastModified(node); - if (!node.getPath().equals(untilPath)) - updateLastModifiedAndParents(node.getParent(), untilPath); + if (untilPath == null) { + if (!node.getPath().equals("/")) + updateLastModifiedAndParents(node.getParent(), untilPath); + } else { + if (!node.getPath().equals(untilPath)) + updateLastModifiedAndParents(node.getParent(), untilPath); + } } catch (RepositoryException e) { throw new ArgeoException("Cannot update lastModified from " + node + " until " + untilPath, e); @@ -1205,7 +1301,7 @@ public class JcrUtils implements ArgeoJcrConstants { * Convenience method for adding a single privilege to a principal (user or * role), typically jcr:all */ - public static void addPrivilege(Session session, String path, + public synchronized static void addPrivilege(Session session, String path, String principal, String privilege) throws RepositoryException { List privileges = new ArrayList(); privileges.add(session.getAccessControlManager().privilegeFromName( @@ -1215,28 +1311,53 @@ public class JcrUtils implements ArgeoJcrConstants { /** * Add privileges on a path to a {@link Principal}. The path must already - * exist. Session is saved. + * exist. Session is saved. Synchronized to prevent concurrent modifications + * of the same node. */ - public static void addPrivileges(Session session, String path, - Principal principal, List privs) + public synchronized static Boolean addPrivileges(Session session, + String path, Principal principal, List privs) throws RepositoryException { + // make sure the session is in line with the persisted state + session.refresh(false); AccessControlManager acm = session.getAccessControlManager(); AccessControlList acl = getAccessControlList(acm, path); - acl.addAccessControlEntry(principal, - privs.toArray(new Privilege[privs.size()])); + + accessControlEntries: for (AccessControlEntry ace : acl + .getAccessControlEntries()) { + Principal currentPrincipal = ace.getPrincipal(); + if (currentPrincipal.getName().equals(principal.getName())) { + Privilege[] currentPrivileges = ace.getPrivileges(); + if (currentPrivileges.length != privs.size()) + break accessControlEntries; + for (int i = 0; i < currentPrivileges.length; i++) { + Privilege currP = currentPrivileges[i]; + Privilege p = privs.get(i); + if (!currP.getName().equals(p.getName())) { + break accessControlEntries; + } + } + return false; + } + } + + Privilege[] privileges = privs.toArray(new Privilege[privs.size()]); + acl.addAccessControlEntry(principal, privileges); acm.setPolicy(path, acl); if (log.isDebugEnabled()) { StringBuffer privBuf = new StringBuffer(); for (Privilege priv : privs) privBuf.append(priv.getName()); - log.debug("Added privileges " + privBuf + " to " + principal - + " on " + path); + log.debug("Added privileges " + privBuf + " to " + + principal.getName() + " on " + path + " in '" + + session.getWorkspace().getName() + "'"); } + session.refresh(true); session.save(); + return true; } /** Gets access control list for this path, throws exception if not found */ - public static AccessControlList getAccessControlList( + public synchronized static AccessControlList getAccessControlList( AccessControlManager acm, String path) throws RepositoryException { // search for an access control list AccessControlList acl = null; @@ -1263,8 +1384,8 @@ public class JcrUtils implements ArgeoJcrConstants { } /** Clear authorizations for a user at this path */ - public static void clearAccessControList(Session session, String path, - String username) throws RepositoryException { + public synchronized static void clearAccessControList(Session session, + String path, String username) throws RepositoryException { AccessControlManager acm = session.getAccessControlManager(); AccessControlList acl = getAccessControlList(acm, path); for (AccessControlEntry ace : acl.getAccessControlEntries()) { @@ -1294,6 +1415,7 @@ public class JcrUtils implements ArgeoJcrConstants { * files * @return how many files were copied */ + @SuppressWarnings("resource") public static Long copyFiles(Node fromNode, Node toNode, Boolean recursive, ArgeoMonitor monitor) { long count = 0l;