import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.ArgeoException;
+import org.argeo.util.security.DigestUtils;
import org.argeo.util.security.SimplePrincipal;
/** Utility methods to simplify common JCR operations. */
.addNode(childName);
}
+ /** Convert a {@link NodeIterator} to a list of {@link Node} */
+ public static List<Node> nodeIteratorToList(NodeIterator nodeIterator) {
+ List<Node> nodes = new ArrayList<Node>();
+ while (nodeIterator.hasNext()) {
+ nodes.add(nodeIterator.nextNode());
+ }
+ return nodes;
+ }
+
+ /*
+ * PROPERTIES
+ */
+
+ /**
+ * Concisely get the string value of a property or null if this node doesn't
+ * have this property
+ */
+ public static String get(Node node, String propertyName) {
+ try {
+ if (!node.hasProperty(propertyName))
+ return null;
+ return node.getProperty(propertyName).getString();
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot get property " + propertyName
+ + " of " + node, e);
+ }
+ }
+
+ /** Concisely get the boolean value of a property */
+ public static Boolean check(Node node, String propertyName) {
+ try {
+ return node.getProperty(propertyName).getBoolean();
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot get property " + propertyName
+ + " of " + node, e);
+ }
+ }
+
+ /** Concisely get the bytes array value of a property */
+ public static byte[] getBytes(Node node, String propertyName) {
+ try {
+ return getBinaryAsBytes(node.getProperty(propertyName));
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot get property " + propertyName
+ + " of " + node, e);
+ }
+ }
+
/** Creates the nodes making path, if they don't exist. */
public static Node mkdirs(Session session, String path) {
return mkdirs(session, path, null, null, false);
return mkdirsSafe(session, path, null);
}
+ /**
+ * Creates the nodes making the path as {@link NodeType#NT_FOLDER}
+ */
+ public static Node mkfolders(Session session, String path) {
+ return mkdirs(session, path, NodeType.NT_FOLDER, NodeType.NT_FOLDER,
+ false);
+ }
+
/**
* Creates the nodes making path, if they don't exist. This is up to the
* caller to save the session. Use with caution since it can create
if (session.itemExists(path)) {
Node node = session.getNode(path);
// check type
- if (type != null && !node.isNodeType(type))
+ if (type != null && !node.isNodeType(type)
+ && !node.getPath().equals("/"))
throw new ArgeoException("Node " + node
+ " exists but is of type "
+ node.getPrimaryNodeType().getName()
}
}
+ /**
+ * Copy a file as an nt:file, assuming an nt:folder hierarchy. The session
+ * is NOT saved.
+ *
+ * @return the created file node
+ */
+ public static Node copyFile(Node folderNode, File file) {
+ InputStream in = null;
+ try {
+ in = new FileInputStream(file);
+ return copyStreamAsFile(folderNode, file.getName(), in);
+ } catch (IOException e) {
+ throw new ArgeoException("Cannot copy file " + file + " under "
+ + folderNode, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ /** Copy bytes as an nt:file */
+ public static Node copyBytesAsFile(Node folderNode, String fileName,
+ byte[] bytes) {
+ InputStream in = null;
+ try {
+ in = new ByteArrayInputStream(bytes);
+ return copyStreamAsFile(folderNode, fileName, in);
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot copy file " + fileName + " under "
+ + folderNode, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ /**
+ * Copy a stream as an nt:file, assuming an nt:folder hierarchy. The session
+ * is NOT saved.
+ *
+ * @return the created file node
+ */
+ public static Node copyStreamAsFile(Node folderNode, String fileName,
+ InputStream in) {
+ Binary binary = null;
+ try {
+ Node fileNode;
+ Node contentNode;
+ if (folderNode.hasNode(fileName)) {
+ fileNode = folderNode.getNode(fileName);
+ // we assume that the content node is already there
+ contentNode = fileNode.getNode(Node.JCR_CONTENT);
+ } else {
+ fileNode = folderNode.addNode(fileName, NodeType.NT_FILE);
+ contentNode = fileNode.addNode(Node.JCR_CONTENT,
+ NodeType.NT_RESOURCE);
+ }
+ binary = contentNode.getSession().getValueFactory()
+ .createBinary(in);
+ contentNode.setProperty(Property.JCR_DATA, binary);
+ return fileNode;
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot create file node " + fileName
+ + " under " + folderNode, e);
+ } finally {
+ closeQuietly(binary);
+ }
+ }
+
+ /** Computes the checksum of an nt:file */
+ public static String checksumFile(Node fileNode, String algorithm) {
+ Binary data = null;
+ InputStream in = null;
+ try {
+ data = fileNode.getNode(Node.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ in = data.getStream();
+ return DigestUtils.digest(algorithm, in);
+ } catch (RepositoryException e) {
+ throw new ArgeoException("Cannot checksum file " + fileNode, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ closeQuietly(data);
+ }
+ }
+
/**
* Creates depth from a string (typically a username) by adding levels based
* on its first characters: "aBcD",2 => a/aB
/**
* Add privileges on a path to a {@link Principal}. The path must already
- * exist.
+ * exist. Session is saved.
*/
public static void addPrivileges(Session session, String path,
Principal principal, List<Privilege> privs)
throw new ArgeoException("Don't know how to apply privileges "
+ privs + " to " + principal + " on " + path);
}
+ session.save();
}
}