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