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=f530f170b7fe4a0637d2eb72b75b4470dba07199;hb=13b5efc8ccec8b21fc049bbb5332a0713dbdfba1;hp=bc7862f5fea23b5a3a2b4d935cfbb1bed2d13ebc;hpb=fb4f7c451ea7d9025f7cf7fe032020f229df794a;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 bc7862f5f..f530f170b 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
@@ -41,7 +41,9 @@ import javax.jcr.RepositoryException;
import javax.jcr.RepositoryFactory;
import javax.jcr.Session;
import javax.jcr.Value;
+import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.observation.EventListener;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.jcr.query.qom.Constraint;
@@ -365,11 +367,16 @@ public class JcrUtils implements ArgeoJcrConstants {
}
/**
- * Copies recursively the content of a node to another one. Mixin are NOT
- * copied.
+ * Copies recursively the content of a node to another one. Do NOT copy the
+ * property values of {@link NodeType#MIX_CREATED} and
+ * {@link NodeType#MIX_LAST_MODIFIED}, but update the
+ * {@link Property#JCR_LAST_MODIFIED} and
+ * {@link Property#JCR_LAST_MODIFIED_BY} properties if the target node has
+ * the {@link NodeType#MIX_LAST_MODIFIED} mixin.
*/
public static void copy(Node fromNode, Node toNode) {
try {
+ // process properties
PropertyIterator pit = fromNode.getProperties();
properties: while (pit.hasNext()) {
Property fromProperty = pit.nextProperty();
@@ -379,10 +386,32 @@ public class JcrUtils implements ArgeoJcrConstants {
.isProtected())
continue properties;
- toNode.setProperty(fromProperty.getName(),
- fromProperty.getValue());
+ if (fromProperty.getDefinition().isProtected())
+ continue properties;
+
+ if (propertyName.equals("jcr:created")
+ || propertyName.equals("jcr:createdBy")
+ || propertyName.equals("jcr:lastModified")
+ || propertyName.equals("jcr:lastModifiedBy"))
+ continue properties;
+
+ if (fromProperty.isMultiple()) {
+ toNode.setProperty(propertyName, fromProperty.getValues());
+ } else {
+ toNode.setProperty(propertyName, fromProperty.getValue());
+ }
}
+ // update jcr:lastModified and jcr:lastModifiedBy in toNode in case
+ // they existed, before adding the mixins
+ updateLastModified(toNode);
+
+ // add mixins
+ for (NodeType mixinType : fromNode.getMixinNodeTypes()) {
+ toNode.addMixin(mixinType.getName());
+ }
+
+ // process children nodes
NodeIterator nit = fromNode.getNodes();
while (nit.hasNext()) {
Node fromChild = nit.nextNode();
@@ -623,6 +652,21 @@ public class JcrUtils implements ArgeoJcrConstants {
}
}
+ /**
+ * Discards the current changes in the session attached to this node. To be
+ * used typically in a catch block.
+ *
+ * @see #discardQuietly(Session)
+ */
+ public static void discardUnderlyingSessionQuietly(Node node) {
+ try {
+ discardQuietly(node.getSession());
+ } catch (RepositoryException e) {
+ log.warn("Cannot quietly discard session of node " + node + ": "
+ + e.getMessage());
+ }
+ }
+
/**
* Discards the current changes in a session by calling
* {@link Session#refresh(boolean)} with false
, only logging
@@ -650,6 +694,24 @@ public class JcrUtils implements ArgeoJcrConstants {
return getUserHome(session, userID);
}
+ /**
+ * Returns user home has path, embedding exceptions. Contrary to
+ * {@link #getUserHome(Session)}, it never returns null but throws and
+ * exception if not found.
+ */
+ public static String getUserHomePath(Session session) {
+ String userID = session.getUserID();
+ try {
+ Node userHome = getUserHome(session, userID);
+ if (userHome != null)
+ return userHome.getPath();
+ else
+ throw new ArgeoException("No home registered for " + userID);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot find user home path", e);
+ }
+ }
+
/** Get the profile of the user attached to this session. */
public static Node getUserProfile(Session session) {
String userID = session.getUserID();
@@ -709,6 +771,7 @@ public class JcrUtils implements ArgeoJcrConstants {
}
}
+ /** Creates an Argeo user home. */
public static Node createUserHome(Session session, String homeBasePath,
String username) {
try {
@@ -738,4 +801,57 @@ public class JcrUtils implements ArgeoJcrConstants {
+ username, e);
}
}
+
+ /**
+ * Quietly unregisters an {@link EventListener} from the udnerlying
+ * workspace of this node.
+ */
+ public static void unregisterQuietly(Node node, EventListener eventListener) {
+ try {
+ unregisterQuietly(node.getSession().getWorkspace(), eventListener);
+ } catch (RepositoryException e) {
+ // silent
+ if (log.isTraceEnabled())
+ log.trace("Could not unregister event listener "
+ + eventListener);
+ }
+ }
+
+ /** Quietly unregisters an {@link EventListener} from this workspace */
+ public static void unregisterQuietly(Workspace workspace,
+ EventListener eventListener) {
+ if (eventListener == null)
+ return;
+ try {
+ workspace.getObservationManager()
+ .removeEventListener(eventListener);
+ } catch (RepositoryException e) {
+ // silent
+ if (log.isTraceEnabled())
+ log.trace("Could not unregister event listener "
+ + eventListener);
+ }
+ }
+
+ /**
+ * If this node is has the {@link NodeType#MIX_LAST_MODIFIED} mixin, it
+ * updates the {@link Property#JCR_LAST_MODIFIED} property with the current
+ * time and the {@link Property#JCR_LAST_MODIFIED_BY} property with the
+ * underlying session user id. In Jackrabbit 2.x, these properties
+ * are not automatically updated, hence the need for manual update. The
+ * session is not saved.
+ */
+ public static void updateLastModified(Node node) {
+ try {
+ if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
+ node.setProperty(Property.JCR_LAST_MODIFIED,
+ new GregorianCalendar());
+ node.setProperty(Property.JCR_LAST_MODIFIED_BY, node
+ .getSession().getUserID());
+ }
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot update last modified", e);
+ }
+ }
}