1 package org.argeo.connect.util;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.jcr.ItemNotFoundException;
7 import javax.jcr.Node;
8 import javax.jcr.NodeIterator;
9 import javax.jcr.Property;
10 import javax.jcr.PropertyIterator;
11 import javax.jcr.PropertyType;
12 import javax.jcr.Repository;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.RepositoryFactory;
15 import javax.jcr.Session;
16 import javax.jcr.SimpleCredentials;
17 import javax.jcr.Value;
18 import javax.jcr.ValueFactory;
19 import javax.jcr.nodetype.NodeType;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.argeo.connect.ConnectException;
24 import org.argeo.jcr.JcrUtils;
25 import org.argeo.node.NodeUtils;
26
27
28 public class RemoteJcrUtils {
29 private final static Log log = LogFactory.getLog(RemoteJcrUtils.class);
30
31
32
33
34
35
36
37
38
39
40
41 public static void copy(Node fromNode, Node toNode, boolean copyChildren) {
42 try {
43 if (toNode.getDefinition().isProtected())
44 return;
45
46
47 for (NodeType mixinType : fromNode.getMixinNodeTypes()) {
48 toNode.addMixin(mixinType.getName());
49 }
50
51
52 PropertyIterator pit = fromNode.getProperties();
53 properties: while (pit.hasNext()) {
54 Property fromProperty = pit.nextProperty();
55 String propertyName = fromProperty.getName();
56 if (toNode.hasProperty(propertyName) && toNode.getProperty(propertyName).getDefinition().isProtected())
57 continue properties;
58
59 if (fromProperty.getDefinition().isProtected())
60 continue properties;
61
62 if (propertyName.equals("jcr:created") || propertyName.equals("jcr:createdBy")
63 || propertyName.equals("jcr:lastModified") || propertyName.equals("jcr:lastModifiedBy"))
64 continue properties;
65
66 if (PropertyType.REFERENCE == fromProperty.getType()
67 || PropertyType.WEAKREFERENCE == fromProperty.getType()) {
68 copyReference(fromProperty, toNode);
69 } else if (fromProperty.isMultiple())
70 toNode.setProperty(propertyName, fromProperty.getValues());
71 else
72 toNode.setProperty(propertyName, fromProperty.getValue());
73 }
74
75
76 if (copyChildren) {
77 NodeIterator nit = fromNode.getNodes();
78 while (nit.hasNext()) {
79 Node fromChild = nit.nextNode();
80 Integer index = fromChild.getIndex();
81 String nodeRelPath = fromChild.getName() + "[" + index + "]";
82 Node toChild;
83 if (toNode.hasNode(nodeRelPath))
84 toChild = toNode.getNode(nodeRelPath);
85 else
86 toChild = toNode.addNode(fromChild.getName(), fromChild.getPrimaryNodeType().getName());
87 copy(fromChild, toChild, true);
88 }
89 }
90 if (toNode.isNodeType(NodeType.MIX_LAST_MODIFIED))
91 JcrUtils.updateLastModified(toNode);
92 if (log.isTraceEnabled())
93 log.trace("Copied " + toNode);
94 } catch (RepositoryException e) {
95 throw new ConnectException("Cannot copy " + fromNode + " to " + toNode, e);
96 }
97 }
98
99 public static void copyReference(Property fromProperty, Node toNode) throws RepositoryException {
100 String propertyName = fromProperty.getName();
101 if (fromProperty.isMultiple()) {
102 Value[] vals = fromProperty.getValues();
103 List<Node> toNodes = new ArrayList<Node>();
104 values: for (Value val : vals) {
105 String fromRefJcrId = val.getString();
106 Node oldReferencedNode = null;
107 try {
108 oldReferencedNode = fromProperty.getSession().getNodeByIdentifier(fromRefJcrId);
109 } catch (ItemNotFoundException e) {
110 log.warn("Cannot resolve reference for multi-valued property " + fromProperty + " with ID "
111 + fromRefJcrId + ". Corresponding value has not been copied.");
112 continue values;
113 }
114 String oldRefPath = oldReferencedNode.getPath();
115 Session toSession = toNode.getSession();
116 if (toSession.nodeExists(oldRefPath))
117 toNodes.add(toSession.getNode(oldRefPath));
118 else
119 log.warn("Node with path: " + oldRefPath + " does not exist in target repository. "
120 + " Reference on this node while copying property " + fromProperty + " has been ignored.");
121 }
122 if (!toNodes.isEmpty())
123 setMultipleReferences(toNode, propertyName, toNodes);
124 } else {
125 String oldRefPath = fromProperty.getNode().getPath();
126 Session toSession = toNode.getSession();
127 if (toSession.nodeExists(oldRefPath)) {
128 Node newRef = toSession.getNode(oldRefPath);
129
130 toNode.setProperty(propertyName, newRef);
131 } else
132 log.warn("Cannot resolve reference for property " + fromProperty.getPath()
133 + ". It has not been copied.");
134 }
135 }
136
137 public static void setMultipleReferences(Node node, String propertyName, List<Node> nodes)
138 throws RepositoryException {
139 ValueFactory vFactory = node.getSession().getValueFactory();
140 int size = nodes.size();
141 Value[] values = new Value[size];
142 int i = 0;
143 for (Node currNode : nodes) {
144 Value val = vFactory.createValue(currNode.getIdentifier(), PropertyType.REFERENCE);
145 values[i++] = val;
146 }
147 node.setProperty(propertyName, values);
148 }
149
150
151
152
153
154 public static Session getSessionOnRemote(RepositoryFactory repositoryFactory, String repoUrl, String wkspName,
155 String login, char[] pwd) throws RepositoryException {
156 Repository remoteRepo = NodeUtils.getRepositoryByUri(repositoryFactory, repoUrl);
157 SimpleCredentials sc = new SimpleCredentials(login, pwd);
158 return remoteRepo.login(sc, wkspName);
159 }
160 }