Introduce JCR XML utilities.
authorMathieu Baudier <mbaudier@argeo.org>
Sat, 31 Oct 2020 08:50:52 +0000 (09:50 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sat, 31 Oct 2020 08:50:52 +0000 (09:50 +0100)
org.argeo.jcr/build.properties
org.argeo.jcr/src/org/argeo/jcr/Jcr.java
org.argeo.jcr/src/org/argeo/jcr/JcrUtils.java
org.argeo.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java [new file with mode: 0644]

index 8a9736e84b645e92af212decb00c64ac111016a8..027445903ad09a10ae524a8876353b12a7bf178f 100644 (file)
@@ -12,7 +12,6 @@ additional.bundles = org.junit,\
                      org.apache.jackrabbit.spi,\
                      org.apache.jackrabbit.spi.commons,\
                      org.slf4j.api,\
-                     org.slf4j.commons.logging,\
                      org.slf4j.log4j12,\
                      org.apache.log4j,\
                      org.apache.commons.collections,\
index fb6f610131842bf546196eeaa7eb3302f029586a..5ce8017ca4120c14accae02dc6669f1d87176771 100644 (file)
@@ -36,6 +36,55 @@ import javax.jcr.version.VersionManager;
  * exceptions. Loosely inspired by Java's <code>Files</code> singleton.
  */
 public class Jcr {
+
+       /**
+        * <code>jcr:name</code>, when used in another context than
+        * {@link Property#JCR_NAME}, typically to name a node rather than a property.
+        */
+       public final static String JCR_NAME = "jcr:name";
+
+       /**
+        * <code>jcr:path</code>, when used in another context than
+        * {@link Property#JCR_PATH}, typically to name a node rather than a property.
+        */
+       public final static String JCR_PATH = "jcr:path";
+
+       /**
+        * <code>jcr:primaryType</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_PRIMARY_TYPE}.
+        */
+       public final static String JCR_PRIMARY_TYPE = "jcr:primaryType";
+       /**
+        * <code>jcr:mixinTypes</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_MIXIN_TYPES}.
+        */
+       public final static String JCR_MIXIN_TYPES = "jcr:mixinTypes";
+       /**
+        * <code>jcr:uuid</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_UUID}.
+        */
+       public final static String JCR_UUID = "jcr:uuid";
+       /**
+        * <code>jcr:created</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_CREATED}.
+        */
+       public final static String JCR_CREATED = "jcr:created";
+       /**
+        * <code>jcr:createdBy</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_CREATED_BY}.
+        */
+       public final static String JCR_CREATED_BY = "jcr:createdBy";
+       /**
+        * <code>jcr:lastModified</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_LAST_MODIFIED}.
+        */
+       public final static String JCR_LAST_MODIFIED = "jcr:lastModified";
+       /**
+        * <code>jcr:lastModifiedBy</code> with prefix instead of namespace (as in
+        * {@link Property#JCR_LAST_MODIFIED_BY}.
+        */
+       public final static String JCR_LAST_MODIFIED_BY = "jcr:lastModifiedBy";
+
        /**
         * @see Node#isNodeType(String)
         * @throws IllegalStateException caused by {@link RepositoryException}
index 857bd60b01044ac802584dd0697315a266b5e05c..e304649e23ac386c718895b532b0b276e52e92ca 100644 (file)
@@ -31,7 +31,6 @@ import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Property;
 import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -49,13 +48,11 @@ import javax.jcr.security.AccessControlPolicyIterator;
 import javax.jcr.security.Privilege;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
 /** Utility methods to simplify common JCR operations. */
 public class JcrUtils {
 
-       final private static Log log = LogFactory.getLog(JcrUtils.class);
+//     final private static Log log = LogFactory.getLog(JcrUtils.class);
 
        /**
         * Not complete yet. See
@@ -500,8 +497,8 @@ public class JcrUtils {
                                                currentNode = currentNode.addNode(part);
                                        if (versioning)
                                                currentNode.addMixin(NodeType.MIX_VERSIONABLE);
-                                       if (log.isTraceEnabled())
-                                               log.debug("Added folder " + part + " as " + current);
+//                                     if (log.isTraceEnabled())
+//                                             log.debug("Added folder " + part + " as " + current);
                                } else {
                                        currentNode = (Node) session.getItem(current.toString());
                                }
@@ -601,83 +598,83 @@ public class JcrUtils {
                }
        }
 
-       /** Recursively outputs the contents of the given node. */
-       public static void debug(Node node) {
-               debug(node, log);
-       }
-
-       /** Recursively outputs the contents of the given node. */
-       public static void debug(Node node, Log log) {
-               try {
-                       // First output the node path
-                       log.debug(node.getPath());
-                       // Skip the virtual (and large!) jcr:system subtree
-                       if (node.getName().equals("jcr:system")) {
-                               return;
-                       }
-
-                       // Then the children nodes (recursive)
-                       NodeIterator it = node.getNodes();
-                       while (it.hasNext()) {
-                               Node childNode = it.nextNode();
-                               debug(childNode, log);
-                       }
-
-                       // Then output the properties
-                       PropertyIterator properties = node.getProperties();
-                       // log.debug("Property are : ");
-
-                       properties: while (properties.hasNext()) {
-                               Property property = properties.nextProperty();
-                               if (property.getType() == PropertyType.BINARY)
-                                       continue properties;// skip
-                               if (property.getDefinition().isMultiple()) {
-                                       // A multi-valued property, print all values
-                                       Value[] values = property.getValues();
-                                       for (int i = 0; i < values.length; i++) {
-                                               log.debug(property.getPath() + "=" + values[i].getString());
-                                       }
-                               } else {
-                                       // A single-valued property
-                                       log.debug(property.getPath() + "=" + property.getString());
-                               }
-                       }
-               } catch (Exception e) {
-                       log.error("Could not debug " + node, e);
-               }
-
-       }
-
-       /** Logs the effective access control policies */
-       public static void logEffectiveAccessPolicies(Node node) {
-               try {
-                       logEffectiveAccessPolicies(node.getSession(), node.getPath());
-               } catch (RepositoryException e) {
-                       log.error("Cannot log effective access policies of " + node, e);
-               }
-       }
-
-       /** Logs the effective access control policies */
-       public static void logEffectiveAccessPolicies(Session session, String path) {
-               if (!log.isDebugEnabled())
-                       return;
+//     /** Recursively outputs the contents of the given node. */
+//     public static void debug(Node node) {
+//             debug(node, log);
+//     }
+//
+//     /** Recursively outputs the contents of the given node. */
+//     public static void debug(Node node, Log log) {
+//             try {
+//                     // First output the node path
+//                     log.debug(node.getPath());
+//                     // Skip the virtual (and large!) jcr:system subtree
+//                     if (node.getName().equals("jcr:system")) {
+//                             return;
+//                     }
+//
+//                     // Then the children nodes (recursive)
+//                     NodeIterator it = node.getNodes();
+//                     while (it.hasNext()) {
+//                             Node childNode = it.nextNode();
+//                             debug(childNode, log);
+//                     }
+//
+//                     // Then output the properties
+//                     PropertyIterator properties = node.getProperties();
+//                     // log.debug("Property are : ");
+//
+//                     properties: while (properties.hasNext()) {
+//                             Property property = properties.nextProperty();
+//                             if (property.getType() == PropertyType.BINARY)
+//                                     continue properties;// skip
+//                             if (property.getDefinition().isMultiple()) {
+//                                     // A multi-valued property, print all values
+//                                     Value[] values = property.getValues();
+//                                     for (int i = 0; i < values.length; i++) {
+//                                             log.debug(property.getPath() + "=" + values[i].getString());
+//                                     }
+//                             } else {
+//                                     // A single-valued property
+//                                     log.debug(property.getPath() + "=" + property.getString());
+//                             }
+//                     }
+//             } catch (Exception e) {
+//                     log.error("Could not debug " + node, e);
+//             }
+//
+//     }
 
-               try {
-                       AccessControlPolicy[] effectivePolicies = session.getAccessControlManager().getEffectivePolicies(path);
-                       if (effectivePolicies.length > 0) {
-                               for (AccessControlPolicy policy : effectivePolicies) {
-                                       if (policy instanceof AccessControlList) {
-                                               AccessControlList acl = (AccessControlList) policy;
-                                               log.debug("Access control list for " + path + "\n" + accessControlListSummary(acl));
-                                       }
-                               }
-                       } else {
-                               log.debug("No effective access control policy for " + path);
-                       }
-               } catch (RepositoryException e) {
-                       log.error("Cannot log effective access policies of " + path, e);
-               }
-       }
+//     /** Logs the effective access control policies */
+//     public static void logEffectiveAccessPolicies(Node node) {
+//             try {
+//                     logEffectiveAccessPolicies(node.getSession(), node.getPath());
+//             } catch (RepositoryException e) {
+//                     log.error("Cannot log effective access policies of " + node, e);
+//             }
+//     }
+//
+//     /** Logs the effective access control policies */
+//     public static void logEffectiveAccessPolicies(Session session, String path) {
+//             if (!log.isDebugEnabled())
+//                     return;
+//
+//             try {
+//                     AccessControlPolicy[] effectivePolicies = session.getAccessControlManager().getEffectivePolicies(path);
+//                     if (effectivePolicies.length > 0) {
+//                             for (AccessControlPolicy policy : effectivePolicies) {
+//                                     if (policy instanceof AccessControlList) {
+//                                             AccessControlList acl = (AccessControlList) policy;
+//                                             log.debug("Access control list for " + path + "\n" + accessControlListSummary(acl));
+//                                     }
+//                             }
+//                     } else {
+//                             log.debug("No effective access control policy for " + path);
+//                     }
+//             } catch (RepositoryException e) {
+//                     log.error("Cannot log effective access policies of " + path, e);
+//             }
+//     }
 
        /** Returns a human-readable summary of this access control list. */
        public static String accessControlListSummary(AccessControlList acl) {
@@ -1031,7 +1028,7 @@ public class JcrUtils {
                try {
                        discardQuietly(node.getSession());
                } catch (RepositoryException e) {
-                       log.warn("Cannot quietly discard session of node " + node + ": " + e.getMessage());
+                       // silent
                }
        }
 
@@ -1045,7 +1042,7 @@ public class JcrUtils {
                        if (session != null)
                                session.refresh(false);
                } catch (RepositoryException e) {
-                       log.warn("Cannot quietly discard session " + session + ": " + e.getMessage());
+                       // silent
                }
        }
 
@@ -1130,8 +1127,6 @@ public class JcrUtils {
                        unregisterQuietly(node.getSession().getWorkspace(), eventListener);
                } catch (RepositoryException e) {
                        // silent
-                       if (log.isTraceEnabled())
-                               log.trace("Could not unregister event listener " + eventListener);
                }
        }
 
@@ -1143,8 +1138,6 @@ public class JcrUtils {
                        workspace.getObservationManager().removeEventListener(eventListener);
                } catch (RepositoryException e) {
                        // silent
-                       if (log.isTraceEnabled())
-                               log.trace("Could not unregister event listener " + eventListener);
                }
        }
 
@@ -1293,13 +1286,13 @@ public class JcrUtils {
                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.getName() + " on " + path + " in '"
-                                       + session.getWorkspace().getName() + "'");
-               }
+//             if (log.isDebugEnabled()) {
+//                     StringBuffer privBuf = new StringBuffer();
+//                     for (Privilege priv : privs)
+//                             privBuf.append(priv.getName());
+//                     log.debug("Added privileges " + privBuf + " to " + principal.getName() + " on " + path + " in '"
+//                                     + session.getWorkspace().getName() + "'");
+//             }
                session.refresh(true);
                session.save();
                return true;
@@ -1402,8 +1395,8 @@ public class JcrUtils {
                                        toNode.getSession().save();
                                        count++;
 
-                                       if (log.isDebugEnabled())
-                                               log.debug("Copied file " + fromChild.getPath());
+//                                     if (log.isDebugEnabled())
+//                                             log.debug("Copied file " + fromChild.getPath());
                                        if (monitor != null)
                                                monitor.worked(1);
                                } else if (fromChild.isNodeType(NodeType.NT_FOLDER) && recursive) {
diff --git a/org.argeo.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java b/org.argeo.jcr/src/org/argeo/jcr/xml/JcrXmlUtils.java
new file mode 100644 (file)
index 0000000..6f1a922
--- /dev/null
@@ -0,0 +1,126 @@
+package org.argeo.jcr.xml;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.nodetype.NodeType;
+
+import org.argeo.jcr.Jcr;
+
+/** Utilities around JCR and XML. */
+public class JcrXmlUtils {
+       /**
+        * Convenience method calling {@link #toXmlElements(Writer, Node, boolean)} with
+        * <code>false</code>.
+        */
+       public static void toXmlElements(Writer writer, Node node) throws RepositoryException, IOException {
+               toXmlElements(writer, node, false, false);
+       }
+
+       /**
+        * Write JCR properties as XML elements in a tree structure whose elements are
+        * named by node primary type.
+        * 
+        * @param writer       the writer to use
+        * @param node         the subtree
+        * @param withMetadata whether to write the primary type and mixins as elements
+        *                     jcr:primaryType (
+        */
+       public static void toXmlElements(Writer writer, Node node, boolean withMetadata, boolean withPrefix)
+                       throws RepositoryException, IOException {
+               if (withMetadata && node.hasProperty(Property.JCR_UUID)) {
+                       writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix), "id",
+                                       "urn:uuid:" + node.getProperty(Property.JCR_UUID).getString());
+               } else {
+                       writeStart(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix));
+               }
+
+               // name
+               writeStart(writer, withPrefix ? Jcr.JCR_NAME : "name");
+               writer.append(node.getName());
+               writeEnd(writer, withPrefix ? Jcr.JCR_NAME : "name");
+
+               // mixins
+               if (withMetadata) {
+                       for (NodeType mixin : node.getMixinNodeTypes()) {
+                               writeStart(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes");
+                               writer.append(mixin.getName());
+                               writeEnd(writer, withPrefix ? Jcr.JCR_MIXIN_TYPES : "mixinTypes");
+                       }
+               }
+
+               // properties
+               PropertyIterator pit = node.getProperties();
+               properties: while (pit.hasNext()) {
+                       Property p = pit.nextProperty();
+                       if (p.isMultiple()) {
+                               for (Value value : p.getValues()) {
+                                       writeStart(writer, withPrefix(p.getName(), withPrefix));
+                                       writer.write(value.getString());
+                                       writeEnd(writer, withPrefix(p.getName(), withPrefix));
+                               }
+                       } else {
+                               Value value = p.getValue();
+                               String pName = p.getName();
+                               if (!withMetadata && (pName.equals(Jcr.JCR_PRIMARY_TYPE) || pName.equals(Jcr.JCR_UUID)
+                                               || pName.equals(Jcr.JCR_CREATED) || pName.equals(Jcr.JCR_CREATED_BY)
+                                               || pName.equals(Jcr.JCR_LAST_MODIFIED) || pName.equals(Jcr.JCR_LAST_MODIFIED_BY)))
+                                       continue properties;
+                               writeStart(writer, withPrefix(p.getName(), withPrefix));
+                               writer.write(value.getString());
+                               writeEnd(writer, withPrefix(p.getName(), withPrefix));
+                       }
+               }
+
+               // children
+               NodeIterator nit = node.getNodes();
+               while (nit.hasNext()) {
+                       toXmlElements(writer, nit.nextNode(), withMetadata, withPrefix);
+               }
+
+               writeEnd(writer, withPrefix(node.getPrimaryNodeType().getName(), withPrefix));
+       }
+
+       private static String withPrefix(String str, boolean withPrefix) {
+               if (withPrefix)
+                       return str;
+               int index = str.indexOf(':');
+               if (index < 0)
+                       return str;
+               return str.substring(index + 1);
+       }
+
+       private static void writeStart(Writer writer, String tagName) throws IOException {
+               writer.append('<');
+               writer.append(tagName);
+               writer.append('>');
+       }
+
+       private static void writeStart(Writer writer, String tagName, String attr, String value) throws IOException {
+               writer.append('<');
+               writer.append(tagName);
+               writer.append(' ');
+               writer.append(attr);
+               writer.append("=\"");
+               writer.append(value);
+               writer.append("\">");
+       }
+
+       private static void writeEnd(Writer writer, String tagName) throws IOException {
+               writer.append("</");
+               writer.append(tagName);
+               writer.append('>');
+       }
+
+       /** Singleton. */
+       private JcrXmlUtils() {
+
+       }
+
+}