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  package org.apache.jetspeed.om.folder.impl;
18  
19  import java.security.AccessController;
20  import java.util.Collection;
21  import java.util.Comparator;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.apache.jetspeed.Jetspeed;
26  import org.apache.jetspeed.JetspeedActions;
27  import org.apache.jetspeed.om.folder.Folder;
28  import org.apache.jetspeed.om.folder.FolderNotFoundException;
29  import org.apache.jetspeed.om.folder.MenuDefinition;
30  import org.apache.jetspeed.om.folder.MenuExcludeDefinition;
31  import org.apache.jetspeed.om.folder.MenuIncludeDefinition;
32  import org.apache.jetspeed.om.folder.MenuOptionsDefinition;
33  import org.apache.jetspeed.om.folder.MenuSeparatorDefinition;
34  import org.apache.jetspeed.om.page.Fragment;
35  import org.apache.jetspeed.om.page.Link;
36  import org.apache.jetspeed.om.page.Page;
37  import org.apache.jetspeed.om.page.PageMetadataImpl;
38  import org.apache.jetspeed.om.page.PageSecurity;
39  import org.apache.jetspeed.om.page.impl.LinkImpl;
40  import org.apache.jetspeed.om.page.impl.PageImpl;
41  import org.apache.jetspeed.om.page.impl.PageSecurityImpl;
42  import org.apache.jetspeed.page.PageManager;
43  import org.apache.jetspeed.page.PageNotFoundException;
44  import org.apache.jetspeed.page.document.DocumentException;
45  import org.apache.jetspeed.page.document.DocumentNotFoundException;
46  import org.apache.jetspeed.page.document.Node;
47  import org.apache.jetspeed.page.document.NodeException;
48  import org.apache.jetspeed.page.document.NodeNotFoundException;
49  import org.apache.jetspeed.page.document.NodeSet;
50  import org.apache.jetspeed.page.document.impl.NodeImpl;
51  import org.apache.jetspeed.page.document.impl.NodeSetImpl;
52  import org.apache.jetspeed.page.impl.DatabasePageManagerUtils;
53  import org.apache.jetspeed.security.FolderPermission;
54  import org.apache.ojb.broker.core.proxy.ProxyHelper;
55  
56  /***
57   * FolderImpl
58   *
59   * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
60   * @version $Id$
61   */
62  public class FolderImpl extends NodeImpl implements Folder
63  {
64      private String defaultPage;
65      private String skin;
66      private String defaultLayoutDecorator;
67      private String defaultPortletDecorator;
68      private List orders;
69      private List menus;
70  
71      private PageManager pageManager;
72      private List folders;
73      private boolean foldersCached;
74      private List pages;
75      private boolean pagesCached;
76      private List links;
77      private boolean linksCached;
78      private PageSecurityImpl pageSecurity;
79      private boolean pageSecurityCached;
80      private List all;
81      private boolean allCached;
82      private FolderOrderList documentOrder;
83      private boolean documentOrderComparatorValid;
84      private Comparator documentOrderComparator;
85      private NodeSet foldersNodeSet;
86      private NodeSet pagesNodeSet;
87      private NodeSet linksNodeSet;
88      private NodeSet allNodeSet;
89      private FolderMenuDefinitionList menuDefinitions;
90  
91      public FolderImpl()
92      {
93          super(new FolderSecurityConstraintsImpl());
94      }
95  
96      /***
97       * accessFolderOrders
98       *
99       * Access mutable persistent collection member for List wrappers.
100      *
101      * @return persistent collection
102      */
103     List accessFolderOrders()
104     {
105         // create initial collection if necessary
106         if (orders == null)
107         {
108             orders = DatabasePageManagerUtils.createList();
109         }
110         return orders;
111     }
112 
113     /***
114      * accessMenus
115      *
116      * Access mutable persistent collection member for List wrappers.
117      *
118      * @return persistent collection
119      */
120     List accessMenus()
121     {
122         // create initial collection if necessary
123         if (menus == null)
124         {
125             menus = DatabasePageManagerUtils.createList();
126         }
127         return menus;
128     }
129 
130     /***
131      * setPageManager
132      *
133      * Infuses PageManager for use by this folder instance.
134      *
135      * @param pageManager page manager that manages this folder instance
136      */
137     public void setPageManager(PageManager pageManager)
138     {
139         this.pageManager = pageManager;
140     }
141 
142     /***
143      * accessFolders
144      *
145      * Access folders transient cache collection for use by PageManager.
146      *
147      * @return folders collection
148      */
149     public List accessFolders()
150     {
151         // create initial collection if necessary
152         if (folders == null)
153         {
154             folders = DatabasePageManagerUtils.createList();
155         }
156         return folders;
157     }
158 
159     /***
160      * resetFolders
161      *
162      * Reset folders transient caches for use by PageManager.
163      *
164      * @param cached set cached state for folders
165      */
166     public void resetFolders(boolean cached)
167     {
168         // save cached state
169         foldersCached = cached;
170         allCached = false;
171 
172         // update node caches
173         if (!cached)
174         {
175             accessFolders().clear();
176         }
177         accessAll().clear();
178 
179         // reset cached node sets
180         foldersNodeSet = null;
181         allNodeSet = null;
182     }
183 
184     /***
185      * accessPages
186      *
187      * Access pages transient cache collection for use by PageManager.
188      *
189      * @return pages collection
190      */
191     public List accessPages()
192     {
193         // create initial collection if necessary
194         if (pages == null)
195         {
196             pages = DatabasePageManagerUtils.createList();
197         }
198         return pages;
199     }
200 
201     /***
202      * resetPages
203      *
204      * Reset pages transient caches for use by PageManager.
205      *
206      * @param cached set cached state for pages
207      */
208     public void resetPages(boolean cached)
209     {
210         // save cached state
211         pagesCached = cached;
212         allCached = false;
213 
214         // update node caches
215         if (!cached)
216         {
217             accessPages().clear();
218         }
219         accessAll().clear();
220 
221         // reset cached node sets
222         pagesNodeSet = null;
223         allNodeSet = null;
224     }
225 
226     /***
227      * accessLinks
228      *
229      * Access links transient cache collection for use by PageManager.
230      *
231      * @return links collection
232      */
233     public List accessLinks()
234     {
235         // create initial collection if necessary
236         if (links == null)
237         {
238             links = DatabasePageManagerUtils.createList();
239         }
240         return links;
241     }
242 
243     /***
244      * resetLinks
245      *
246      * Reset links transient caches for use by PageManager.
247      *
248      * @param cached set cached state for links
249      */
250     public void resetLinks(boolean cached)
251     {
252         // save cached state
253         linksCached = cached;
254         allCached = false;
255 
256         // update node caches
257         if (!cached)
258         {
259             accessLinks().clear();
260         }
261         accessAll().clear();
262 
263         // reset cached node sets
264         linksNodeSet = null;
265         allNodeSet = null;
266     }
267 
268     /***
269      * accessPageSecurity
270      *
271      * Access pageSecurity cached instance for use by PageManager.
272      *
273      * @return pageSecurity instance
274      */
275     public PageSecurityImpl accessPageSecurity()
276     {
277         return pageSecurity;
278     }
279 
280     /***
281      * resetPageSecurity
282      *
283      * Reset pageSecurity transient cache instance for use by PageManager.
284      *
285      * @param newPageSecurty cached page security instance.
286      * @param cached set cached state for page security
287      */
288     public void resetPageSecurity(PageSecurityImpl newPageSecurity, boolean cached)
289     {
290         // save cached state
291         pageSecurity = newPageSecurity;
292         pageSecurityCached = cached;
293         allCached = false;
294 
295         // update node caches
296         accessAll().clear();
297 
298         // reset cached node sets
299         allNodeSet = null;
300     }
301 
302     /***
303      * accessAll
304      *
305      * Access all transient cache collection for use by PageManager.
306      *
307      * @return all collection
308      */
309     public List accessAll()
310     {
311         // create initial collection if necessary
312         if (all == null)
313         {
314             all = DatabasePageManagerUtils.createList();
315         }
316         return all;
317     }
318 
319     /***
320      * resetAll
321      *
322      * Reset all transient caches for use by PageManager.
323      *
324      * @param cached set cached state for all
325      */
326     public void resetAll(boolean cached)
327     {
328         // save cached state
329         allCached = cached;
330         foldersCached = cached;
331         pagesCached = cached;
332         linksCached = cached;
333         pageSecurityCached = cached;
334 
335         // update node caches
336         accessFolders().clear();
337         accessPages().clear();
338         accessLinks().clear();
339         pageSecurity = null;
340         if (cached)
341         {
342             // populate node caches
343             synchronized(all)
344             {
345                 Iterator nodeIter = accessAll().iterator();
346                 while (nodeIter.hasNext())
347                 {
348                     Node node = (Node)nodeIter.next();
349                     if (node instanceof PageImpl)
350                     {
351                         pages.add(node);
352                     }
353                     else if (node instanceof FolderImpl)
354                     {
355                         folders.add(node);
356                     }
357                     else if (node instanceof LinkImpl)
358                     {
359                         links.add(node);
360                     }
361                     else if (node instanceof PageSecurityImpl)
362                     {
363                         pageSecurity = (PageSecurityImpl)node;
364                     }
365                 }
366             }
367         }
368         else
369         {
370             accessAll().clear();
371         }
372 
373         // reset cached node sets
374         allNodeSet = null;
375         foldersNodeSet = null;
376         pagesNodeSet = null;
377         linksNodeSet = null;
378     }
379 
380     /***
381      * createDocumentOrderComparator
382      *
383      * @return document order comparator
384      */
385     private Comparator createDocumentOrderComparator()
386     {
387         if (!documentOrderComparatorValid)
388         {
389             documentOrderComparatorValid = true;
390             // return null if no document order exists;
391             // (null implies natural ordering by name)
392             final List documentOrder = getDocumentOrder();
393             if ((documentOrder == null) || documentOrder.isEmpty())
394             {
395                 return null;
396             }
397             // create new document order comparator
398             documentOrderComparator = new Comparator()
399                 {
400                     /* (non-Javadoc)
401                      * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
402                      */
403                     public int compare(Object o1, Object o2)
404                     {
405                         // Compare node names using document order;
406                         // use indicies as names if found in document
407                         // order to force explicitly ordered items
408                         // ahead of unordered items
409                         String name1 = (String)o1;
410                         int index1 = documentOrder.indexOf(name1);
411                         if (index1 >= 0)
412                         {
413                             // use order index as name1
414                             name1 = String.valueOf(index1);
415                         }
416                         String name2 = (String)o2;
417                         int index2 = documentOrder.indexOf(name2);
418                         if (index2 >= 0)
419                         {
420                             // use order index as name2
421                             name2 = String.valueOf(index2);
422                             if (index1 >= 0)
423                             {
424                                 // pad order indicies for numeric string compare
425                                 while (name1.length() != name2.length())
426                                 {
427                                     if (name1.length() < name2.length())
428                                     {
429                                         name1 = "0" + name1;
430                                     }
431                                     else
432                                     {
433                                         name2 = "0" + name2;
434                                     }
435                                 }
436                             }
437                         }
438                         // compare names and/or indicies
439                         return name1.compareTo(name2);                        
440                     }
441                 };
442         }
443         return documentOrderComparator;
444     }
445 
446     /***
447      * clearDocumentOrderComparator
448      */
449     void clearDocumentOrderComparator()
450     {
451         // clear node set ordering
452         documentOrderComparatorValid = false;
453         documentOrderComparator = null;
454         // clear previously cached node sets
455         allNodeSet = null;
456         foldersNodeSet = null;
457         pagesNodeSet = null;
458     }
459 
460     /* (non-Javadoc)
461      * @see org.apache.jetspeed.page.document.impl.NodeImpl#newPageMetadata(java.util.Collection)
462      */
463     public PageMetadataImpl newPageMetadata(Collection fields)
464     {
465         PageMetadataImpl pageMetadata = new PageMetadataImpl(FolderMetadataLocalizedFieldImpl.class);
466         pageMetadata.setFields(fields);
467         return pageMetadata;
468     }
469     
470     /* (non-Javadoc)
471      * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#getEffectivePageSecurity()
472      */
473     public PageSecurity getEffectivePageSecurity()
474     {
475         // return page security instance if available
476         if (!pageSecurityCached)
477         {
478             // use PageManager to get and cache page security
479             // instance for this folder
480             try
481             {
482                 return getPageManager().getPageSecurity(this);
483             }
484             catch (NodeException ne)
485             {
486             }
487             catch (NodeNotFoundException nnfe)
488             {
489             }
490         }
491         else if (pageSecurity != null)
492         {
493             return pageSecurity;
494         }
495 
496         // delegate to real parent folder implementation
497         FolderImpl parentFolderImpl = (FolderImpl)ProxyHelper.getRealObject(getParent());
498         if (parentFolderImpl != null)
499         {
500             return parentFolderImpl.getEffectivePageSecurity();
501         }
502         return null;
503     }
504 
505     /* (non-Javadoc)
506      * @see org.apache.jetspeed.om.page.impl.BaseElementImpl#checkPermissions(java.lang.String, int, boolean, boolean)
507      */
508     public void checkPermissions(String path, int mask, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
509     {
510         // check granted folder permissions unless the check is
511         // to be skipped due to explicity granted access
512         if (!checkParentsOnly)
513         {
514             FolderPermission permission = new FolderPermission(path, mask);
515             AccessController.checkPermission(permission);
516         }
517 
518         // if not checking node only, recursively check
519         // all parent permissions in hierarchy
520         if (!checkNodeOnly)
521         {
522             FolderImpl parentFolderImpl = (FolderImpl)ProxyHelper.getRealObject(getParent());
523             if (parentFolderImpl != null)
524             {
525                 parentFolderImpl.checkPermissions(mask, false, false);
526             }
527         }
528     }
529 
530     /* (non-Javadoc)
531      * @see org.apache.jetspeed.om.page.BaseElement#getTitle()
532      */
533     public String getTitle()
534     {
535         // default title to folder name
536         String title = super.getTitle();
537         if (title == null)
538         {
539             title = defaultTitleFromName();
540             setTitle(title);
541         }
542         return title;
543     }
544 
545     /* (non-Javadoc)
546      * @see org.apache.jetspeed.om.folder.Folder#getSkin()
547      */
548     public String getSkin()
549     {
550         return skin;
551     }
552     
553     /* (non-Javadoc)
554      * @see org.apache.jetspeed.om.folder.Folder#setSkin(java.lang.String)
555      */
556     public void setSkin(String skinName)
557     {
558         this.skin = skinName;
559     }
560 
561     /* (non-Javadoc)
562      * @see org.apache.jetspeed.om.folder.Folder#getEffectiveDefaultDecorator(java.lang.String)
563      */
564     public String getEffectiveDefaultDecorator(String fragmentType)
565     {
566         // get locally defined decorator
567         String decorator = getDefaultDecorator(fragmentType);
568         if (decorator == null)
569         {
570             // delegate to parent folder
571             Folder parentFolder = (Folder)ProxyHelper.getRealObject(getParent());
572             if (parentFolder != null)
573             {
574                 return parentFolder.getEffectiveDefaultDecorator(fragmentType);
575             }
576         }
577         return decorator;
578     }
579 
580     /* (non-Javadoc)
581      * @see org.apache.jetspeed.om.folder.Folder#getDefaultDecorator(java.lang.String)
582      */
583     public String getDefaultDecorator(String fragmentType)
584     {
585         // retrieve supported decorator types
586         if (fragmentType != null)
587         {
588             if (fragmentType.equals(Fragment.LAYOUT))
589             {
590                 return defaultLayoutDecorator; 
591             }
592             if (fragmentType.equals(Fragment.PORTLET))
593             {
594                 return defaultPortletDecorator; 
595             }
596         }
597         return null;
598     }
599     
600     /* (non-Javadoc)
601      * @see org.apache.jetspeed.om.folder.Folder#getDefaultDecorator(java.lang.String,java.lang.String)
602      */
603     public void setDefaultDecorator(String decoratorName, String fragmentType)
604     {
605         // save supported decorator types
606         if (fragmentType != null)
607         {
608             if (fragmentType.equals(Fragment.LAYOUT))
609             {
610                 defaultLayoutDecorator = decoratorName; 
611             }
612             if (fragmentType.equals(Fragment.PORTLET))
613             {
614                 defaultPortletDecorator = decoratorName; 
615             }
616         }
617     }
618 
619     /* (non-Javadoc)
620      * @see org.apache.jetspeed.om.folder.Folder#getDocumentOrder()
621      */
622     public List getDocumentOrder()
623     {
624         // return mutable document order list
625         // by using list wrapper to manage sort
626         // order and element uniqueness
627         if (documentOrder == null)
628         {
629             documentOrder = new FolderOrderList(this);
630         }
631         return documentOrder;
632     }
633     
634     /* (non-Javadoc)
635      * @see org.apache.jetspeed.om.folder.Folder#setDocumentOrder(java.util.List)
636      */
637     public void setDocumentOrder(List docNames)
638     {
639         // set document order using ordered document
640         // names by replacing existing entries with
641         // new elements if new collection is specified
642         List documentOrder = getDocumentOrder();
643         if (docNames != documentOrder)
644         {
645             // replace all document order names
646             documentOrder.clear();
647             if (docNames != null)
648             {
649                 documentOrder.addAll(docNames);
650             }
651         }
652     }
653 
654     /* (non-Javadoc)
655      * @see org.apache.jetspeed.om.folder.Folder#getDefaultPage()
656      */
657     public String getDefaultPage()
658     {
659         return defaultPage;
660     }
661     
662     /* (non-Javadoc)
663      * @see org.apache.jetspeed.om.folder.Folder#setDefaultPage(java.lang.String)
664      */
665     public void setDefaultPage(String defaultPage)
666     {
667         this.defaultPage = defaultPage;
668     }
669 
670     /* (non-Javadoc)
671      * @see org.apache.jetspeed.om.folder.Folder#getFolders()
672      */
673     public NodeSet getFolders() throws DocumentException
674     {
675         // get folders collection
676         if (!foldersCached)
677         {
678             // use PageManager to get and cache folders
679             // collection for this folder
680             return getPageManager().getFolders(this);
681         }
682 
683         // return nodes with view access
684         return filterNodeSetByAccess(getFoldersNodeSet());
685     }
686     
687     /* (non-Javadoc)
688      * @see org.apache.jetspeed.om.folder.Folder#getFolder(java.lang.String)
689      */
690     public Folder getFolder(String name) throws FolderNotFoundException, DocumentException
691     {
692         // get folder instance if folders collection not available
693         if (!foldersCached)
694         {
695             // use PageManager to get folder instance without
696             // caching the folders collection for this folder
697             return getPageManager().getFolder(this, name);
698         }
699 
700         // select folder by name from cached folders collection
701         Folder folder = (Folder)getFoldersNodeSet().get(name);
702         if (folder == null)
703         {
704             throw new FolderNotFoundException("Folder not found: " + name);
705         }
706 
707         // check for view access on folder
708         folder.checkAccess(JetspeedActions.VIEW);
709 
710         return folder;
711     }
712     
713     /* (non-Javadoc)
714      * @see org.apache.jetspeed.om.folder.Folder#getPages()
715      */
716     public NodeSet getPages() throws NodeException
717     {
718         // get pages collection
719         if (!pagesCached)
720         {
721             // use PageManager to get and cache pages
722             // collection for this folder
723             return getPageManager().getPages(this);
724         }
725 
726         // return nodes with view access
727         return filterNodeSetByAccess(getPagesNodeSet());
728     }
729     
730     /* (non-Javadoc)
731      * @see org.apache.jetspeed.om.folder.Folder#getPage(java.lang.String)
732      */
733     public Page getPage(String name) throws PageNotFoundException, NodeException
734     {
735         // get page instance if pages collection not available
736         if (!pagesCached)
737         {
738             // use PageManager to get page instance without
739             // caching the pages collection for this folder
740             return getPageManager().getPage(this, name);
741         }
742 
743         // select page by name from cached pages collection
744         Page page = (Page)getPagesNodeSet().get(name);
745         if (page == null)
746         {
747             throw new PageNotFoundException("Page not found: " + name);
748         }
749 
750         // check for view access on page
751         page.checkAccess(JetspeedActions.VIEW);
752 
753         return page;
754     }
755     
756     /* (non-Javadoc)
757      * @see org.apache.jetspeed.om.folder.Folder#getLinks()
758      */
759     public NodeSet getLinks() throws NodeException
760     {
761         // get links collection
762         if (!linksCached)
763         {
764             // use PageManager to get and cache links
765             // collection for this folder
766             return getPageManager().getLinks(this);
767         }
768 
769         // return nodes with view access
770         return filterNodeSetByAccess(getLinksNodeSet());
771     }
772     
773     /* (non-Javadoc)
774      * @see org.apache.jetspeed.om.folder.Folder#getLink(java.lang.String)
775      */
776     public Link getLink(String name) throws DocumentNotFoundException, NodeException
777     {
778         // get link instance if links collection not available
779         if (!linksCached)
780         {
781             // use PageManager to get link instance without
782             // caching the links collection for this folder
783             return getPageManager().getLink(this, name);
784         }
785 
786         // select link by name from cached links collection
787         Link link = (Link)getLinksNodeSet().get(name);
788         if (link == null)
789         {
790             throw new DocumentNotFoundException("Link not found: " + name);
791         }
792 
793         // check for view access on link
794         link.checkAccess(JetspeedActions.VIEW);
795 
796         return link;
797     }
798     
799     /* (non-Javadoc)
800      * @see org.apache.jetspeed.om.folder.Folder#getPageSecurity()
801      */
802     public PageSecurity getPageSecurity() throws DocumentNotFoundException, NodeException
803     {
804         // get page security instance
805         if (!pageSecurityCached)
806         {
807             // use PageManager to get and cache page security
808             // instance for this folder
809             return getPageManager().getPageSecurity(this);
810         }
811         if (pageSecurity == null)
812         {
813             throw new DocumentNotFoundException("Page security document not found");
814         }
815 
816         // check for view access on document
817         pageSecurity.checkAccess(JetspeedActions.VIEW);
818 
819         return pageSecurity;
820     }
821     
822     /* (non-Javadoc)
823      * @see org.apache.jetspeed.om.folder.Folder#getAll()
824      */
825     public NodeSet getAll() throws DocumentException
826     {
827         // get all nodes collection
828         if (!allCached)
829         {
830             // use PageManager to get and cache all nodes
831             // collection for this folder
832             return getPageManager().getAll(this);
833         }
834 
835         // return nodes with view access
836         return filterNodeSetByAccess(getAllNodeSet());
837     }
838     
839     /* (non-Javadoc)
840      * @see org.apache.jetspeed.om.folder.Folder#getMenuDefinitions()
841      */
842     public List getMenuDefinitions()
843     {
844         // return mutable menu definition list
845         // by using list wrapper to manage
846         // element uniqueness
847         if (menuDefinitions == null)
848         {
849             menuDefinitions = new FolderMenuDefinitionList(this);
850         }
851         return menuDefinitions;
852     }
853     
854     /* (non-Javadoc)
855      * @see org.apache.jetspeed.om.folder.Folder#newMenuDefinition()
856      */
857     public MenuDefinition newMenuDefinition()
858     {
859         return new FolderMenuDefinitionImpl();
860     }
861 
862     /* (non-Javadoc)
863      * @see org.apache.jetspeed.om.folder.Folder#newMenuExcludeDefinition()
864      */
865     public MenuExcludeDefinition newMenuExcludeDefinition()
866     {
867         return new FolderMenuExcludeDefinitionImpl();
868     }
869 
870     /* (non-Javadoc)
871      * @see org.apache.jetspeed.om.folder.Folder#newMenuIncludeDefinition()
872      */
873     public MenuIncludeDefinition newMenuIncludeDefinition()
874     {
875         return new FolderMenuIncludeDefinitionImpl();
876     }
877 
878     /* (non-Javadoc)
879      * @see org.apache.jetspeed.om.folder.Folder#newMenuOptionsDefinition()
880      */
881     public MenuOptionsDefinition newMenuOptionsDefinition()
882     {
883         return new FolderMenuOptionsDefinitionImpl();
884     }
885 
886     /* (non-Javadoc)
887      * @see org.apache.jetspeed.om.folder.Folder#newMenuSeparatorDefinition()
888      */
889     public MenuSeparatorDefinition newMenuSeparatorDefinition()
890     {
891         return new FolderMenuSeparatorDefinitionImpl();
892     }
893 
894     /* (non-Javadoc)
895      * @see org.apache.jetspeed.om.folder.Folder#setMenuDefinitions(java.util.List)
896      */
897     public void setMenuDefinitions(List definitions)
898     {
899         // set menu definitions by replacing
900         // existing entries with new elements if
901         // new collection is specified
902         List menuDefinitions = getMenuDefinitions();
903         if (definitions != menuDefinitions)
904         {
905             // replace all menu definitions
906             menuDefinitions.clear();
907             if (definitions != null)
908             {
909                 menuDefinitions.addAll(definitions);
910             }
911         }
912     }
913 
914     /* (non-Javadoc)
915      * @see org.apache.jetspeed.om.folder.Folder#isReserved()
916      */
917     public boolean isReserved()
918     {
919         // folders are always concrete in this implementation
920         return false;
921     }
922     
923     /* (non-Javadoc)
924      * @see org.apache.jetspeed.om.folder.Folder#getReservedType()
925      */
926     public int getReservedType()
927     {
928         // folders are always concrete in this implementation
929         return RESERVED_FOLDER_NONE;
930     }
931 
932     /* (non-Javadoc)
933      * @see org.apache.jetspeed.page.document.Node#getType()
934      */
935     public String getType()
936     {
937         return FOLDER_TYPE;
938     }
939 
940     /***
941      * getFoldersNodeSet
942      *
943      * Latently create and access folders node set.
944      *
945      * @return folders node set
946      */
947     private NodeSet getFoldersNodeSet()
948     {
949         if (foldersNodeSet == null)
950         {
951             if ((folders != null) && !folders.isEmpty())
952             {
953                 foldersNodeSet = new NodeSetImpl(folders, createDocumentOrderComparator());
954             }
955             else
956             {
957                 foldersNodeSet = NodeSetImpl.EMPTY_NODE_SET;
958             }
959         }
960         return foldersNodeSet;
961     }
962     
963     /***
964      * getPagesNodeSet
965      *
966      * Latently create and access pages node set.
967      *
968      * @return folders node set
969      */
970     private NodeSet getPagesNodeSet() throws NodeException
971     {
972         if (pagesNodeSet == null)
973         {
974             if ((pages != null) && !pages.isEmpty())
975             {
976                 pagesNodeSet = new NodeSetImpl(pages, createDocumentOrderComparator());
977             }
978             else
979             {
980                 pagesNodeSet = NodeSetImpl.EMPTY_NODE_SET;
981             }
982         }
983         return pagesNodeSet;
984     }
985     
986     /***
987      * getLinksNodeSet
988      *
989      * Latently create and access links node set.
990      *
991      * @return folders node set
992      */
993     private NodeSet getLinksNodeSet() throws NodeException
994     {
995         if (linksNodeSet == null)
996         {
997             if ((links != null) && !links.isEmpty())
998             {
999                 linksNodeSet = new NodeSetImpl(links, createDocumentOrderComparator());
1000             }
1001             else
1002             {
1003                 linksNodeSet = NodeSetImpl.EMPTY_NODE_SET;
1004             }
1005         }
1006         return linksNodeSet;
1007     }
1008     
1009     /***
1010      * getAllNodeSet
1011      *
1012      * Latently create and access all nodes node set.
1013      *
1014      * @return all nodes node set
1015      */
1016     private NodeSet getAllNodeSet()
1017     {
1018         if (allNodeSet == null)
1019         {
1020             if ((all != null) && !all.isEmpty())
1021             {
1022                 List allCopy = new java.util.ArrayList();
1023                 synchronized(all)
1024                 {
1025                     allCopy.addAll(all); 
1026                 }
1027                 allNodeSet = new NodeSetImpl(allCopy, createDocumentOrderComparator());
1028             }
1029             else
1030             {
1031                 allNodeSet = NodeSetImpl.EMPTY_NODE_SET;
1032             }
1033         }
1034         return allNodeSet;
1035     }
1036 
1037     /***
1038      * filterNodeSetByAccess
1039      *
1040      * Filter node set elements for view access.
1041      *
1042      * @param nodes node set containing nodes to check
1043      * @return checked subset of nodes
1044      */
1045     static NodeSet filterNodeSetByAccess(NodeSet nodes)
1046     {
1047         if ((nodes != null) && !nodes.isEmpty())
1048         {
1049             // check permissions and constraints, filter nodes as required
1050             NodeSetImpl filteredNodes = null;
1051             Iterator checkAccessIter = nodes.iterator();
1052             while (checkAccessIter.hasNext())
1053             {
1054                 Node node = (Node)checkAccessIter.next();
1055                 try
1056                 {
1057                     // check access
1058                     node.checkAccess(JetspeedActions.VIEW);
1059 
1060                     // add to filteredNodes nodes if copying
1061                     if (filteredNodes != null)
1062                     {
1063                         // permitted, add to filteredNodes nodes
1064                         filteredNodes.add(node);
1065                     }
1066                 }
1067                 catch (SecurityException se)
1068                 {
1069                     // create filteredNodes nodes if not already copying
1070                     if (filteredNodes == null)
1071                     {
1072                         // not permitted, copy previously permitted nodes
1073                         // to new filteredNodes node set with same comparator
1074                         filteredNodes = new NodeSetImpl(nodes);
1075                         Iterator copyIter = nodes.iterator();
1076                         while (copyIter.hasNext())
1077                         {
1078                             Node copyNode = (Node)copyIter.next();
1079                             if (copyNode != node)
1080                             {
1081                                 filteredNodes.add(copyNode);
1082                             }
1083                             else
1084                             {
1085                                 break;
1086                             }
1087                         }
1088                     }
1089                 }
1090             }
1091 
1092             // return filteredNodes nodes if generated
1093             if (filteredNodes != null)
1094             {
1095                 return filteredNodes;
1096             }
1097         }
1098         return nodes;
1099     }
1100     
1101     public PageManager getPageManager()
1102     {
1103         if(pageManager == null)
1104         {
1105             pageManager = (PageManager)Jetspeed.getComponentManager().getComponent("PageManager");
1106         }        
1107         return pageManager;
1108     }     
1109 }