X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;ds=inline;f=org.argeo.jcr%2Fsrc%2Forg%2Fargeo%2Fjcr%2FJcr.java;h=fb6f610131842bf546196eeaa7eb3302f029586a;hb=215480a865603e0090c43114541441ac1586b379;hp=f8ad9c79cca88dd58526b0320612940e61993c8d;hpb=25e4528153640a2e211e217468f8f5aa01607cf0;p=lgpl%2Fargeo-commons.git
diff --git a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java
index f8ad9c79c..fb6f61013 100644
--- a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java
+++ b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java
@@ -1,9 +1,16 @@
package org.argeo.jcr;
+import java.math.BigDecimal;
+import java.time.Instant;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
+import javax.jcr.Binary;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
@@ -13,6 +20,13 @@ import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.security.Privilege;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+import javax.jcr.version.VersionManager;
/**
* Utility class whose purpose is to make using JCR less verbose by
@@ -22,7 +36,6 @@ import javax.jcr.Value;
* exceptions. Loosely inspired by Java's Files
singleton.
*/
public class Jcr {
-
/**
* @see Node#isNodeType(String)
* @throws IllegalStateException caused by {@link RepositoryException}
@@ -84,6 +97,15 @@ public class Jcr {
}
}
+ /**
+ * @see Node#getSession()
+ * @see Session#getWorkspace()
+ * @see Workspace#getName()
+ */
+ public static String getWorkspaceName(Node node) {
+ return session(node).getWorkspace().getName();
+ }
+
/**
* @see Node#getIdentifier()
* @throws IllegalStateException caused by {@link RepositoryException}
@@ -108,6 +130,17 @@ public class Jcr {
}
}
+ /**
+ * If node has mixin {@link NodeType#MIX_TITLE}, return
+ * {@link Property#JCR_TITLE}, otherwise return {@link #getName(Node)}.
+ */
+ public static String getTitle(Node node) {
+ if (Jcr.isNodeType(node, NodeType.MIX_TITLE))
+ return get(node, Property.JCR_TITLE);
+ else
+ return Jcr.getName(node);
+ }
+
/** Accesses a {@link NodeIterator} as an {@link Iterable}. */
@SuppressWarnings("unchecked")
public static Iterable iterate(NodeIterator nodeIterator) {
@@ -200,6 +233,48 @@ public class Jcr {
}
}
+ /**
+ * Set a property to the given value, or remove it if the value is
+ * null
.
+ *
+ * @throws IllegalStateException caused by {@link RepositoryException}
+ */
+ public static void set(Node node, String property, Object value) {
+ try {
+ if (!node.hasProperty(property))
+ throw new IllegalArgumentException("No property " + property + " in " + node);
+ Property prop = node.getProperty(property);
+ if (value == null) {
+ prop.remove();
+ return;
+ }
+
+ if (value instanceof String)
+ prop.setValue((String) value);
+ else if (value instanceof Long)
+ prop.setValue((Long) value);
+ else if (value instanceof Double)
+ prop.setValue((Double) value);
+ else if (value instanceof Calendar)
+ prop.setValue((Calendar) value);
+ else if (value instanceof BigDecimal)
+ prop.setValue((BigDecimal) value);
+ else if (value instanceof Boolean)
+ prop.setValue((Boolean) value);
+ else if (value instanceof byte[])
+ JcrUtils.setBinaryAsBytes(prop, (byte[]) value);
+ else if (value instanceof Instant) {
+ Instant instant = (Instant) value;
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTime(Date.from(instant));
+ prop.setValue(calendar);
+ } else // try with toString()
+ prop.setValue(value.toString());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot set property " + property + " of " + node + " to " + value, e);
+ }
+ }
+
/**
* Get property as {@link String}.
*
@@ -290,6 +365,53 @@ public class Jcr {
}
}
+ /**
+ * Retrieves the {@link Session} related to this node.
+ *
+ * @deprecated Use {@link #getSession(Node)} instead.
+ */
+ @Deprecated
+ public static Session session(Node node) {
+ return getSession(node);
+ }
+
+ /** Retrieves the {@link Session} related to this node. */
+ public static Session getSession(Node node) {
+ try {
+ return node.getSession();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot retrieve session related to " + node, e);
+ }
+ }
+
+ /** Retrieves the root node related to this session. */
+ public static Node getRootNode(Session session) {
+ try {
+ return session.getRootNode();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get root node for " + session, e);
+ }
+ }
+
+ /**
+ * Saves the {@link Session} related to this node. Note that all other unrelated
+ * modifications in this session will also be saved.
+ */
+ public static void save(Node node) {
+ try {
+ Session session = node.getSession();
+// if (node.isNodeType(NodeType.MIX_LAST_MODIFIED)) {
+// set(node, Property.JCR_LAST_MODIFIED, Instant.now());
+// set(node, Property.JCR_LAST_MODIFIED_BY, session.getUserID());
+// }
+ if (session.hasPendingChanges())
+ session.save();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot save session related to " + node + " in workspace "
+ + session(node).getWorkspace().getName(), e);
+ }
+ }
+
/** Login to a JCR repository. */
public static Session login(Repository repository, String workspace) {
try {
@@ -310,6 +432,150 @@ public class Jcr {
}
}
+ /** Safely and silently logs out the underlying session. */
+ public static void logout(Node node) {
+ Jcr.logout(session(node));
+ }
+
+ /*
+ * SECURITY
+ */
+ /**
+ * Add a single privilege to a node.
+ *
+ * @see Privilege
+ */
+ public static void addPrivilege(Node node, String principal, String privilege) {
+ try {
+ Session session = node.getSession();
+ JcrUtils.addPrivilege(session, node.getPath(), principal, privilege);
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot add privilege " + privilege + " to " + node, e);
+ }
+ }
+
+ /*
+ * VERSIONING
+ */
+ /** Get checked out status. */
+ public static boolean isCheckedOut(Node node) {
+ try {
+ return node.isCheckedOut();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot retrieve checked out status of " + node, e);
+ }
+ }
+
+ /** @see VersionManager#checkpoint(String) */
+ public static void checkpoint(Node node) {
+ try {
+ versionManager(node).checkpoint(node.getPath());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot check in " + node, e);
+ }
+ }
+
+ /** @see VersionManager#checkin(String) */
+ public static void checkin(Node node) {
+ try {
+ versionManager(node).checkin(node.getPath());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot check in " + node, e);
+ }
+ }
+
+ /** @see VersionManager#checkout(String) */
+ public static void checkout(Node node) {
+ try {
+ versionManager(node).checkout(node.getPath());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot check out " + node, e);
+ }
+ }
+
+ /** Get the {@link VersionManager} related to this node. */
+ public static VersionManager versionManager(Node node) {
+ try {
+ return node.getSession().getWorkspace().getVersionManager();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get version manager from " + node, e);
+ }
+ }
+
+ /** Get the {@link VersionHistory} related to this node. */
+ public static VersionHistory getVersionHistory(Node node) {
+ try {
+ return versionManager(node).getVersionHistory(node.getPath());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get version history from " + node, e);
+ }
+ }
+
+ /**
+ * The linear versions of this version history in reverse order and without the
+ * root version.
+ */
+ public static List getLinearVersions(VersionHistory versionHistory) {
+ try {
+ List lst = new ArrayList<>();
+ VersionIterator vit = versionHistory.getAllLinearVersions();
+ while (vit.hasNext())
+ lst.add(vit.nextVersion());
+ lst.remove(0);
+ Collections.reverse(lst);
+ return lst;
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get linear versions from " + versionHistory, e);
+ }
+ }
+
+ /** The frozen node related to this {@link Version}. */
+ public static Node getFrozenNode(Version version) {
+ try {
+ return version.getFrozenNode();
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get frozen node from " + version, e);
+ }
+ }
+
+ /** Get the base {@link Version} related to this node. */
+ public static Version getBaseVersion(Node node) {
+ try {
+ return versionManager(node).getBaseVersion(node.getPath());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get base version from " + node, e);
+ }
+ }
+
+ /*
+ * FILES
+ */
+ /**
+ * Returns the size of this file.
+ *
+ * @see NodeType#NT_FILE
+ */
+ public static long getFileSize(Node fileNode) {
+ try {
+ if (!fileNode.isNodeType(NodeType.NT_FILE))
+ throw new IllegalArgumentException(fileNode + " must be a file.");
+ return getBinarySize(fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary());
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get file size of " + fileNode, e);
+ }
+ }
+
+ /** Returns the size of this {@link Binary}. */
+ public static long getBinarySize(Binary binaryArg) {
+ try {
+ try (Bin binary = new Bin(binaryArg)) {
+ return binary.getSize();
+ }
+ } catch (RepositoryException e) {
+ throw new IllegalStateException("Cannot get file size of binary " + binaryArg, e);
+ }
+ }
+
/** Singleton. */
private Jcr() {