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.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
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
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
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
169 foldersCached = cached;
170 allCached = false;
171
172
173 if (!cached)
174 {
175 accessFolders().clear();
176 }
177 accessAll().clear();
178
179
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
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
211 pagesCached = cached;
212 allCached = false;
213
214
215 if (!cached)
216 {
217 accessPages().clear();
218 }
219 accessAll().clear();
220
221
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
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
253 linksCached = cached;
254 allCached = false;
255
256
257 if (!cached)
258 {
259 accessLinks().clear();
260 }
261 accessAll().clear();
262
263
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
291 pageSecurity = newPageSecurity;
292 pageSecurityCached = cached;
293 allCached = false;
294
295
296 accessAll().clear();
297
298
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
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
329 allCached = cached;
330 foldersCached = cached;
331 pagesCached = cached;
332 linksCached = cached;
333 pageSecurityCached = cached;
334
335
336 accessFolders().clear();
337 accessPages().clear();
338 accessLinks().clear();
339 pageSecurity = null;
340 if (cached)
341 {
342
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
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
391
392 final List documentOrder = getDocumentOrder();
393 if ((documentOrder == null) || documentOrder.isEmpty())
394 {
395 return null;
396 }
397
398 documentOrderComparator = new Comparator()
399 {
400
401
402
403 public int compare(Object o1, Object o2)
404 {
405
406
407
408
409 String name1 = (String)o1;
410 int index1 = documentOrder.indexOf(name1);
411 if (index1 >= 0)
412 {
413
414 name1 = String.valueOf(index1);
415 }
416 String name2 = (String)o2;
417 int index2 = documentOrder.indexOf(name2);
418 if (index2 >= 0)
419 {
420
421 name2 = String.valueOf(index2);
422 if (index1 >= 0)
423 {
424
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
439 return name1.compareTo(name2);
440 }
441 };
442 }
443 return documentOrderComparator;
444 }
445
446 /***
447 * clearDocumentOrderComparator
448 */
449 void clearDocumentOrderComparator()
450 {
451
452 documentOrderComparatorValid = false;
453 documentOrderComparator = null;
454
455 allNodeSet = null;
456 foldersNodeSet = null;
457 pagesNodeSet = null;
458 }
459
460
461
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
471
472
473 public PageSecurity getEffectivePageSecurity()
474 {
475
476 if (!pageSecurityCached)
477 {
478
479
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
497 FolderImpl parentFolderImpl = (FolderImpl)ProxyHelper.getRealObject(getParent());
498 if (parentFolderImpl != null)
499 {
500 return parentFolderImpl.getEffectivePageSecurity();
501 }
502 return null;
503 }
504
505
506
507
508 public void checkPermissions(String path, int mask, boolean checkNodeOnly, boolean checkParentsOnly) throws SecurityException
509 {
510
511
512 if (!checkParentsOnly)
513 {
514 FolderPermission permission = new FolderPermission(path, mask);
515 AccessController.checkPermission(permission);
516 }
517
518
519
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
531
532
533 public String getTitle()
534 {
535
536 String title = super.getTitle();
537 if (title == null)
538 {
539 title = defaultTitleFromName();
540 setTitle(title);
541 }
542 return title;
543 }
544
545
546
547
548 public String getSkin()
549 {
550 return skin;
551 }
552
553
554
555
556 public void setSkin(String skinName)
557 {
558 this.skin = skinName;
559 }
560
561
562
563
564 public String getEffectiveDefaultDecorator(String fragmentType)
565 {
566
567 String decorator = getDefaultDecorator(fragmentType);
568 if (decorator == null)
569 {
570
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
581
582
583 public String getDefaultDecorator(String fragmentType)
584 {
585
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
601
602
603 public void setDefaultDecorator(String decoratorName, String fragmentType)
604 {
605
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
620
621
622 public List getDocumentOrder()
623 {
624
625
626
627 if (documentOrder == null)
628 {
629 documentOrder = new FolderOrderList(this);
630 }
631 return documentOrder;
632 }
633
634
635
636
637 public void setDocumentOrder(List docNames)
638 {
639
640
641
642 List documentOrder = getDocumentOrder();
643 if (docNames != documentOrder)
644 {
645
646 documentOrder.clear();
647 if (docNames != null)
648 {
649 documentOrder.addAll(docNames);
650 }
651 }
652 }
653
654
655
656
657 public String getDefaultPage()
658 {
659 return defaultPage;
660 }
661
662
663
664
665 public void setDefaultPage(String defaultPage)
666 {
667 this.defaultPage = defaultPage;
668 }
669
670
671
672
673 public NodeSet getFolders() throws DocumentException
674 {
675
676 if (!foldersCached)
677 {
678
679
680 return getPageManager().getFolders(this);
681 }
682
683
684 return filterNodeSetByAccess(getFoldersNodeSet());
685 }
686
687
688
689
690 public Folder getFolder(String name) throws FolderNotFoundException, DocumentException
691 {
692
693 if (!foldersCached)
694 {
695
696
697 return getPageManager().getFolder(this, name);
698 }
699
700
701 Folder folder = (Folder)getFoldersNodeSet().get(name);
702 if (folder == null)
703 {
704 throw new FolderNotFoundException("Folder not found: " + name);
705 }
706
707
708 folder.checkAccess(JetspeedActions.VIEW);
709
710 return folder;
711 }
712
713
714
715
716 public NodeSet getPages() throws NodeException
717 {
718
719 if (!pagesCached)
720 {
721
722
723 return getPageManager().getPages(this);
724 }
725
726
727 return filterNodeSetByAccess(getPagesNodeSet());
728 }
729
730
731
732
733 public Page getPage(String name) throws PageNotFoundException, NodeException
734 {
735
736 if (!pagesCached)
737 {
738
739
740 return getPageManager().getPage(this, name);
741 }
742
743
744 Page page = (Page)getPagesNodeSet().get(name);
745 if (page == null)
746 {
747 throw new PageNotFoundException("Page not found: " + name);
748 }
749
750
751 page.checkAccess(JetspeedActions.VIEW);
752
753 return page;
754 }
755
756
757
758
759 public NodeSet getLinks() throws NodeException
760 {
761
762 if (!linksCached)
763 {
764
765
766 return getPageManager().getLinks(this);
767 }
768
769
770 return filterNodeSetByAccess(getLinksNodeSet());
771 }
772
773
774
775
776 public Link getLink(String name) throws DocumentNotFoundException, NodeException
777 {
778
779 if (!linksCached)
780 {
781
782
783 return getPageManager().getLink(this, name);
784 }
785
786
787 Link link = (Link)getLinksNodeSet().get(name);
788 if (link == null)
789 {
790 throw new DocumentNotFoundException("Link not found: " + name);
791 }
792
793
794 link.checkAccess(JetspeedActions.VIEW);
795
796 return link;
797 }
798
799
800
801
802 public PageSecurity getPageSecurity() throws DocumentNotFoundException, NodeException
803 {
804
805 if (!pageSecurityCached)
806 {
807
808
809 return getPageManager().getPageSecurity(this);
810 }
811 if (pageSecurity == null)
812 {
813 throw new DocumentNotFoundException("Page security document not found");
814 }
815
816
817 pageSecurity.checkAccess(JetspeedActions.VIEW);
818
819 return pageSecurity;
820 }
821
822
823
824
825 public NodeSet getAll() throws DocumentException
826 {
827
828 if (!allCached)
829 {
830
831
832 return getPageManager().getAll(this);
833 }
834
835
836 return filterNodeSetByAccess(getAllNodeSet());
837 }
838
839
840
841
842 public List getMenuDefinitions()
843 {
844
845
846
847 if (menuDefinitions == null)
848 {
849 menuDefinitions = new FolderMenuDefinitionList(this);
850 }
851 return menuDefinitions;
852 }
853
854
855
856
857 public MenuDefinition newMenuDefinition()
858 {
859 return new FolderMenuDefinitionImpl();
860 }
861
862
863
864
865 public MenuExcludeDefinition newMenuExcludeDefinition()
866 {
867 return new FolderMenuExcludeDefinitionImpl();
868 }
869
870
871
872
873 public MenuIncludeDefinition newMenuIncludeDefinition()
874 {
875 return new FolderMenuIncludeDefinitionImpl();
876 }
877
878
879
880
881 public MenuOptionsDefinition newMenuOptionsDefinition()
882 {
883 return new FolderMenuOptionsDefinitionImpl();
884 }
885
886
887
888
889 public MenuSeparatorDefinition newMenuSeparatorDefinition()
890 {
891 return new FolderMenuSeparatorDefinitionImpl();
892 }
893
894
895
896
897 public void setMenuDefinitions(List definitions)
898 {
899
900
901
902 List menuDefinitions = getMenuDefinitions();
903 if (definitions != menuDefinitions)
904 {
905
906 menuDefinitions.clear();
907 if (definitions != null)
908 {
909 menuDefinitions.addAll(definitions);
910 }
911 }
912 }
913
914
915
916
917 public boolean isReserved()
918 {
919
920 return false;
921 }
922
923
924
925
926 public int getReservedType()
927 {
928
929 return RESERVED_FOLDER_NONE;
930 }
931
932
933
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
1050 NodeSetImpl filteredNodes = null;
1051 Iterator checkAccessIter = nodes.iterator();
1052 while (checkAccessIter.hasNext())
1053 {
1054 Node node = (Node)checkAccessIter.next();
1055 try
1056 {
1057
1058 node.checkAccess(JetspeedActions.VIEW);
1059
1060
1061 if (filteredNodes != null)
1062 {
1063
1064 filteredNodes.add(node);
1065 }
1066 }
1067 catch (SecurityException se)
1068 {
1069
1070 if (filteredNodes == null)
1071 {
1072
1073
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
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 }