View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.jetspeed.page.psml;
19  
20  import java.io.FileNotFoundException;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.Map;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.jetspeed.JetspeedActions;
28  import org.apache.jetspeed.cache.file.FileCache;
29  import org.apache.jetspeed.cache.file.FileCacheEntry;
30  import org.apache.jetspeed.cache.file.FileCacheEventListener;
31  import org.apache.jetspeed.idgenerator.IdGenerator;
32  import org.apache.jetspeed.om.folder.Folder;
33  import org.apache.jetspeed.om.folder.FolderNotFoundException;
34  import org.apache.jetspeed.om.folder.InvalidFolderException;
35  import org.apache.jetspeed.om.folder.psml.FolderImpl;
36  import org.apache.jetspeed.om.folder.psml.MenuDefinitionImpl;
37  import org.apache.jetspeed.om.folder.psml.MenuExcludeDefinitionImpl;
38  import org.apache.jetspeed.om.folder.psml.MenuIncludeDefinitionImpl;
39  import org.apache.jetspeed.om.folder.psml.MenuOptionsDefinitionImpl;
40  import org.apache.jetspeed.om.folder.psml.MenuSeparatorDefinitionImpl;
41  import org.apache.jetspeed.om.page.ContentPage;
42  import org.apache.jetspeed.om.page.ContentPageImpl;
43  import org.apache.jetspeed.om.page.Fragment;
44  import org.apache.jetspeed.om.page.Link;
45  import org.apache.jetspeed.om.page.Page;
46  import org.apache.jetspeed.om.page.PageSecurity;
47  import org.apache.jetspeed.om.page.SecurityConstraintImpl;
48  import org.apache.jetspeed.om.page.SecurityConstraintsDef;
49  import org.apache.jetspeed.om.page.psml.FragmentImpl;
50  import org.apache.jetspeed.om.page.psml.FragmentPreferenceImpl;
51  import org.apache.jetspeed.om.page.psml.LinkImpl;
52  import org.apache.jetspeed.om.page.psml.PageImpl;
53  import org.apache.jetspeed.om.page.psml.PageSecurityImpl;
54  import org.apache.jetspeed.om.page.psml.SecurityConstraintsDefImpl;
55  import org.apache.jetspeed.om.page.psml.SecurityConstraintsImpl;
56  import org.apache.jetspeed.page.AbstractPageManager;
57  import org.apache.jetspeed.page.FolderNotUpdatedException;
58  import org.apache.jetspeed.page.PageManager;
59  import org.apache.jetspeed.page.PageManagerSecurityUtils;
60  import org.apache.jetspeed.page.PageNotFoundException;
61  import org.apache.jetspeed.page.document.DocumentException;
62  import org.apache.jetspeed.page.document.DocumentHandlerFactory;
63  import org.apache.jetspeed.page.document.DocumentNotFoundException;
64  import org.apache.jetspeed.page.document.FailedToDeleteDocumentException;
65  import org.apache.jetspeed.page.document.FailedToUpdateDocumentException;
66  import org.apache.jetspeed.page.document.FolderHandler;
67  import org.apache.jetspeed.page.document.Node;
68  import org.apache.jetspeed.page.document.NodeException;
69  import org.apache.jetspeed.page.document.NodeSet;
70  import org.apache.jetspeed.page.document.UnsupportedDocumentTypeException;
71  import org.apache.jetspeed.page.document.psml.NodeSetImpl;
72  
73  /***
74   * This service is responsible for loading and saving PSML pages serialized to
75   * disk
76   * 
77   * @author <a href="mailto:raphael@apache.org">Rapha?l Luta </a>
78   * @author <a href="mailto:weaver@apache.org">Scott T Weaver </a>
79   * @version $Id: CastorXmlPageManager.java 516448 2007-03-09 16:25:47Z ate $
80   */
81  public class CastorXmlPageManager extends AbstractPageManager implements PageManager, FileCacheEventListener
82  {
83      private final static Log log = LogFactory.getLog(CastorXmlPageManager.class);
84  
85      private static Map modelClasses = new HashMap();
86      static
87      {
88          modelClasses.put("FragmentImpl", FragmentImpl.class);
89          modelClasses.put("PageImpl", PageImpl.class);
90          modelClasses.put("FolderImpl", FolderImpl.class);
91          modelClasses.put("LinkImpl", LinkImpl.class);
92          modelClasses.put("PageSecurityImpl", PageSecurityImpl.class);
93          modelClasses.put("FolderMenuDefinitionImpl", MenuDefinitionImpl.class);
94          modelClasses.put("FolderMenuExcludeDefinitionImpl", MenuExcludeDefinitionImpl.class);
95          modelClasses.put("FolderMenuIncludeDefinitionImpl", MenuIncludeDefinitionImpl.class);
96          modelClasses.put("FolderMenuOptionsDefinitionImpl", MenuOptionsDefinitionImpl.class);
97          modelClasses.put("FolderMenuSeparatorDefinitionImpl", MenuSeparatorDefinitionImpl.class);
98          modelClasses.put("PageMenuDefinitionImpl", MenuDefinitionImpl.class);
99          modelClasses.put("PageMenuExcludeDefinitionImpl", MenuExcludeDefinitionImpl.class);
100         modelClasses.put("PageMenuIncludeDefinitionImpl", MenuIncludeDefinitionImpl.class);
101         modelClasses.put("PageMenuOptionsDefinitionImpl", MenuOptionsDefinitionImpl.class);
102         modelClasses.put("PageMenuSeparatorDefinitionImpl", MenuSeparatorDefinitionImpl.class);
103         modelClasses.put("SecurityConstraintsImpl", SecurityConstraintsImpl.class);
104         modelClasses.put("FolderSecurityConstraintImpl", SecurityConstraintImpl.class);
105         modelClasses.put("PageSecurityConstraintImpl", SecurityConstraintImpl.class);
106         modelClasses.put("FragmentSecurityConstraintImpl", SecurityConstraintImpl.class);
107         modelClasses.put("LinkSecurityConstraintImpl", SecurityConstraintImpl.class);
108         modelClasses.put("PageSecuritySecurityConstraintImpl", SecurityConstraintImpl.class);
109         modelClasses.put("SecurityConstraintsDefImpl", SecurityConstraintsDefImpl.class);
110         modelClasses.put("FragmentPreferenceImpl", FragmentPreferenceImpl.class);
111     }
112 
113     private IdGenerator generator = null;
114     private DocumentHandlerFactory handlerFactory;
115     private FolderHandler folderHandler;
116     private FileCache fileCache;
117 
118     public CastorXmlPageManager( IdGenerator generator, DocumentHandlerFactory handlerFactory,
119                                  FolderHandler folderHandler, FileCache fileCache,
120                                  boolean permissionsEnabled, boolean constraintsEnabled ) throws FileNotFoundException
121     {
122         super(permissionsEnabled, constraintsEnabled, modelClasses);
123         this.generator = generator;
124         handlerFactory.setPermissionsEnabled(permissionsEnabled);
125         handlerFactory.setConstraintsEnabled(constraintsEnabled);
126         this.handlerFactory = handlerFactory;
127         this.folderHandler = folderHandler;
128         this.fileCache = fileCache;
129         this.fileCache.addListener(this);
130     }
131 
132     /***
133      * <p>
134      * newFragment
135      * </p>
136      * 
137      * @see org.apache.jetspeed.page.PageManager#newFragment()
138      * @return fragment
139      */
140     public Fragment newFragment()
141     {
142         // FragmentImpl requires generated ids
143         FragmentImpl fragment = (FragmentImpl)super.newFragment();
144         fragment.setId(generator.getNextPeid());
145         return fragment;
146     }
147 
148     public Fragment newPortletFragment()
149     {
150         // FragmentImpl requires generated ids
151         FragmentImpl fragment = (FragmentImpl)super.newFragment();
152         fragment.setType(Fragment.PORTLET);
153         fragment.setId(generator.getNextPeid());
154         return fragment;
155     }
156         
157     /***
158      * <p>
159      * getPage
160      * </p>
161      * 
162      * @see org.apache.jetspeed.page.PageManager#getPage(java.lang.String)
163      * @param path
164      * @return page
165      * @throws PageNotFoundException
166      * @throws NodeException
167      * @throws FolderNotFoundException
168      */
169     public Page getPage(String path) throws PageNotFoundException, NodeException
170     {
171         // get page via folder, (access checked in Folder.getPage())
172         try
173         {
174             FolderImpl folder = getNodeFolder(path);
175             return folder.getPage(getNodeName(path));
176         }
177         catch (FolderNotFoundException fnfe)
178         {
179             throw new PageNotFoundException(fnfe.getMessage());
180         }
181     }
182 
183     /***
184      * <p>
185      * updatePage
186      * </p>
187      * 
188      * @see org.apache.jetspeed.services.page.PageManagerService#updatePage(org.apache.jetspeed.om.page.Page)
189      */
190     public void updatePage(Page page) throws NodeException
191     {
192         // unwrap page to be registered
193         if (page instanceof ContentPageImpl)
194         {
195             page = ((ContentPageImpl)page).getPage();
196         }
197 
198         // make sure path and related members are set
199         if (page.getPath() != null)
200         {
201             if (!page.getPath().equals(page.getId()))
202             {
203                 log.error("Page paths and ids must match!");
204                 return;
205             }
206         }
207         else
208         {
209             log.error("Page paths and ids must be set!");
210             return;
211         }
212 
213         try
214         {
215             // set parent
216             boolean newPage = false;
217             FolderImpl parentFolder = getNodeFolder(page.getPath());
218             if (page.getParent() == null)
219             {
220                 page.setParent(parentFolder);
221                 newPage = true;
222             }
223 
224             // enable permissions/constraints
225             PageImpl pageImpl = (PageImpl)page;
226             pageImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled());
227             pageImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled());
228             
229             // check for edit access
230             page.checkAccess(JetspeedActions.EDIT);
231             
232             // update page
233             handlerFactory.getDocumentHandler(Page.DOCUMENT_TYPE).updateDocument(page);
234             
235             // update parent folder
236             if (parentFolder != null)
237             {
238                 NodeSetImpl parentAllNodes = (NodeSetImpl)parentFolder.getAllNodes();
239                 if (!parentAllNodes.contains(page))
240                 {
241                     // add new page
242                     parentAllNodes.add(page);
243                     newPage = true;
244                 }
245                 else if (parentAllNodes.get(page.getPath()) != page)
246                 {
247                     // remove stale page and add updated page
248                     parentAllNodes.remove(page);                
249                     parentAllNodes.add(page);
250                 }
251             }
252             
253             // notify page manager listeners
254             if (newPage)
255             {
256                 notifyNewNode(page);
257             }
258             else
259             {
260                 notifyUpdatedNode(page);
261             }
262         }
263         catch (FolderNotFoundException fnfe)
264         {
265             throw new NodeException(fnfe.getMessage());
266         }
267     }
268 
269     /***
270      * <p>
271      * removePage
272      * </p>
273      * 
274      * @see org.apache.jetspeed.services.page.PageManagerService#removePage(org.apache.jetspeed.om.page.Page)
275      */
276     public void removePage(Page page) throws NodeException
277     {
278         // unwrap page to be removed
279         if (page instanceof ContentPageImpl)
280         {
281             page = ((ContentPageImpl)page).getPage();
282         }
283 
284         // check for edit access
285         page.checkAccess(JetspeedActions.EDIT);
286 
287         try
288         {
289             FolderImpl folder = getNodeFolder(page.getPath());
290 
291             // remove page
292             handlerFactory.getDocumentHandler(Page.DOCUMENT_TYPE).removeDocument(page);
293             
294             // update folder
295             ((NodeSetImpl)folder.getAllNodes()).remove(page);
296             
297             // notify page manager listeners
298             notifyRemovedNode(page);
299         }
300         catch (FolderNotFoundException fnfe)
301         {
302             throw new NodeException(fnfe.getMessage());
303         }
304         catch (DocumentNotFoundException dnfe)
305         {
306             throw new NodeException(dnfe.getMessage());
307         }
308     }
309 
310     /***
311      * <p>
312      * getLink
313      * </p>
314      * 
315      * @see org.apache.jetspeed.page.PageManager#getLink(java.lang.String)
316      * @param path
317      * @return link
318      * @throws DocumentNotFoundException
319      * @throws UnsupportedDocumentTypeException
320      * @throws NodeException
321      */
322     public Link getLink(String path) throws DocumentNotFoundException, UnsupportedDocumentTypeException, NodeException
323     {
324         // get link via folder, (access checked in Folder.getLink())
325         try
326         {
327             FolderImpl folder = getNodeFolder(path);
328             return folder.getLink(getNodeName(path));
329         }
330         catch (FolderNotFoundException fnfe)
331         {
332             throw new DocumentNotFoundException(fnfe.getMessage());
333         }
334     }
335 
336     /***
337      * <p>
338      * updateLink
339      * </p>
340      * 
341      * @see org.apache.jetspeed.services.page.PageManagerService#updateLink(org.apache.jetspeed.om.page.Link)
342      */
343     public void updateLink(Link link) throws NodeException
344     {
345         // make sure path and related members are set
346         if (link.getPath() != null)
347         {
348             if (!link.getPath().equals(link.getId()))
349             {
350                 log.error("Link paths and ids must match!");
351                 return;
352             }
353         }
354         else
355         {
356             log.error("Link paths and ids must be set!");
357             return;
358         }
359 
360         try
361         {
362             // set parent
363             boolean newLink = false;
364             FolderImpl parentFolder = getNodeFolder(link.getPath());
365             if (link.getParent() == null)
366             {
367                 link.setParent(parentFolder);
368                 newLink = true;
369             }
370             
371             // enable permissions/constraints
372             LinkImpl linkImpl = (LinkImpl)link;
373             linkImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled());
374             linkImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled());
375             
376             // check for edit access
377             link.checkAccess(JetspeedActions.EDIT);
378             
379             // update link
380             handlerFactory.getDocumentHandler(Link.DOCUMENT_TYPE).updateDocument(link);
381             
382             // update parent folder
383             if (parentFolder != null)
384             {
385                 NodeSetImpl parentAllNodes = (NodeSetImpl)parentFolder.getAllNodes();
386                 if (!parentAllNodes.contains(link))
387                 {
388                     // add new link
389                     parentAllNodes.add(link);
390                     newLink = true;
391                 }
392                 else if (parentAllNodes.get(link.getPath()) != link)
393                 {
394                     // remove stale link and add updated link
395                     parentAllNodes.remove(link);
396                     parentAllNodes.add(link);
397                 }
398             }
399             
400             // notify page manager listeners
401             if (newLink)
402             {
403                 notifyNewNode(link);
404             }
405             else
406             {
407                 notifyUpdatedNode(link);
408             }
409         }
410         catch (FolderNotFoundException fnfe)
411         {
412             throw new NodeException(fnfe.getMessage());
413         }
414     }
415 
416     /***
417      * <p>
418      * removeLink
419      * </p>
420      * 
421      * @see org.apache.jetspeed.services.page.PageManagerService#removeLink(org.apache.jetspeed.om.page.Link)
422      */
423     public void removeLink(Link link) throws NodeException
424     {
425         // check for edit access
426         link.checkAccess(JetspeedActions.EDIT);
427 
428         try
429         {
430             FolderImpl folder = getNodeFolder(link.getPath());
431 
432             // remove link
433             handlerFactory.getDocumentHandler(Link.DOCUMENT_TYPE).removeDocument(link);
434             
435             // update folder
436             ((NodeSetImpl)folder.getAllNodes()).remove(link);
437             
438             // notify page manager listeners
439             notifyRemovedNode(link);
440         }
441         catch (FolderNotFoundException fnfe)
442         {
443             throw new NodeException(fnfe.getMessage());
444         }
445         catch (DocumentNotFoundException dnfe)
446         {
447             throw new NodeException(dnfe.getMessage());
448         }
449     }
450 
451     public boolean checkConstraint(String securityConstraintName, String actions)
452     {
453         try
454         {
455             PageSecurity security = this.getPageSecurity();
456             SecurityConstraintsDef def = security.getSecurityConstraintsDef(securityConstraintName);
457             if (def != null)
458             {
459                 return PageManagerSecurityUtils.checkConstraint(def, actions);
460             }
461         }
462         catch (Exception e)
463         {
464             log.error(e.getMessage(), e);
465         }
466         return false;
467     }
468     
469     /***
470      * <p>
471      * getPageSecurity
472      * </p>
473      * 
474      * @see org.apache.jetspeed.page.PageManager#getPageSecurity()
475      * @return page security instance
476      * @throws DocumentNotFoundException
477      * @throws UnsupportedDocumentTypeException
478      * @throws NodeException
479      */
480     public PageSecurity getPageSecurity() throws DocumentNotFoundException, UnsupportedDocumentTypeException, NodeException
481     {
482         // get page security via folder, (always allow access)
483         try
484         {
485             FolderImpl folder = getNodeFolder(Folder.PATH_SEPARATOR);
486             return folder.getPageSecurity();
487         }
488         catch (FolderNotFoundException fnfe)
489         {
490             throw new DocumentNotFoundException(fnfe.getMessage());
491         }
492     }
493 
494     /* (non-Javadoc)
495      * @see org.apache.jetspeed.page.PageManager#updatePageSecurity(org.apache.jetspeed.om.page.PageSecurity)
496      */
497     public void updatePageSecurity(PageSecurity pageSecurity) throws NodeException, FailedToUpdateDocumentException
498     {
499         // validate path... must exist in root folder and
500         // make sure path and related members are set
501         if (pageSecurity.getPath() != null)
502         {
503             if (!pageSecurity.getPath().equals(Folder.PATH_SEPARATOR + PageSecurity.DOCUMENT_TYPE))
504             {
505                 log.error("PageSecurity path must be: " + Folder.PATH_SEPARATOR + PageSecurity.DOCUMENT_TYPE);
506                 return;
507             }
508             if (!pageSecurity.getPath().equals(pageSecurity.getId()))
509             {
510                 log.error("PageSecurity paths and ids must match!");
511                 return;
512             }
513         }
514         else
515         {
516             log.error("PageSecurity paths and ids must be set!");
517             return;
518         }
519 
520         try
521         {
522             // set parent
523             boolean newPageSecurity = false;
524             FolderImpl parentFolder = getNodeFolder(Folder.PATH_SEPARATOR);
525             if (pageSecurity.getParent() == null)
526             {
527                 pageSecurity.setParent(parentFolder);
528                 newPageSecurity = true;
529             }
530             
531             // enable permissions/constraints
532             PageSecurityImpl pageSecurityImpl = (PageSecurityImpl)pageSecurity;
533             pageSecurityImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled());
534             pageSecurityImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled());
535             
536             // check for edit access
537             pageSecurity.checkAccess(JetspeedActions.EDIT);
538             
539             // update pageSecurity
540             handlerFactory.getDocumentHandler(PageSecurity.DOCUMENT_TYPE).updateDocument(pageSecurity);
541             
542             // update parent folder
543             if (parentFolder != null)
544             {
545                 NodeSetImpl parentAllNodes = (NodeSetImpl)parentFolder.getAllNodes();
546                 if (!parentAllNodes.contains(pageSecurity))
547                 {
548                     // add new page security
549                     parentAllNodes.add(pageSecurity);
550                     newPageSecurity = true;
551                 }
552                 else if (parentAllNodes.get(pageSecurity.getPath()) != pageSecurity)
553                 {
554                     // remove stale page security and add updated page security
555                     parentAllNodes.remove(pageSecurity);
556                     parentAllNodes.add(pageSecurity);
557                 }
558             }
559             
560             // notify page manager listeners
561             if (newPageSecurity)
562             {
563                 notifyNewNode(pageSecurity);
564             }
565             else
566             {
567                 notifyUpdatedNode(pageSecurity);
568             }
569         }
570         catch (FolderNotFoundException fnfe)
571         {
572             throw new NodeException(fnfe.getMessage());
573         }
574     }
575 
576     /* (non-Javadoc)
577      * @see org.apache.jetspeed.page.PageManager#removePageSecurity(org.apache.jetspeed.om.page.PageSecurity)
578      */
579     public void removePageSecurity(PageSecurity pageSecurity) throws NodeException, FailedToDeleteDocumentException
580     {
581         // check for edit access
582         pageSecurity.checkAccess(JetspeedActions.EDIT);
583 
584         try
585         {
586             FolderImpl folder = getNodeFolder(Folder.PATH_SEPARATOR);
587 
588             // remove page security
589             handlerFactory.getDocumentHandler(PageSecurity.DOCUMENT_TYPE).removeDocument(pageSecurity);
590             
591             // update folder
592             ((NodeSetImpl)folder.getAllNodes()).remove(pageSecurity);
593             
594             // notify page manager listeners
595             notifyRemovedNode(pageSecurity);
596         }
597         catch (FolderNotFoundException fnfe)
598         {
599             throw new NodeException(fnfe.getMessage());
600         }
601         catch (DocumentNotFoundException dnfe)
602         {
603             throw new NodeException(dnfe.getMessage());
604         }
605     }
606 
607     /***
608      * <p>
609      * getFolder
610      * </p>
611      * 
612      * @see org.apache.jetspeed.page.PageManager#getFolder(java.lang.String)
613      * @param folderPath
614      * @return folder instance
615      * @throws FolderNotFoundException
616      * @throws NodeException
617      * @throws InvalidFolderException
618      */
619     public Folder getFolder(String folderPath) throws FolderNotFoundException, InvalidFolderException, NodeException
620     {
621         // get folder and check access before returning
622         Folder folder = folderHandler.getFolder(folderPath);
623         folder.checkAccess(JetspeedActions.VIEW);
624         return folder;
625     }
626 
627     /* (non-Javadoc)
628      * @see org.apache.jetspeed.page.PageManager#getFolders(org.apache.jetspeed.om.folder.Folder)
629      */
630     public NodeSet getFolders(Folder folder) throws DocumentException
631     {
632         // delegate back to folder instance
633         return folder.getFolders();
634     }
635 
636     /* (non-Javadoc)
637      * @see org.apache.jetspeed.page.PageManager#getFolder(org.apache.jetspeed.om.folder.Folder,java.lang.String)
638      */
639     public Folder getFolder(Folder folder, String name) throws FolderNotFoundException, DocumentException
640     {
641         // delegate back to folder instance
642         return folder.getFolder(name);
643     }
644 
645     /* (non-Javadoc)
646      * @see org.apache.jetspeed.page.PageManager#getPages(org.apache.jetspeed.om.folder.Folder)
647      */
648     public NodeSet getPages(Folder folder) throws NodeException
649     {
650         // delegate back to folder instance
651         return folder.getPages();
652     }
653     
654     /* (non-Javadoc)
655      * @see org.apache.jetspeed.page.PageManager#getPage(org.apache.jetspeed.om.folder.Folder,java.lang.String)
656      */
657     public Page getPage(Folder folder, String name) throws PageNotFoundException, NodeException
658     {
659         // delegate back to folder instance
660         return folder.getPage(name);
661     }
662     
663     /* (non-Javadoc)
664      * @see org.apache.jetspeed.page.PageManager#getLinks(org.apache.jetspeed.om.folder.Folder)
665      */    
666     public NodeSet getLinks(Folder folder) throws NodeException
667     {
668         // delegate back to folder instance
669         return folder.getLinks();
670     }
671     
672     /* (non-Javadoc)
673      * @see org.apache.jetspeed.page.PageManager#getLink(org.apache.jetspeed.om.folder.Folder,java.lang.String)
674      */    
675     public Link getLink(Folder folder, String name) throws DocumentNotFoundException, NodeException
676     {
677         // delegate back to folder instance
678         return folder.getLink(name);
679     }
680     
681     /* (non-Javadoc)
682      * @see org.apache.jetspeed.page.PageManager#getPageSecurity(org.apache.jetspeed.om.folder.Folder)
683      */    
684     public PageSecurity getPageSecurity(Folder folder) throws DocumentNotFoundException, NodeException
685     {
686         // delegate back to folder instance
687         return folder.getPageSecurity();
688     }
689 
690     /* (non-Javadoc)
691      * @see org.apache.jetspeed.page.PageManager#getAll(org.apache.jetspeed.om.folder.Folder)
692      */
693     public NodeSet getAll(Folder folder) throws DocumentException
694     {
695         // delegate back to folder instance
696         return folder.getAll();
697     }
698 
699     /***
700      * <p>
701      * updateFolder
702      * </p>
703      * 
704      * @see org.apache.jetspeed.services.page.PageManagerService#updateFolder(org.apache.jetspeed.om.folder.Folder)
705      */
706     public void updateFolder(Folder folder) throws NodeException, FolderNotUpdatedException
707     {
708         // shallow update by default
709         updateFolder(folder, false);
710     }
711 
712     /* (non-Javadoc)
713      * @see org.apache.jetspeed.page.PageManager#updateFolder(org.apache.jetspeed.om.folder.Folder,boolean)
714      */
715     public void updateFolder(Folder folder, boolean deep) throws NodeException, FolderNotUpdatedException
716     {
717         // make sure path and related members are set
718         if (folder.getPath() != null)
719         {
720             if (!folder.getPath().equals(folder.getId()))
721             {
722                 log.error("Folder paths and ids must match!");
723                 return;
724             }
725         }
726         else
727         {
728             log.error("Folder paths and ids must be set!");
729             return;
730         }
731 
732         try
733         {
734             // set parent
735             boolean newFolder = false;
736             FolderImpl parentFolder = null;
737             if (!folder.getPath().equals(Folder.PATH_SEPARATOR))
738             {
739                 parentFolder = getNodeFolder(folder.getPath());
740                 if (folder.getParent() == null)
741                 {
742                     folder.setParent(parentFolder);
743                     newFolder = true;
744                 }
745             }
746             else
747             {
748                 folder.setParent(null);            
749             }
750             
751             // enable permissions/constraints and configure
752             // folder handler before access is checked
753             FolderImpl folderImpl = (FolderImpl)folder;
754             folderImpl.setPermissionsEnabled(handlerFactory.getPermissionsEnabled());
755             folderImpl.setConstraintsEnabled(handlerFactory.getConstraintsEnabled());
756             folderImpl.setFolderHandler(folderHandler);
757             
758             // check for edit access
759             folder.checkAccess(JetspeedActions.EDIT);
760             
761             // update folder
762             folderHandler.updateFolder(folder);
763             
764             // update parent folder
765             if (parentFolder != null)
766             {
767                 NodeSetImpl parentAllNodes = (NodeSetImpl)parentFolder.getAllNodes();
768                 if (!parentAllNodes.contains(folder))
769                 {
770                     // add new folder
771                     parentAllNodes.add(folder);
772                     newFolder = true;
773                 }
774                 else if (parentAllNodes.get(folder.getPath()) != folder)
775                 {
776                     // remove stale folder and add updated folder
777                     parentAllNodes.remove(folder);
778                     parentAllNodes.add(folder);
779                 }
780             }
781             
782             // update deep recursively if specified
783             if (deep)
784             {
785                 // update recursively, (breadth first)
786                 updateFolderNodes(folderImpl);
787             }
788             
789             // notify page manager listeners
790             if (newFolder)
791             {
792                 notifyNewNode(folder);
793             }
794             else
795             {
796                 notifyUpdatedNode(folder);
797             }            
798         }
799         catch (FolderNotFoundException fnfe)
800         {
801             throw new NodeException(fnfe.getMessage());
802         }
803     }
804 
805     /***
806      * updateFolderNodes - recusively update all folder nodes
807      *
808      * @param folderImpl folder whose nodes are to be updated
809      * @param throws FolderNotUpdatedException
810      */
811     private void updateFolderNodes(FolderImpl folderImpl) throws FolderNotUpdatedException
812     {
813         try
814         {
815             // update folder documents
816             NodeSet nodes = folderImpl.getAllNodes();
817             Iterator nodesIter = nodes.iterator();
818             while (nodesIter.hasNext())
819             {
820                 Node node = (Node) nodesIter.next();
821                 if (node instanceof Page)
822                 {
823                     updatePage((Page)node);
824                 }
825                 else if (node instanceof Link)
826                 {
827                     updateLink((Link)node);
828                 }
829                 else if (node instanceof PageSecurity)
830                 {
831                     updatePageSecurity((PageSecurity)node);
832                 }
833             }
834 
835             // update folders last: breadth first recursion
836             nodesIter = nodes.iterator();
837             while (nodesIter.hasNext())
838             {
839                 Node node = (Node) nodesIter.next();
840                 if (node instanceof Folder)
841                 {
842                     updateFolder((Folder)node, true);
843                 }
844             }
845         }
846         catch (FolderNotUpdatedException fnue)
847         {
848             throw fnue;
849         }
850         catch (SecurityException se)
851         {
852             throw se;
853         }
854         catch (Exception e)
855         {
856             throw new FolderNotUpdatedException("Folder " + folderImpl.getPath() + " not updated.", e);
857         }
858     }
859 
860     /***
861      * <p>
862      * removeFolder
863      * </p>
864      * 
865      * @see org.apache.jetspeed.services.page.PageManagerService#removeFolder(org.apache.jetspeed.om.folder.Folder)
866      */
867     public void removeFolder(Folder folder) throws NodeException
868     {
869         // check for edit access
870         folder.checkAccess(JetspeedActions.EDIT);
871 
872         try
873         {
874             FolderImpl parentFolder = null;
875             if (!folder.getPath().equals(Folder.PATH_SEPARATOR))
876             {
877                 parentFolder = getNodeFolder(folder.getPath());
878             }
879 
880             // remove folder
881             folderHandler.removeFolder(folder);
882 
883             // update parent folder
884             if (parentFolder != null)
885             {
886                 ((NodeSetImpl)parentFolder.getAllNodes()).remove(folder);
887             }
888 
889             // notify page manager listeners
890             notifyRemovedNode(folder);
891         }
892         catch (FolderNotFoundException fnfe)
893         {
894             throw new NodeException(fnfe.getMessage());
895         }
896     }
897 
898     /* (non-Javadoc)
899      * @see org.apache.jetspeed.page.PageManager#reset()
900      */
901     public void reset()
902     {
903         // propagate to super
904         super.reset();
905 
906         // evict all from file cache to force subsequent
907         // refreshs from persistent store
908         fileCache.evictAll();
909     }
910 
911     /***
912      * <p>
913      * getNodeFolder - get folder implementation associated with specifed path
914      * </p>
915      * 
916      * @param nodePath
917      * @return folder impl instance
918      * @throws NodeException
919      * @throws InvalidFolderException
920      * @throws FolderNotFoundException
921      */
922     private FolderImpl getNodeFolder(String nodePath) throws NodeException, InvalidFolderException, FolderNotFoundException
923     {
924         int folderIndex = nodePath.lastIndexOf(Folder.PATH_SEPARATOR);
925         if (folderIndex > 0)
926         {
927             return (FolderImpl) folderHandler.getFolder(nodePath.substring(0, folderIndex));
928         }
929         return (FolderImpl) folderHandler.getFolder(Folder.PATH_SEPARATOR);
930     }
931 
932     /***
933      * <p>
934      * getNodeFolder - get name of node from specified path
935      * </p>
936      * 
937      * @param nodePath
938      * @return name of node
939      */
940     private String getNodeName(String nodePath)
941     {
942         int folderIndex = nodePath.lastIndexOf(Folder.PATH_SEPARATOR);
943         if (folderIndex > -1)
944         {
945             return nodePath.substring(folderIndex+1);
946         }
947         return nodePath;
948     }
949 
950     /***
951      * <p>
952      * refresh file cache entry
953      * </p>
954      * 
955      * @see org.apache.jetspeed.cache.file.FileCacheEventListener#refresh(org.apache.jetspeed.cache.file.FileCacheEntry)
956      * @param entry
957      * @throws Exception
958      */
959     public void refresh( FileCacheEntry entry ) throws Exception
960     {
961         // file cache managed component refreshed:
962         // notify page manager listeners
963         Node refreshedNode = null;
964         if (entry.getDocument() instanceof Node)
965         {
966             refreshedNode = (Node)entry.getDocument();
967         }
968         if (entry.getFile().exists())
969         {
970             notifyUpdatedNode(refreshedNode);
971         }
972         else
973         {
974             notifyRemovedNode(refreshedNode);
975         }
976     }
977 
978     /***
979      * <p>
980      * evict file cache entry
981      * </p>
982      * 
983      * @see org.apache.jetspeed.cache.file.FileCacheEventListener#evict(org.apache.jetspeed.cache.file.FileCacheEntry)
984      * @param entry
985      * @throws Exception
986      */
987     public void evict( FileCacheEntry entry ) throws Exception
988     {
989         // file cache managed component evicted:
990         // no notifications required since eviction
991         // is normal cache operation and does not
992         // indicate a change in the nodes managed by
993         // this page manager
994     }
995 
996     /* (non-Javadoc)
997      * @see org.apache.jetspeed.page.PageManager#getContentPage(java.lang.String)
998      */
999     public ContentPage getContentPage(String path) throws PageNotFoundException, NodeException
1000     {        
1001         return new ContentPageImpl(getPage(path));
1002     } 
1003 
1004     public Page copy(Page source)
1005     {
1006         return null;
1007     }
1008     
1009     public int addPages(Page[] pages)
1010     throws NodeException
1011     {
1012         this.updatePage(pages[0]);
1013         this.updatePage(pages[1]);
1014         throw new NodeException("Its gonna blow captain!");
1015     }
1016     
1017 }