X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.jcr%2Fsrc%2Forg%2Fargeo%2Fjcr%2FJcr.java;h=31077737e8e7e789335e263409b2279d190b1b27;hb=f65811e6912330a8d1e2ab330114f22d2bae43ed;hp=c3db4b604c71b1e8a955b45b2b5019de7a13dd14;hpb=32315b6eea1e2284e4269536b5fb7fee8cc03b8d;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 c3db4b604..31077737e 100644
--- a/org.argeo.jcr/src/org/argeo/jcr/Jcr.java
+++ b/org.argeo.jcr/src/org/argeo/jcr/Jcr.java
@@ -1,8 +1,13 @@
package org.argeo.jcr;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.math.BigDecimal;
+import java.text.MessageFormat;
import java.time.Instant;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
@@ -22,12 +27,16 @@ import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.Workspace;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
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;
+import org.apache.commons.io.IOUtils;
+
/**
* Utility class whose purpose is to make using JCR less verbose by
* systematically using unchecked exceptions and returning null
@@ -36,65 +45,128 @@ import javax.jcr.version.VersionManager;
* exceptions. Loosely inspired by Java's Files
singleton.
*/
public class Jcr {
+ /**
+ * The name of a node which will be serialized as XML text, as per section 7.3.1
+ * of the JCR 2.0 specifications.
+ */
+ public final static String JCR_XMLTEXT = "jcr:xmltext";
+ /**
+ * The name of a property which will be serialized as XML text, as per section
+ * 7.3.1 of the JCR 2.0 specifications.
+ */
+ public final static String JCR_XMLCHARACTERS = "jcr:xmlcharacters";
+ /**
+ * jcr:name
, 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";
+ /**
+ * jcr:path
, 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";
+ /**
+ * jcr:primaryType
with prefix instead of namespace (as in
+ * {@link Property#JCR_PRIMARY_TYPE}.
+ */
+ public final static String JCR_PRIMARY_TYPE = "jcr:primaryType";
+ /**
+ * jcr:mixinTypes
with prefix instead of namespace (as in
+ * {@link Property#JCR_MIXIN_TYPES}.
+ */
+ public final static String JCR_MIXIN_TYPES = "jcr:mixinTypes";
+ /**
+ * jcr:uuid
with prefix instead of namespace (as in
+ * {@link Property#JCR_UUID}.
+ */
+ public final static String JCR_UUID = "jcr:uuid";
+ /**
+ * jcr:created
with prefix instead of namespace (as in
+ * {@link Property#JCR_CREATED}.
+ */
+ public final static String JCR_CREATED = "jcr:created";
+ /**
+ * jcr:createdBy
with prefix instead of namespace (as in
+ * {@link Property#JCR_CREATED_BY}.
+ */
+ public final static String JCR_CREATED_BY = "jcr:createdBy";
+ /**
+ * jcr:lastModified
with prefix instead of namespace (as in
+ * {@link Property#JCR_LAST_MODIFIED}.
+ */
+ public final static String JCR_LAST_MODIFIED = "jcr:lastModified";
+ /**
+ * jcr:lastModifiedBy
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}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static boolean isNodeType(Node node, String nodeTypeName) {
try {
return node.isNodeType(nodeTypeName);
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get whether " + node + " is of type " + nodeTypeName, e);
+ throw new JcrException("Cannot get whether " + node + " is of type " + nodeTypeName, e);
}
}
/**
* @see Node#hasNodes()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static boolean hasNodes(Node node) {
try {
return node.hasNodes();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get whether " + node + " has children.", e);
+ throw new JcrException("Cannot get whether " + node + " has children.", e);
}
}
/**
* @see Node#getParent()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Node getParent(Node node) {
try {
return isRoot(node) ? null : node.getParent();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get parent of " + node, e);
+ throw new JcrException("Cannot get parent of " + node, e);
}
}
+ /**
+ * @see Node#getParent()
+ * @throws JcrException caused by {@link RepositoryException}
+ */
+ public static String getParentPath(Node node) {
+ return getPath(getParent(node));
+ }
+
/**
* Whether this node is the root node.
*
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static boolean isRoot(Node node) {
try {
return node.getDepth() == 0;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get depth of " + node, e);
+ throw new JcrException("Cannot get depth of " + node, e);
}
}
/**
* @see Node#getPath()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static String getPath(Node node) {
try {
return node.getPath();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get path of " + node, e);
+ throw new JcrException("Cannot get path of " + node, e);
}
}
@@ -109,25 +181,67 @@ public class Jcr {
/**
* @see Node#getIdentifier()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static String getIdentifier(Node node) {
try {
return node.getIdentifier();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get identifier of " + node, e);
+ throw new JcrException("Cannot get identifier of " + node, e);
}
}
/**
* @see Node#getName()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static String getName(Node node) {
try {
return node.getName();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get name of " + node, e);
+ throw new JcrException("Cannot get name of " + node, e);
+ }
+ }
+
+ /**
+ * Returns the node name with its current index (useful for re-ordering).
+ *
+ * @see Node#getName()
+ * @see Node#getIndex()
+ * @throws JcrException caused by {@link RepositoryException}
+ */
+ public static String getIndexedName(Node node) {
+ try {
+ return node.getName() + "[" + node.getIndex() + "]";
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot get name of " + node, e);
+ }
+ }
+
+ /**
+ * @see Node#getProperty(String)
+ * @throws JcrException caused by {@link RepositoryException}
+ */
+ public static Property getProperty(Node node, String property) {
+ try {
+ if (node.hasProperty(property))
+ return node.getProperty(property);
+ else
+ return null;
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot get property " + property + " of " + node, e);
+ }
+ }
+
+ /**
+ * @see Node#getIndex()
+ * @throws JcrException caused by {@link RepositoryException}
+ */
+ public static int getIndex(Node node) {
+ try {
+ return node.getIndex();
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot get index of " + node, e);
}
}
@@ -157,20 +271,20 @@ public class Jcr {
/**
* @return the children as an {@link Iterable} for use in for-each llops.
* @see Node#getNodes()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Iterable nodes(Node node) {
try {
return iterate(node.getNodes());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get children of " + node, e);
+ throw new JcrException("Cannot get children of " + node, e);
}
}
/**
* @return the children as a (possibly empty) {@link List}.
* @see Node#getNodes()
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static List getNodes(Node node) {
List nodes = new ArrayList<>();
@@ -183,14 +297,14 @@ public class Jcr {
} else
return nodes;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get children of " + node, e);
+ throw new JcrException("Cannot get children of " + node, e);
}
}
/**
* @return the child or null
if not found
* @see Node#getNode(String)
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Node getNode(Node node, String child) {
try {
@@ -199,14 +313,14 @@ public class Jcr {
else
return null;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get child of " + node, e);
+ throw new JcrException("Cannot get child of " + node, e);
}
}
/**
* @return the node at this path or null
if not found
* @see Session#getNode(String)
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Node getNode(Session session, String path) {
try {
@@ -215,14 +329,93 @@ public class Jcr {
else
return null;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get node " + path, e);
+ throw new JcrException("Cannot get node " + path, e);
+ }
+ }
+
+ /**
+ * Add a node to this parent, setting its primary type and its mixins.
+ *
+ * @param parent the parent node
+ * @param name the name of the node, if null
, the primary
+ * type will be used (typically for XML structures)
+ * @param primaryType the primary type, if null
+ * {@link NodeType#NT_UNSTRUCTURED} will be used.
+ * @param mixins the mixins
+ * @return the created node
+ * @see Node#addNode(String, String)
+ * @see Node#addMixin(String)
+ */
+ public static Node addNode(Node parent, String name, String primaryType, String... mixins) {
+ if (name == null && primaryType == null)
+ throw new IllegalArgumentException("Both node name and primary type cannot be null");
+ try {
+ Node newNode = parent.addNode(name == null ? primaryType : name,
+ primaryType == null ? NodeType.NT_UNSTRUCTURED : primaryType);
+ for (String mixin : mixins) {
+ newNode.addMixin(mixin);
+ }
+ return newNode;
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot add node " + name + " to " + parent, e);
+ }
+ }
+
+ /**
+ * Add an {@link NodeType#NT_BASE} node to this parent.
+ *
+ * @param parent the parent node
+ * @param name the name of the node, cannot be null
+ * @return the created node
+ *
+ * @see Node#addNode(String)
+ */
+ public static Node addNode(Node parent, String name) {
+ if (name == null)
+ throw new IllegalArgumentException("Node name cannot be null");
+ try {
+ Node newNode = parent.addNode(name);
+ return newNode;
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot add node " + name + " to " + parent, e);
+ }
+ }
+
+ /**
+ * Add mixins to a node.
+ *
+ * @param node the node
+ * @param mixins the mixins
+ * @return the created node
+ * @see Node#addMixin(String)
+ */
+ public static void addMixin(Node node, String... mixins) {
+ try {
+ for (String mixin : mixins) {
+ node.addMixin(mixin);
+ }
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot add mixins " + Arrays.asList(mixins) + " to " + node, e);
+ }
+ }
+
+ /**
+ * Removes this node.
+ *
+ * @see Node#remove()
+ */
+ public static void remove(Node node) {
+ try {
+ node.remove();
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot remove node " + node, e);
}
}
/**
* @return the node with htis id or null
if not found
* @see Session#getNodeByIdentifier(String)
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Node getNodeById(Session session, String id) {
try {
@@ -230,7 +423,7 @@ public class Jcr {
} catch (ItemNotFoundException e) {
return null;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get node with id " + id, e);
+ throw new JcrException("Cannot get node with id " + id, e);
}
}
@@ -238,24 +431,62 @@ public class Jcr {
* Set a property to the given value, or remove it if the value is
* null
.
*
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException 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);
+ if (!node.hasProperty(property)) {
+ if (value != null) {
+ if (value instanceof List) {// multiple
+ List> lst = (List>) value;
+ String[] values = new String[lst.size()];
+ for (int i = 0; i < lst.size(); i++) {
+ values[i] = lst.get(i).toString();
+ }
+ node.setProperty(property, values);
+ } else {
+ node.setProperty(property, value.toString());
+ }
+ }
+ return;
+ }
Property prop = node.getProperty(property);
if (value == null) {
prop.remove();
return;
}
+ // multiple
+ if (value instanceof List) {
+ List> lst = (List>) value;
+ String[] values = new String[lst.size()];
+ // TODO better cast?
+ for (int i = 0; i < lst.size(); i++) {
+ values[i] = lst.get(i).toString();
+ }
+ if (!prop.isMultiple())
+ prop.remove();
+ node.setProperty(property, values);
+ return;
+ }
+
+ // single
+ if (prop.isMultiple()) {
+ prop.remove();
+ node.setProperty(property, value.toString());
+ return;
+ }
+
if (value instanceof String)
prop.setValue((String) value);
else if (value instanceof Long)
prop.setValue((Long) value);
+ else if (value instanceof Integer)
+ prop.setValue(((Integer) value).longValue());
else if (value instanceof Double)
prop.setValue((Double) value);
+ else if (value instanceof Float)
+ prop.setValue(((Float) value).doubleValue());
else if (value instanceof Calendar)
prop.setValue((Calendar) value);
else if (value instanceof BigDecimal)
@@ -272,7 +503,7 @@ public class Jcr {
} else // try with toString()
prop.setValue(value.toString());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot set property " + property + " of " + node + " to " + value, e);
+ throw new JcrException("Cannot set property " + property + " of " + node + " to " + value, e);
}
}
@@ -282,28 +513,38 @@ public class Jcr {
* @return the value of
* {@link Node#getProperty(String)}.{@link Property#getString()} or
* null
if the property does not exist.
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static String get(Node node, String property) {
return get(node, property, null);
}
/**
- * Get property as a {@link String}.
+ * Get property as a {@link String}. If the property is multiple it returns the
+ * first value.
*
* @return the value of
* {@link Node#getProperty(String)}.{@link Property#getString()} or
* defaultValue
if the property does not exist.
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static String get(Node node, String property, String defaultValue) {
try {
- if (node.hasProperty(property))
- return node.getProperty(property).getString();
- else
+ if (node.hasProperty(property)) {
+ Property p = node.getProperty(property);
+ if (!p.isMultiple())
+ return p.getString();
+ else {
+ Value[] values = p.getValues();
+ if (values.length == 0)
+ return defaultValue;
+ else
+ return values[0].getString();
+ }
+ } else
return defaultValue;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot retrieve property " + property + " from " + node);
+ throw new JcrException("Cannot retrieve property " + property + " from " + node, e);
}
}
@@ -312,7 +553,7 @@ public class Jcr {
*
* @return {@link Node#getProperty(String)} or null
if the property
* does not exist.
- * @throws IllegalStateException caused by {@link RepositoryException}
+ * @throws JcrException caused by {@link RepositoryException}
*/
public static Value getValue(Node node, String property) {
try {
@@ -321,7 +562,7 @@ public class Jcr {
else
return null;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot retrieve property " + property + " from " + node);
+ throw new JcrException("Cannot retrieve property " + property + " from " + node, e);
}
}
@@ -331,29 +572,21 @@ public class Jcr {
* @return the value of {@link Node#getProperty(String)} or
* defaultValue
if the property does not exist.
* @throws IllegalArgumentException if the value could not be cast
- * @throws IllegalStateException in case of unexpected
+ * @throws JcrException in case of unexpected
* {@link RepositoryException}
*/
@SuppressWarnings("unchecked")
public static T getAs(Node node, String property, T defaultValue) {
try {
+ // TODO deal with multiple
if (node.hasProperty(property)) {
Property p = node.getProperty(property);
try {
- switch (p.getType()) {
- case PropertyType.STRING:
- return (T) node.getProperty(property).getString();
- case PropertyType.DOUBLE:
- return (T) (Double) node.getProperty(property).getDouble();
- case PropertyType.LONG:
- return (T) (Long) node.getProperty(property).getLong();
- case PropertyType.BOOLEAN:
- return (T) (Boolean) node.getProperty(property).getBoolean();
- case PropertyType.DATE:
- return (T) node.getProperty(property).getDate();
- default:
- return (T) node.getProperty(property).getString();
+ if (p.isMultiple()) {
+ throw new UnsupportedOperationException("Multiple values properties are not supported");
}
+ Value value = p.getValue();
+ return (T) get(value);
} catch (ClassCastException e) {
throw new IllegalArgumentException(
"Cannot cast property of type " + PropertyType.nameFromValue(p.getType()), e);
@@ -362,16 +595,124 @@ public class Jcr {
return defaultValue;
}
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot retrieve property " + property + " from " + node);
+ throw new JcrException("Cannot retrieve property " + property + " from " + node, e);
}
}
- /** Retrieves the {@link Session} related to this node. */
+ /**
+ * Get a multiple property as a list, doing a best effort to cast it as the
+ * target list.
+ *
+ * @return the value of {@link Node#getProperty(String)}.
+ * @throws IllegalArgumentException if the value could not be cast
+ * @throws JcrException in case of unexpected
+ * {@link RepositoryException}
+ */
+ public static List getMultiple(Node node, String property) {
+ try {
+ if (node.hasProperty(property)) {
+ Property p = node.getProperty(property);
+ return getMultiple(p);
+ } else {
+ return null;
+ }
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot retrieve multiple values property " + property + " from " + node, e);
+ }
+ }
+
+ /**
+ * Get a multiple property as a list, doing a best effort to cast it as the
+ * target list.
+ */
+ @SuppressWarnings("unchecked")
+ public static List getMultiple(Property p) {
+ try {
+ List res = new ArrayList<>();
+ if (!p.isMultiple()) {
+ res.add((T) get(p.getValue()));
+ return res;
+ }
+ Value[] values = p.getValues();
+ for (Value value : values) {
+ res.add((T) get(value));
+ }
+ return res;
+ } catch (ClassCastException | RepositoryException e) {
+ throw new IllegalArgumentException("Cannot get property " + p, e);
+ }
+ }
+
+ /** Cast a {@link Value} to a standard Java object. */
+ public static Object get(Value value) {
+ Binary binary = null;
+ try {
+ switch (value.getType()) {
+ case PropertyType.STRING:
+ return value.getString();
+ case PropertyType.DOUBLE:
+ return (Double) value.getDouble();
+ case PropertyType.LONG:
+ return (Long) value.getLong();
+ case PropertyType.BOOLEAN:
+ return (Boolean) value.getBoolean();
+ case PropertyType.DATE:
+ return value.getDate();
+ case PropertyType.BINARY:
+ binary = value.getBinary();
+ byte[] arr = null;
+ try (InputStream in = binary.getStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();) {
+ IOUtils.copy(in, out);
+ arr = out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot read binary from " + value, e);
+ }
+ return arr;
+ default:
+ return value.getString();
+ }
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot cast value from " + value, e);
+ } finally {
+ if (binary != null)
+ binary.dispose();
+ }
+ }
+
+ /**
+ * 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);
+ throw new JcrException("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 JcrException("Cannot get root node for " + session, e);
+ }
+ }
+
+ /** Whether this item exists. */
+ public static boolean itemExists(Session session, String path) {
+ try {
+ return session.itemExists(path);
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot check whether " + path + " exists", e);
}
}
@@ -389,7 +730,7 @@ public class Jcr {
if (session.hasPendingChanges())
session.save();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot save session related to " + node + " in workspace "
+ throw new JcrException("Cannot save session related to " + node + " in workspace "
+ session(node).getWorkspace().getName(), e);
}
}
@@ -414,6 +755,11 @@ public class Jcr {
}
}
+ /** Safely and silently logs out the underlying session. */
+ public static void logout(Node node) {
+ Jcr.logout(session(node));
+ }
+
/*
* SECURITY
*/
@@ -427,7 +773,7 @@ public class Jcr {
Session session = node.getSession();
JcrUtils.addPrivilege(session, node.getPath(), principal, privilege);
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot add privilege " + privilege + " to " + node, e);
+ throw new JcrException("Cannot add privilege " + privilege + " to " + node, e);
}
}
@@ -439,7 +785,7 @@ public class Jcr {
try {
return node.isCheckedOut();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot retrieve checked out status of " + node, e);
+ throw new JcrException("Cannot retrieve checked out status of " + node, e);
}
}
@@ -448,7 +794,7 @@ public class Jcr {
try {
versionManager(node).checkpoint(node.getPath());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot check in " + node, e);
+ throw new JcrException("Cannot check in " + node, e);
}
}
@@ -457,7 +803,7 @@ public class Jcr {
try {
versionManager(node).checkin(node.getPath());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot check in " + node, e);
+ throw new JcrException("Cannot check in " + node, e);
}
}
@@ -466,7 +812,7 @@ public class Jcr {
try {
versionManager(node).checkout(node.getPath());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot check out " + node, e);
+ throw new JcrException("Cannot check out " + node, e);
}
}
@@ -475,7 +821,7 @@ public class Jcr {
try {
return node.getSession().getWorkspace().getVersionManager();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get version manager from " + node, e);
+ throw new JcrException("Cannot get version manager from " + node, e);
}
}
@@ -484,7 +830,7 @@ public class Jcr {
try {
return versionManager(node).getVersionHistory(node.getPath());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get version history from " + node, e);
+ throw new JcrException("Cannot get version history from " + node, e);
}
}
@@ -502,7 +848,7 @@ public class Jcr {
Collections.reverse(lst);
return lst;
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get linear versions from " + versionHistory, e);
+ throw new JcrException("Cannot get linear versions from " + versionHistory, e);
}
}
@@ -511,7 +857,7 @@ public class Jcr {
try {
return version.getFrozenNode();
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get frozen node from " + version, e);
+ throw new JcrException("Cannot get frozen node from " + version, e);
}
}
@@ -520,7 +866,7 @@ public class Jcr {
try {
return versionManager(node).getBaseVersion(node.getPath());
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get base version from " + node, e);
+ throw new JcrException("Cannot get base version from " + node, e);
}
}
@@ -538,7 +884,7 @@ public class Jcr {
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);
+ throw new JcrException("Cannot get file size of " + fileNode, e);
}
}
@@ -549,8 +895,75 @@ public class Jcr {
return binary.getSize();
}
} catch (RepositoryException e) {
- throw new IllegalStateException("Cannot get file size of binary " + binaryArg, e);
+ throw new JcrException("Cannot get file size of binary " + binaryArg, e);
+ }
+ }
+
+ // QUERY
+ /** Creates a JCR-SQL2 query using {@link MessageFormat}. */
+ public static Query createQuery(QueryManager qm, String sql, Object... args) {
+ String query = MessageFormat.format(sql, args);
+ try {
+ return qm.createQuery(query, Query.JCR_SQL2);
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot create JCR-SQL2 query from " + query, e);
+ }
+ }
+
+ /** Executes a JCR-SQL2 query using {@link MessageFormat}. */
+ public static NodeIterator executeQuery(QueryManager qm, String sql, Object... args) {
+ Query query = createQuery(qm, sql, args);
+ try {
+ return query.execute().getNodes();
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot execute query " + sql + " with arguments " + Arrays.asList(args), e);
+ }
+ }
+
+ /** Executes a JCR-SQL2 query using {@link MessageFormat}. */
+ public static NodeIterator executeQuery(Session session, String sql, Object... args) {
+ QueryManager queryManager;
+ try {
+ queryManager = session.getWorkspace().getQueryManager();
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot get query manager from session " + session, e);
+ }
+ return executeQuery(queryManager, sql, args);
+ }
+
+ /**
+ * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a
+ * single node at most.
+ *
+ * @return the node or null
if not found.
+ */
+ public static Node getNode(QueryManager qm, String sql, Object... args) {
+ NodeIterator nit = executeQuery(qm, sql, args);
+ if (nit.hasNext()) {
+ Node node = nit.nextNode();
+ if (nit.hasNext())
+ throw new IllegalStateException(
+ "Query " + sql + " with arguments " + Arrays.asList(args) + " returned more than one node.");
+ return node;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Executes a JCR-SQL2 query using {@link MessageFormat}, which must return a
+ * single node at most.
+ *
+ * @return the node or null
if not found.
+ */
+ public static Node getNode(Session session, String sql, Object... args) {
+ QueryManager queryManager;
+ try {
+ queryManager = session.getWorkspace().getQueryManager();
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot get query manager from session " + session, e);
}
+ return getNode(queryManager, sql, args);
}
/** Singleton. */