import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import javax.jcr.Binary;
import javax.jcr.Credentials;
+import javax.jcr.ImportUUIDBehavior;
import javax.jcr.NamespaceRegistry;
import javax.jcr.NoSuchWorkspaceException;
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;
import javax.jcr.Value;
import javax.jcr.Workspace;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.observation.EventListener;
import javax.jcr.query.Query;
}
}
+ /** Copy the whole workspace via a system view XML. */
+ public static void copyWorkspaceXml(Session fromSession, Session toSession) {
+ Workspace fromWorkspace = fromSession.getWorkspace();
+ Workspace toWorkspace = toSession.getWorkspace();
+ String errorMsg = "Cannot copy workspace " + fromWorkspace + " to " + toWorkspace + " via XML.";
+
+ try (PipedInputStream in = new PipedInputStream(1024 * 1024);) {
+ new Thread(() -> {
+ try (PipedOutputStream out = new PipedOutputStream(in)) {
+ fromSession.exportSystemView("/", out, false, false);
+ out.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(errorMsg, e);
+ } catch (RepositoryException e) {
+ throw new JcrException(errorMsg, e);
+ }
+ }, "Copy workspace" + fromWorkspace + " to " + toWorkspace).start();
+
+ toSession.importXML("/", in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING);
+ toSession.save();
+ } catch (IOException e) {
+ throw new RuntimeException(errorMsg, e);
+ } catch (RepositoryException e) {
+ throw new JcrException(errorMsg, e);
+ }
+ }
+
/**
* Copies recursively the content of a node to another one. Do NOT copy the
* property values of {@link NodeType#MIX_CREATED} and
if (toNode.getDefinition().isProtected())
return;
+ // add mixins
+ for (NodeType mixinType : fromNode.getMixinNodeTypes()) {
+ try {
+ toNode.addMixin(mixinType.getName());
+ } catch (NoSuchNodeTypeException e) {
+ // ignore unknown mixins
+ // TODO log it
+ }
+ }
+
// process properties
PropertyIterator pit = fromNode.getProperties();
properties: while (pit.hasNext()) {
// they existed, before adding the mixins
updateLastModified(toNode, true);
- // add mixins
- for (NodeType mixinType : fromNode.getMixinNodeTypes()) {
- toNode.addMixin(mixinType.getName());
- }
-
// process children nodes
NodeIterator nit = fromNode.getNodes();
while (nit.hasNext()) {
Node toChild;
if (toNode.hasNode(nodeRelPath))
toChild = toNode.getNode(nodeRelPath);
- else
- toChild = toNode.addNode(fromChild.getName(), fromChild.getPrimaryNodeType().getName());
+ else {
+ try {
+ toChild = toNode.addNode(fromChild.getName(), fromChild.getPrimaryNodeType().getName());
+ } catch (NoSuchNodeTypeException e) {
+ // ignore unknown primary types
+ // TODO log it
+ return;
+ }
+ }
copy(fromChild, toChild);
}
} catch (RepositoryException e) {
// the new access control list must be applied otherwise this call:
// acl.removeAccessControlEntry(ace); has no effect
acm.setPolicy(path, acl);
+ session.refresh(true);
+ session.save();
}
/*
*
* @return the created file node
*/
+ @Deprecated
public static Node copyFile(Node folderNode, File file) {
try (InputStream in = new FileInputStream(file)) {
return copyStreamAsFile(folderNode, file.getName(), in);
}
binary = contentNode.getSession().getValueFactory().createBinary(in);
contentNode.setProperty(Property.JCR_DATA, binary);
+ updateLastModified(contentNode);
return fileNode;
} catch (RepositoryException e) {
throw new JcrException("Cannot create file node " + fileName + " under " + folderNode, e);
return fileNode.getNode(Node.JCR_CONTENT).getProperty(Property.JCR_DATA).getBinary().getStream();
}
+ /**
+ * Set the properties of {@link NodeType#MIX_MIMETYPE} on the content of this
+ * file node.
+ */
+ public static void setFileMimeType(Node fileNode, String mimeType, String encoding) throws RepositoryException {
+ Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
+ if (mimeType != null)
+ contentNode.setProperty(Property.JCR_MIMETYPE, mimeType);
+ if (encoding != null)
+ contentNode.setProperty(Property.JCR_ENCODING, encoding);
+ // TODO remove properties if args are null?
+ }
+
+ public static void copyFilesToFs(Node baseNode, Path targetDir, boolean recursive) {
+ try {
+ Files.createDirectories(targetDir);
+ for (NodeIterator nit = baseNode.getNodes(); nit.hasNext();) {
+ Node node = nit.nextNode();
+ if (node.isNodeType(NodeType.NT_FILE)) {
+ Path filePath = targetDir.resolve(node.getName());
+ try (OutputStream out = Files.newOutputStream(filePath); InputStream in = getFileAsStream(node)) {
+ IOUtils.copy(in, out);
+ }
+ } else if (recursive && node.isNodeType(NodeType.NT_FOLDER)) {
+ Path dirPath = targetDir.resolve(node.getName());
+ copyFilesToFs(node, dirPath, true);
+ }
+ }
+ } catch (RepositoryException e) {
+ throw new JcrException("Cannot copy " + baseNode + " to " + targetDir, e);
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot copy " + baseNode + " to " + targetDir, e);
+ }
+ }
+
/**
* Computes the checksum of an nt:file.
*
return new String(hexChars);
}
+ /** Export a subtree as a compact XML without namespaces. */
+ public static void toSimpleXml(Node node, StringBuilder sb) throws RepositoryException {
+ sb.append('<');
+ String nodeName = node.getName();
+ int colIndex = nodeName.indexOf(':');
+ if (colIndex > 0) {
+ nodeName = nodeName.substring(colIndex + 1);
+ }
+ sb.append(nodeName);
+ PropertyIterator pit = node.getProperties();
+ properties: while (pit.hasNext()) {
+ Property p = pit.nextProperty();
+ // skip multiple properties
+ if (p.isMultiple())
+ continue properties;
+ String propertyName = p.getName();
+ int pcolIndex = propertyName.indexOf(':');
+ // skip properties with namespaces
+ if (pcolIndex > 0)
+ continue properties;
+ // skip binaries
+ if (p.getType() == PropertyType.BINARY) {
+ continue properties;
+ // TODO retrieve identifier?
+ }
+ sb.append(' ');
+ sb.append(propertyName);
+ sb.append('=');
+ sb.append('\"').append(p.getString()).append('\"');
+ }
+
+ if (node.hasNodes()) {
+ sb.append('>');
+ NodeIterator children = node.getNodes();
+ while (children.hasNext()) {
+ toSimpleXml(children.nextNode(), sb);
+ }
+ sb.append("</");
+ sb.append(nodeName);
+ sb.append('>');
+ } else {
+ sb.append("/>");
+ }
+ }
+
}