1 13 package info.magnolia.cms.core.version; 14 15 import info.magnolia.cms.core.Content; 16 import info.magnolia.cms.core.HierarchyManager; 17 import info.magnolia.cms.core.Path; 18 import info.magnolia.context.MgnlContext; 19 20 import java.io.File ; 21 import java.io.FileInputStream ; 22 import java.io.FileOutputStream ; 23 import java.io.IOException ; 24 import java.util.Iterator ; 25 26 import javax.jcr.ImportUUIDBehavior; 27 import javax.jcr.ItemNotFoundException; 28 import javax.jcr.Node; 29 import javax.jcr.Property; 30 import javax.jcr.PropertyIterator; 31 import javax.jcr.PropertyType; 32 import javax.jcr.RepositoryException; 33 import javax.jcr.nodetype.ConstraintViolationException; 34 35 import org.apache.commons.io.IOUtils; 36 import org.apache.commons.lang.StringUtils; 37 import org.slf4j.Logger; 38 import org.slf4j.LoggerFactory; 39 40 41 46 public final class CopyUtil { 47 48 51 private static Logger log = LoggerFactory.getLogger(CopyUtil.class); 52 53 56 private static final CopyUtil thisInstance = new CopyUtil(); 57 58 61 private CopyUtil() { 62 } 63 64 67 static CopyUtil getInstance() { 68 return thisInstance; 69 } 70 71 76 void copyToversion(Content source, Content.ContentFilter filter) throws RepositoryException { 77 Content root; 79 try { 80 root = this.getHierarchyManager().getContentByUUID(source.getUUID()); 81 if (root.getParent().getName().equalsIgnoreCase(VersionManager.TMP_REFERENCED_NODES)) { 82 root.getJCRNode().getSession().move(root.getHandle(), "/" + root.getName()); 83 } 84 this.removeProperties(root); 85 this.updateProperties(source, root); 87 root.save(); 88 } 89 catch (ItemNotFoundException e) { 90 try { 92 this.importNode(this.getHierarchyManager().getRoot(), source); 93 } 94 catch (IOException ioe) { 95 throw new RepositoryException("Failed to import node in magnolia version store : " + ioe.getMessage()); 96 } 97 root = this.getHierarchyManager().getContentByUUID(source.getUUID()); 98 getHierarchyManager().getRoot().save(); 102 } 103 Iterator children = source.getChildren(filter).iterator(); 105 while (children.hasNext()) { 106 Content child = (Content) children.next(); 107 this.clone(child, root, filter, true); 108 } 109 this.removeNonExistingChildNodes(source, root, filter); 110 } 111 112 118 void copyFromVersion(Content source, Content destination, Content.ContentFilter filter) throws RepositoryException { 119 this.removeProperties(destination); 121 this.updateProperties(source, destination); 122 this.copyAllChildNodes(source, destination, filter); 124 this.removeNonExistingChildNodes(source, destination, filter); 126 } 127 128 134 private void removeNonExistingChildNodes(Content source, Content destination, Content.ContentFilter filter) 135 throws RepositoryException { 136 Iterator children = destination.getChildren(filter).iterator(); 138 while (children.hasNext()) { 139 Content child = (Content) children.next(); 140 if (child.getJCRNode().getDefinition().isAutoCreated()) { 142 continue; 143 } 144 try { 145 source.getJCRNode().getSession().getNodeByUUID(child.getUUID()); 146 this.removeNonExistingChildNodes(source, child, filter); 148 } 149 catch (ItemNotFoundException e) { 150 PropertyIterator referencedProperties = child.getJCRNode().getReferences(); 151 if (referencedProperties.getSize() > 0) { 152 while (referencedProperties.hasNext()) { 155 referencedProperties.nextProperty().remove(); 156 } 157 } 158 child.delete(); 159 } 160 } 161 } 162 163 169 private void copyAllChildNodes(Content node1, Content node2, Content.ContentFilter filter) 170 throws RepositoryException { 171 Iterator children = node1.getChildren(filter).iterator(); 172 while (children.hasNext()) { 173 Content child = (Content) children.next(); 174 this.clone(child, node2, filter, false); 175 } 176 } 177 178 185 private void clone(Content node, Content parent, Content.ContentFilter filter, boolean removeExisting) 186 throws RepositoryException { 187 try { 188 Content existingNode = getHierarchyManager(parent.getWorkspace().getName()) 192 .getContentByUUID(node.getUUID()); 193 if (removeExisting) { 194 existingNode.delete(); 195 parent.save(); 196 this.clone(node, parent); 197 return; 198 } 199 this.removeProperties(existingNode); 200 this.updateProperties(node, existingNode); 201 Iterator children = node.getChildren(filter).iterator(); 202 while (children.hasNext()) { 203 this.clone((Content) children.next(), existingNode, filter, removeExisting); 204 } 205 } 206 catch (ItemNotFoundException e) { 207 this.clone(node, parent); 209 } 210 } 211 212 217 private void clone(Content node, Content parent) throws RepositoryException { 218 if (node.getJCRNode().getDefinition().isAutoCreated()) { 219 Content destination = parent.getContent(node.getName()); 220 this.removeProperties(destination); 221 this.updateProperties(node, destination); 222 } 223 else { 224 parent.getWorkspace().clone( 225 node.getWorkspace().getName(), 226 node.getHandle(), 227 parent.getHandle() + "/" + node.getName(), 228 true); 229 } 230 } 231 232 236 private void removeProperties(Content node) throws RepositoryException { 237 PropertyIterator properties = node.getJCRNode().getProperties(); 238 while (properties.hasNext()) { 239 Property property = properties.nextProperty(); 240 if (property.getDefinition().isProtected() || property.getDefinition().isMandatory()) { 241 continue; 242 } 243 try { 244 property.remove(); 245 } 246 catch (ConstraintViolationException e) { 247 if (log.isDebugEnabled()) { 248 log.debug("Property " + property.getName() + " is a reserved property"); 249 } 250 } 251 } 252 } 253 254 261 private void importNode(Content parent, Content node) throws RepositoryException, IOException { 262 File file = File.createTempFile("mgnl", null, Path.getTempDirectory()); 263 FileOutputStream outStream = new FileOutputStream (file); 264 node.getWorkspace().getSession().exportSystemView(node.getHandle(), outStream, false, true); 265 outStream.flush(); 266 IOUtils.closeQuietly(outStream); 267 FileInputStream inStream = new FileInputStream (file); 268 parent.getWorkspace().getSession().importXML( 269 parent.getHandle(), 270 inStream, 271 ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING); 272 IOUtils.closeQuietly(inStream); 273 file.delete(); 274 } 275 276 281 private void updateProperties(Content source, Content destination) throws RepositoryException { 282 Node sourceNode = source.getJCRNode(); 283 Node destinationNode = destination.getJCRNode(); 284 PropertyIterator properties = sourceNode.getProperties(); 285 while (properties.hasNext()) { 286 Property property = properties.nextProperty(); 287 if (property.getName().equalsIgnoreCase(VersionManager.PROPERTY_RULE)) { 289 continue; 290 } 291 try { 292 if (property.getDefinition().isProtected()) { 293 continue; 294 } 295 if (property.getType() == PropertyType.REFERENCE) { 296 try { 298 getHierarchyManager(destination.getWorkspace().getName()) 299 .getContentByUUID(property.getString()); 300 } 301 catch (ItemNotFoundException e) { 302 if (!StringUtils.equalsIgnoreCase( 303 destination.getWorkspace().getName(), 304 VersionManager.VERSION_WORKSPACE)) { 305 throw e; 306 } 307 Content referencedNode = getHierarchyManager(source.getWorkspace().getName()).getContentByUUID( 310 property.getString()); 311 try { 312 this.importNode(getTemporaryPath(), referencedNode); 313 this.removeProperties(getHierarchyManager().getContentByUUID(property.getString())); 314 getTemporaryPath().save(); 315 } 316 catch (IOException ioe) { 317 log.error("Failed to import referenced node", ioe); 318 } 319 } 320 } 321 if (property.getDefinition().isMultiple()) { 322 destinationNode.setProperty(property.getName(), property.getValues()); 323 } 324 else { 325 destinationNode.setProperty(property.getName(), property.getValue()); 326 } 327 } 328 catch (ConstraintViolationException e) { 329 if (log.isDebugEnabled()) { 330 log.debug("Property " + property.getName() + " is a reserved property"); 331 } 332 } 333 } 334 } 335 336 339 private HierarchyManager getHierarchyManager() { 340 return MgnlContext.getHierarchyManager(VersionManager.VERSION_WORKSPACE); 341 } 342 343 347 private HierarchyManager getHierarchyManager(String workspaceId) { 348 return MgnlContext.getHierarchyManager(workspaceId); 349 } 350 351 354 private Content getTemporaryPath() throws RepositoryException { 355 return getHierarchyManager().getContent("/" + VersionManager.TMP_REFERENCED_NODES); 356 } 357 } 358 | Popular Tags |