KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > lenya > cms > publication > DefaultSiteTree


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17
18 /* @version $Id: DefaultSiteTree.java 160864 2005-04-11 11:46:24Z michi $ */
19
20 package org.apache.lenya.cms.publication;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Date JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import javax.xml.parsers.ParserConfigurationException JavaDoc;
30 import javax.xml.transform.TransformerException JavaDoc;
31
32 import org.apache.lenya.xml.DocumentHelper;
33 import org.apache.lenya.xml.NamespaceHelper;
34 import org.apache.log4j.Logger;
35 import org.apache.xpath.XPathAPI;
36 import org.w3c.dom.Document JavaDoc;
37 import org.w3c.dom.Element JavaDoc;
38 import org.w3c.dom.NamedNodeMap JavaDoc;
39 import org.w3c.dom.Node JavaDoc;
40 import org.w3c.dom.NodeList JavaDoc;
41 import org.xml.sax.SAXException JavaDoc;
42
43 /**
44  * Default Sitetree implementation
45  */

46 public class DefaultSiteTree implements SiteTree, LastModified {
47     private static Logger log = Logger.getLogger(DefaultSiteTree.class);
48     
49     private static Object JavaDoc lock = new Object JavaDoc();
50
51     public static final String JavaDoc SITE_TREE_FILENAME = "sitetree.xml";
52
53     private Document document = null;
54     private File JavaDoc treefile = null;
55     // the area is only retained to provide some more info when raising an exception.
56
private String JavaDoc area = "";
57     
58     private long lastModified = 0;
59
60     /**
61      * Create a DefaultSiteTree
62      *
63      * @param pubDir the publication directory
64      * @param area the area
65      *
66      * @throws SiteTreeException if an error occurs
67      */

68     protected DefaultSiteTree(File JavaDoc pubDir, String JavaDoc area) throws SiteTreeException {
69         this(
70             new File JavaDoc(
71                 pubDir,
72                 Publication.CONTENT_PATH
73                     + File.separator
74                     + area
75                     + File.separator
76                     + SITE_TREE_FILENAME));
77         this.area = area;
78     }
79
80     /**
81      * Create a DefaultSiteTree from a filename.
82      *
83      * @param treefilename file name of the tree
84      *
85      * @throws SiteTreeException if an error occurs
86      *
87      * @deprecated use the DefaultSiteTree(File pubDir, String area) constructor instead.
88      */

89     public DefaultSiteTree(String JavaDoc treefilename) throws SiteTreeException {
90         this(new File JavaDoc(treefilename));
91     }
92
93     /**
94      * Create a DefaultSiteTree from a file.
95      *
96      * @param treefile the file containing the tree
97      *
98      * @throws SiteTreeException if an error occurs
99      *
100      * @deprecated this constructor will be private in the future
101      */

102     public DefaultSiteTree(File JavaDoc treefile) throws SiteTreeException {
103         this.treefile = treefile;
104
105         try {
106             if (!treefile.isFile()) {
107                 //the treefile doesn't exist, so create it
108

109                 document = createDocument();
110             } else {
111                 // Read tree
112
document = DocumentHelper.readDocument(treefile);
113             }
114         } catch (ParserConfigurationException JavaDoc e) {
115             throw new SiteTreeException(e);
116         } catch (SAXException JavaDoc e) {
117             throw new SiteTreeException(e);
118         } catch (IOException JavaDoc e) {
119             throw new SiteTreeException(e);
120         }
121
122     }
123
124     /**
125      * Checks if the tree file has been modified externally and reloads the site tree.
126      * @throws SiteTreeException when something went wrong.
127      */

128     protected synchronized void checkModified() {
129         if (area.equals(Publication.LIVE_AREA)
130             && treefile.isFile()
131             && treefile.lastModified() > lastModified) {
132                 
133             if (log.isDebugEnabled()) {
134                 log.debug("Sitetree [" + treefile + "] has changed: reloading.");
135             }
136                 
137             try {
138                 document = DocumentHelper.readDocument(treefile);
139             } catch (Exception JavaDoc e) {
140                 throw new IllegalStateException JavaDoc(e.getMessage());
141             }
142             lastModified = treefile.lastModified();
143         }
144     }
145
146     /**
147      * Create a new DefaultSiteTree xml document.
148      *
149      * @return the new site document
150      *
151      * @throws ParserConfigurationException if an error occurs
152      */

153     public synchronized Document createDocument() throws ParserConfigurationException JavaDoc {
154         document = DocumentHelper.createDocument(NAMESPACE_URI, "site", null);
155
156         Element JavaDoc root = document.getDocumentElement();
157         root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
158         root.setAttribute(
159             "xsi:schemaLocation",
160             "http://apache.org/cocoon/lenya/sitetree/1.0 ../../../../resources/entities/sitetree.xsd");
161
162         return document;
163     }
164
165     /**
166      * Find a node in a subtree. The search is started at the
167      * given node. The list of ids contains the document-id
168      * split by "/".
169      *
170      * @param node where to start the search
171      * @param ids list of node ids
172      *
173      * @return the node that matches the path given in the list of ids
174      */

175     protected synchronized Node JavaDoc findNode(Node JavaDoc node, List JavaDoc ids) {
176
177         checkModified();
178
179         if (ids.size() < 1) {
180             return node;
181         } else {
182             NodeList JavaDoc nodes = node.getChildNodes();
183
184             for (int i = 0; i < nodes.getLength(); i++) {
185                 NamedNodeMap JavaDoc attributes = nodes.item(i).getAttributes();
186
187                 if (attributes != null) {
188                     Node JavaDoc idAttribute = attributes.getNamedItem("id");
189
190                     if (idAttribute != null
191                         && !"".equals(idAttribute.getNodeValue())
192                         && idAttribute.getNodeValue().equals(ids.get(0))) {
193                         return findNode(nodes.item(i), ids.subList(1, ids.size()));
194                     }
195                 }
196             }
197         }
198
199         // node wasn't found
200
return null;
201     }
202
203     /** (non-Javadoc)
204      * @see org.apache.lenya.cms.publication.SiteTree#addNode(org.apache.lenya.cms.publication.SiteTreeNode, java.lang.String)
205      */

206     public synchronized void addNode(SiteTreeNode node, String JavaDoc refDocumentId) throws SiteTreeException {
207         this.addNode(
208             node.getAbsoluteParentId(),
209             node.getId(),
210             node.getLabels(),
211             node.visibleInNav(),
212             node.getHref(),
213             node.getSuffix(),
214             node.hasLink(),
215             refDocumentId);
216     }
217
218     /** (non-Javadoc)
219      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, java.lang.String, org.apache.lenya.cms.publication.Label[])
220      */

221     public synchronized void addNode(String JavaDoc parentid, String JavaDoc id, Label[] labels, boolean visibleInNav ) throws SiteTreeException {
222         addNode(parentid, id, labels, visibleInNav, null, null, false);
223     }
224
225     /** (non-Javadoc)
226      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, java.lang.String, org.apache.lenya.cms.publication.Label[], boolean)
227      */

228     public synchronized void addNode(String JavaDoc parentid, String JavaDoc id, Label[] labels) throws SiteTreeException {
229         addNode(parentid, id, labels, true);
230     }
231
232     /** (non-Javadoc)
233      * @see org.apache.lenya.cms.publication.SiteTree#addNode(org.apache.lenya.cms.publication.SiteTreeNode)
234      */

235     public synchronized void addNode(SiteTreeNode node) throws SiteTreeException {
236         this.addNode(node, null);
237     }
238
239     /** (non-Javadoc)
240      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, org.apache.lenya.cms.publication.Label[], java.lang.String, java.lang.String, boolean, java.lang.String)
241      */

242     public synchronized void addNode(
243         String JavaDoc documentid,
244         Label[] labels,
245         boolean visibleInNav,
246         String JavaDoc href,
247         String JavaDoc suffix,
248         boolean link,
249         String JavaDoc refDocumentId)
250         throws SiteTreeException {
251         String JavaDoc parentid = "";
252         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(documentid, "/");
253         int length = st.countTokens();
254
255         for (int i = 0; i < (length - 1); i++) {
256             parentid = parentid + "/" + st.nextToken();
257         }
258
259         String JavaDoc id = st.nextToken();
260         this.addNode(parentid, id, labels, visibleInNav, href, suffix, link, refDocumentId);
261     }
262
263     /** (non-Javadoc)
264      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, org.apache.lenya.cms.publication.Label[], java.lang.String, java.lang.String, boolean)
265      */

266     public synchronized void addNode(
267         String JavaDoc documentid,
268         Label[] labels,
269         boolean visibleInNav,
270         String JavaDoc href,
271         String JavaDoc suffix,
272         boolean link)
273         throws SiteTreeException {
274         this.addNode(documentid, labels, visibleInNav, href, suffix, link, null);
275     }
276     /** (non-Javadoc)
277      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, java.lang.String, org.apache.lenya.cms.publication.Label[], java.lang.String, java.lang.String, boolean)
278      */

279     public synchronized void addNode(
280         String JavaDoc parentid,
281         String JavaDoc id,
282         Label[] labels,
283         boolean visibleInNav,
284         String JavaDoc href,
285         String JavaDoc suffix,
286         boolean link)
287         throws SiteTreeException {
288         this.addNode(parentid, id, labels, visibleInNav, href, suffix, link, null);
289     }
290
291     /** (non-Javadoc)
292      * @see org.apache.lenya.cms.publication.SiteTree#addNode(java.lang.String, java.lang.String, org.apache.lenya.cms.publication.Label[], java.lang.String, java.lang.String, boolean)
293      */

294     public synchronized void addNode(
295         String JavaDoc parentid,
296         String JavaDoc id,
297         Label[] labels,
298         boolean visibleInNav,
299         String JavaDoc href,
300         String JavaDoc suffix,
301         boolean link,
302         String JavaDoc refDocumentId)
303         throws SiteTreeException {
304
305         Node JavaDoc parentNode = getNodeInternal(parentid);
306
307         if (parentNode == null) {
308             throw new SiteTreeException(
309                 "Parentid: " + parentid + " in " + area + " tree not found");
310         }
311
312         log.debug("PARENT ELEMENT: " + parentNode);
313
314         // Check if child already exists
315
Node JavaDoc childNode = getNodeInternal(parentid + "/" + id);
316
317         if (childNode != null) {
318             log.info("This node: " + parentid + "/" + id + " has already been inserted");
319
320             return;
321         }
322
323         // Create node
324
NamespaceHelper helper = new NamespaceHelper(NAMESPACE_URI, "", document);
325         Element JavaDoc child = helper.createElement(SiteTreeNodeImpl.NODE_NAME);
326         child.setAttribute(SiteTreeNodeImpl.ID_ATTRIBUTE_NAME, id);
327         
328         if (visibleInNav) {
329             child.setAttribute(SiteTreeNodeImpl.VISIBLEINNAV_ATTRIBUTE_NAME, "true");
330         } else {
331             child.setAttribute(SiteTreeNodeImpl.VISIBLEINNAV_ATTRIBUTE_NAME, "false");
332         }
333
334         if ((href != null) && (href.length() > 0)) {
335             child.setAttribute(SiteTreeNodeImpl.HREF_ATTRIBUTE_NAME, href);
336         }
337
338         if ((suffix != null) && (suffix.length() > 0)) {
339             child.setAttribute(SiteTreeNodeImpl.SUFFIX_ATTRIBUTE_NAME, suffix);
340         }
341
342         if (link) {
343             child.setAttribute(SiteTreeNodeImpl.LINK_ATTRIBUTE_NAME, "true");
344         }
345
346         for (int i = 0; i < labels.length; i++) {
347             String JavaDoc labelName = labels[i].getLabel();
348             Element JavaDoc label = helper.createElement(SiteTreeNodeImpl.LABEL_NAME, labelName);
349             String JavaDoc labelLanguage = labels[i].getLanguage();
350
351             if ((labelLanguage != null) && (labelLanguage.length() > 0)) {
352                 label.setAttribute(SiteTreeNodeImpl.LANGUAGE_ATTRIBUTE_NAME, labelLanguage);
353             }
354
355             child.appendChild(label);
356         }
357
358         // Add Node
359
if (refDocumentId != null && !refDocumentId.equals("")) {
360             Node JavaDoc nextSibling = getNodeInternal(refDocumentId);
361             if (nextSibling != null) {
362                 parentNode.insertBefore(child, nextSibling);
363             } else {
364                 parentNode.appendChild(child);
365             }
366         } else {
367             parentNode.appendChild(child);
368         }
369         log.debug("Tree has been modified: " + document.getDocumentElement());
370     }
371     /**
372      * (non-Javadoc)
373      * @see org.apache.lenya.cms.publication.SiteTree#addLabel(java.lang.String, org.apache.lenya.cms.publication.Label)
374      */

375     public synchronized void addLabel(String JavaDoc documentId, Label label) {
376         SiteTreeNode node = getNode(documentId);
377         if (node != null) {
378             node.addLabel(label);
379         }
380     }
381
382     /**
383      * (non-Javadoc)
384      * @see org.apache.lenya.cms.publication.SiteTree#removeLabel(java.lang.String, org.apache.lenya.cms.publication.Label)
385      */

386     public synchronized void removeLabel(String JavaDoc documentId, Label label) {
387         SiteTreeNode node = getNode(documentId);
388         if (node != null) {
389             node.removeLabel(label);
390         }
391     }
392
393     /** (non-Javadoc)
394      * @see org.apache.lenya.cms.publication.SiteTree#removeNode(java.lang.String)
395      */

396     public synchronized SiteTreeNode removeNode(String JavaDoc documentId) {
397         assert documentId != null;
398
399         Node JavaDoc node = removeNodeInternal(documentId);
400
401         if (node == null) {
402             return null;
403         }
404
405         return new SiteTreeNodeImpl(node, this);
406     }
407     
408     /* (non-Javadoc)
409      * @see org.apache.lenya.cms.publication.SiteTree#deleteNode(java.lang.String)
410      */

411     public void deleteNode(String JavaDoc documentId) throws SiteTreeException {
412         Node JavaDoc node = this.getNodeInternal(documentId);
413         Node JavaDoc parentNode = node.getParentNode();
414         Node JavaDoc newNode = parentNode.removeChild(node);
415     }
416
417
418     /**
419      * removes the node corresponding to the given document-id
420      * and returns it
421      *
422      * @param documentId the document-id of the Node to be removed
423      *
424      * @return the <code>Node</code> that was removed
425      */

426     private synchronized Node JavaDoc removeNodeInternal(String JavaDoc documentId) {
427         Node JavaDoc node = this.getNodeInternal(documentId);
428         Node JavaDoc parentNode = node.getParentNode();
429         Node JavaDoc newNode = parentNode.removeChild(node);
430
431         return newNode;
432     }
433
434     /**
435      * Find a node for a given document-id
436      *
437      * @param documentId the document-id of the Node that we're trying to get
438      *
439      * @return the Node if there is a Node for the given document-id, null otherwise
440      */

441     private synchronized Node JavaDoc getNodeInternal(String JavaDoc documentId) {
442         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(documentId, "/");
443         ArrayList JavaDoc ids = new ArrayList JavaDoc();
444
445         while (st.hasMoreTokens()) {
446             ids.add(st.nextToken());
447         }
448
449         Node JavaDoc node = findNode(document.getDocumentElement(), ids);
450         return node;
451     }
452
453     /**
454      * @see org.apache.lenya.cms.publication.SiteTree#getNode(java.lang.String)
455      */

456     public synchronized SiteTreeNode getNode(String JavaDoc documentId) {
457         assert documentId != null;
458
459         SiteTreeNode treeNode = null;
460
461         Node JavaDoc node = getNodeInternal(documentId);
462         if (node != null) {
463             treeNode = new SiteTreeNodeImpl(node, this);
464         }
465
466         return treeNode;
467     }
468
469     /**
470      * @see org.apache.lenya.cms.publication.SiteTree#getTopNodes()
471      */

472     public SiteTreeNode[] getTopNodes() {
473         List JavaDoc childElements = new ArrayList JavaDoc();
474
475         NamespaceHelper helper = new NamespaceHelper(NAMESPACE_URI, "", document);
476  
477         Element JavaDoc[] elements = helper.getChildren((Element JavaDoc) document.getDocumentElement(), SiteTreeNodeImpl.NODE_NAME);
478
479         for (int i = 0; i < elements.length; i++) {
480             SiteTreeNode newNode = new SiteTreeNodeImpl(elements[i], this);
481             childElements.add(newNode);
482         }
483
484         return (SiteTreeNode[]) childElements.toArray(new SiteTreeNode[childElements.size()]);
485     }
486     
487     /**
488      * Move up the node amongst its siblings.
489      *
490      * @param documentid The document id for the node.
491      * @throws SiteTreeException if the moving failed.
492      */

493     public synchronized void moveUp(String JavaDoc documentid) throws SiteTreeException {
494         Node JavaDoc node = this.getNodeInternal(documentid);
495         if (node == null) {
496             throw new SiteTreeException("Node to move: " + documentid + " not found");
497         }
498         Node JavaDoc parentNode = node.getParentNode();
499         if (parentNode == null) {
500             throw new SiteTreeException(
501                 "Parentid of node with documentid: " + documentid + " not found");
502         }
503
504         Node JavaDoc previousNode;
505         try {
506             previousNode =
507                 XPathAPI.selectSingleNode(
508                     node,
509                     "(preceding-sibling::*[local-name() = 'node'])[last()]");
510         } catch (TransformerException JavaDoc e) {
511             throw new SiteTreeException(e);
512         }
513
514         if (previousNode == null) {
515             log.warn("Couldn't found a preceding sibling");
516             return;
517         }
518         Node JavaDoc insertNode = parentNode.removeChild(node);
519         parentNode.insertBefore(insertNode, previousNode);
520     }
521
522     /**
523      * Move down the node amongst its siblings.
524      *
525      * @param documentid The document id for the node.
526      * @throws SiteTreeException if the moving failed.
527      */

528     public synchronized void moveDown(String JavaDoc documentid) throws SiteTreeException {
529         Node JavaDoc node = this.getNodeInternal(documentid);
530         if (node == null) {
531             throw new SiteTreeException("Node to move: " + documentid + " not found");
532         }
533         Node JavaDoc parentNode = node.getParentNode();
534         if (parentNode == null) {
535             throw new SiteTreeException(
536                 "Parentid of node with documentid: " + documentid + " not found");
537         }
538         Node JavaDoc nextNode;
539         try {
540             nextNode =
541                 XPathAPI.selectSingleNode(
542                     node,
543                     "following-sibling::*[local-name() = 'node'][position()=2]");
544         } catch (TransformerException JavaDoc e) {
545             throw new SiteTreeException(e);
546         }
547
548         Node JavaDoc insertNode = parentNode.removeChild(node);
549
550         if (nextNode == null) {
551             log.warn("Couldn't found the second following sibling");
552             parentNode.appendChild(insertNode);
553         } else {
554             parentNode.insertBefore(insertNode, nextNode);
555         }
556     }
557
558     /** (non-Javadoc)
559      * @see org.apache.lenya.cms.publication.SiteTree#importSubtree(org.apache.lenya.cms.publication.SiteTreeNode, org.apache.lenya.cms.publication.SiteTreeNode, java.lang.String)
560      */

561     public synchronized void importSubtree(
562         SiteTreeNode newParent,
563         SiteTreeNode subtreeRoot,
564         String JavaDoc newid,
565         String JavaDoc refDocumentId)
566         throws SiteTreeException {
567         assert subtreeRoot != null;
568         assert newParent != null;
569         String JavaDoc parentId = newParent.getAbsoluteId();
570         String JavaDoc id = newid;
571
572         this.addNode(
573             parentId,
574             id,
575             subtreeRoot.getLabels(),
576             subtreeRoot.visibleInNav(),
577             subtreeRoot.getHref(),
578             subtreeRoot.getSuffix(),
579             subtreeRoot.hasLink(),
580             refDocumentId);
581         newParent = this.getNode(parentId + "/" + id);
582         if (newParent == null) {
583             throw new SiteTreeException("The added node was not found.");
584         }
585         SiteTreeNode[] children = subtreeRoot.getChildren();
586         if (children == null) {
587             log.info("The node " + subtreeRoot.toString() + " has no children");
588             return;
589         } else { for (int i = 0; i < children.length; i++) {
590                 importSubtree(newParent, children[i], children[i].getId(), null);
591             }
592         }
593     }
594
595     /** (non-Javadoc)
596      * @see org.apache.lenya.cms.publication.SiteTree#save()
597      */

598     public synchronized void save() throws SiteTreeException {
599         try {
600             DocumentHelper.writeDocument(document, treefile);
601         } catch (TransformerException JavaDoc e) {
602             throw new SiteTreeException(
603                 "The document [" + document.getLocalName() + "] could not be transformed");
604         } catch (IOException JavaDoc e) {
605             throw new SiteTreeException(
606                 "The saving of document [" + document.getLocalName() + "] failed");
607         }
608         lastModified = new Date JavaDoc().getTime();
609     }
610
611     /**
612      * @see org.apache.lenya.cms.publication.SiteTree#setLabel(java.lang.String, org.apache.lenya.cms.publication.Label)
613      */

614     public synchronized void setLabel(String JavaDoc documentId, Label label) {
615         SiteTreeNode node = getNode(documentId);
616         if (node != null) {
617             node.setLabel(label);
618         }
619     }
620
621     /**
622      * @see org.apache.lenya.cms.publication.SiteTree#copy(org.apache.lenya.cms.publication.SiteTreeNode, org.apache.lenya.cms.publication.SiteTreeNode, java.lang.String, java.lang.String)
623      */

624     public void copy(SiteTreeNode src, SiteTreeNode dst, String JavaDoc newId, String JavaDoc followingSibling) throws SiteTreeException {
625         assert dst instanceof SiteTreeNodeImpl;
626         
627         SiteTreeNodeImpl dstNode = (SiteTreeNodeImpl)dst;
628         if (this.equals(dstNode.getDefaultSiteTree())) {
629             // Copy if this sitetree is the destination sitetree.
630
// Acquire global sitetree lock to establish lock hierarchy in case of copy operation
631
synchronized(DefaultSiteTree.lock) {
632                 DefaultSiteTree srcSiteTree = ((SiteTreeNodeImpl)src).getDefaultSiteTree();
633                 synchronized(srcSiteTree) {
634                     synchronized(this) {
635                         String JavaDoc parentId = dst.getAbsoluteId();
636                         String JavaDoc id = newId;
637             
638                         this.addNode(
639                             parentId,
640                             id,
641                             src.getLabels(),
642                             src.visibleInNav(),
643                             src.getHref(),
644                             src.getSuffix(),
645                             src.hasLink(),
646                             followingSibling);
647                         SiteTreeNode node = this.getNode(parentId + "/" + id);
648                         if (node == null) {
649                             throw new SiteTreeException("The added node was not found.");
650                         }
651                         SiteTreeNode[] children = src.getChildren();
652                         if (children == null) {
653                             log.debug("The node " + src.toString() + " has no children");
654                             return;
655                         } else {
656                             for (int i = 0; i < children.length; i++) {
657                                 copy(children[i], node, children[i].getId(), null);
658                             }
659                         }
660                     }
661                 }
662             }
663         } else {
664             // Delegate copy operation to destination sitetree.
665
dstNode.getDefaultSiteTree().copy(src, dst, newId, followingSibling);
666         }
667     }
668
669     /**
670      * @see org.apache.lenya.cms.publication.SiteTree#move(org.apache.lenya.cms.publication.SiteTreeNode, org.apache.lenya.cms.publication.SiteTreeNode, java.lang.String, java.lang.String)
671      */

672     public void move(SiteTreeNode src, SiteTreeNode dst, String JavaDoc newId, String JavaDoc followingSibling) throws SiteTreeException {
673         assert dst != null;
674         assert src instanceof SiteTreeNodeImpl;
675         
676         // Acquire global sitetree lock to establish lock hierarchy in case of move operation
677
synchronized(DefaultSiteTree.lock) {
678             // Lock both source and destination sitetree.
679
synchronized(((SiteTreeNodeImpl)src).getDefaultSiteTree()) {
680                 synchronized(((SiteTreeNodeImpl)dst).getDefaultSiteTree()) {
681                     copy(src, dst, newId, followingSibling);
682                     DefaultSiteTree sitetree = ((SiteTreeNodeImpl)src).getDefaultSiteTree();
683                     sitetree.deleteNode(src.getAbsoluteId());
684                 }
685             }
686         }
687     }
688
689     /**
690      * @see org.apache.lenya.cms.publication.LastModified#getLastModified()
691      */

692     public long getLastModified() {
693         return lastModified;
694     }
695 }
696
Popular Tags