/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.om.folder.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.apache.jetspeed.om.folder.Folder;
import org.apache.jetspeed.om.folder.FolderNotFoundException;
import org.apache.jetspeed.om.page.DynamicPage;
import org.apache.jetspeed.om.page.FragmentDefinition;
import org.apache.jetspeed.om.page.Link;
import org.apache.jetspeed.om.page.Page;
import org.apache.jetspeed.om.page.PageTemplate;
import org.apache.jetspeed.om.page.proxy.DynamicPageProxy;
import org.apache.jetspeed.om.page.proxy.FragmentDefinitionProxy;
import org.apache.jetspeed.om.page.proxy.LinkProxy;
import org.apache.jetspeed.om.page.proxy.PageProxy;
import org.apache.jetspeed.om.page.proxy.PageTemplateProxy;
import org.apache.jetspeed.om.portlet.GenericMetadata;
import org.apache.jetspeed.page.PageManager;
import org.apache.jetspeed.page.PageNotFoundException;
import org.apache.jetspeed.page.document.DocumentException;
import org.apache.jetspeed.page.document.DocumentNotFoundException;
import org.apache.jetspeed.page.document.Node;
import org.apache.jetspeed.page.document.NodeException;
import org.apache.jetspeed.page.document.NodeNotFoundException;
import org.apache.jetspeed.page.document.NodeSet;
import org.apache.jetspeed.page.document.proxy.NodeProxy;
import org.apache.jetspeed.page.document.proxy.NodeSetImpl;
import org.apache.jetspeed.portalsite.view.SearchPathsSiteView;
import org.apache.jetspeed.portalsite.view.SiteViewSearchPath;
/**
* This class proxies PSML Folder instances to create a logical view
* of site content using the Dynamic Proxy pattern.
*
* @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
* @version $Id: FolderProxy.java 995680 2010-09-10 06:14:22Z rwatler $
*/
public class FolderProxy extends NodeProxy implements InvocationHandler
{
/**
* *_METHOD - Folder method constants
*/
protected static final Method GET_ALL_METHOD = reflectMethod(Folder.class, "getAll", null);
protected static final Method GET_DEFAULT_PAGE_METHOD = reflectMethod(Folder.class, "getDefaultPage", null);
protected static final Method GET_DYNAMIC_PAGES_METHOD = reflectMethod(Folder.class, "getDynamicPages", null);
protected static final Method GET_DYNAMIC_PAGE_METHOD = reflectMethod(Folder.class, "getDynamicPage", new Class[]{String.class});
protected static final Method GET_FOLDERS_METHOD = reflectMethod(Folder.class, "getFolders", null);
protected static final Method GET_FOLDER_METHOD = reflectMethod(Folder.class, "getFolder", new Class[]{String.class});
protected static final Method GET_FRAGMENT_DEFINITIONS_METHOD = reflectMethod(Folder.class, "getFragmentDefinitions", null);
protected static final Method GET_FRAGMENT_DEFINITION_METHOD = reflectMethod(Folder.class, "getFragmentDefinition", new Class[]{String.class});
protected static final Method GET_LINKS_METHOD = reflectMethod(Folder.class, "getLinks", null);
protected static final Method GET_LINK_METHOD = reflectMethod(Folder.class, "getLink", new Class[]{String.class});
protected static final Method GET_MENU_DEFINITIONS_METHOD = reflectMethod(Folder.class, "getMenuDefinitions", null);
protected static final Method GET_METADATA_METHOD = reflectMethod(Folder.class, "getMetadata", null);
protected static final Method GET_NAME_METHOD = reflectMethod(Folder.class, "getName", null);
protected static final Method GET_PAGES_METHOD = reflectMethod(Folder.class, "getPages", null);
protected static final Method GET_PAGE_METHOD = reflectMethod(Folder.class, "getPage", new Class[]{String.class});
protected static final Method GET_PAGE_SECURITY_METHOD = reflectMethod(Folder.class, "getPageSecurity", null);
protected static final Method GET_PAGE_TEMPLATES_METHOD = reflectMethod(Folder.class, "getPageTemplates", null);
protected static final Method GET_PAGE_TEMPLATE_METHOD = reflectMethod(Folder.class, "getPageTemplate", new Class[]{String.class});
protected static final Method GET_SHORT_TITLE_LOCALE_METHOD = reflectMethod(Folder.class, "getShortTitle", new Class[]{Locale.class});
protected static final Method GET_SHORT_TITLE_METHOD = reflectMethod(Folder.class, "getShortTitle", null);
protected static final Method GET_TITLE_LOCALE_METHOD = reflectMethod(Folder.class, "getTitle", new Class[]{Locale.class});
protected static final Method GET_TITLE_METHOD = reflectMethod(Folder.class, "getTitle", null);
/**
* defaultFolderReference - default proxy delegate folder instance reference
*/
private FolderWeakReference defaultFolderReference;
/**
* titledFolderReference - titled proxy delegate folder instance reference
*/
private FolderWeakReference titledFolderReference;
/**
* forceReservedVisible - flag used to suppress child reserved/hidden folder visibility checks
*/
private boolean forceReservedVisible;
/**
* children - aggregated proxy sub-folder, page, and link nodes
*/
private NodeSet children;
/**
* childrenAggregated - boolean flag to indicate children aggregated
*/
private boolean childrenAggregated;
/**
* folders - aggregated proxy sub-folder nodes
*/
private NodeSet folders;
/**
* foldersAggregated - boolean flag to indicate folders aggregated
*/
private boolean foldersAggregated;
/**
* pages - aggregated proxy page nodes
*/
private NodeSet pages;
/**
* pagesAggregated - boolean flag to indicate pages aggregated
*/
private boolean pagesAggregated;
/**
* pageTemplates - aggregated proxy page template nodes
*/
private NodeSet pageTemplates;
/**
* pageTemplatesAggregated - boolean flag to indicate page templates aggregated
*/
private boolean pageTemplatesAggregated;
/**
* dynamicPages - aggregated proxy dynamic page nodes
*/
private NodeSet dynamicPages;
/**
* dynamicPagesAggregated - boolean flag to indicate dynamic pages aggregated
*/
private boolean dynamicPagesAggregated;
/**
* fragmentDefinitions - aggregated proxy fragment definition nodes
*/
private NodeSet fragmentDefinitions;
/**
* fragmentDefinitionsAggregated - boolean flag to indicate fragment definitions aggregated
*/
private boolean fragmentDefinitionsAggregated;
/**
* links - aggregated proxy link nodes
*/
private NodeSet links;
/**
* linksAggregated - boolean flag to indicate links aggregated
*/
private boolean linksAggregated;
/**
* SearchFolder - data object used hold concrete search folder reference
* and related search path profile locator name pairs
*/
private class SearchFolder
{
public FolderWeakReference folderReference;
public String locatorName;
public SearchFolder(FolderWeakReference folderReference, String locatorName)
{
this.folderReference = folderReference;
this.locatorName = locatorName;
}
}
/**
* searchFolders - search folder objects along view search paths
* in most to least specific order
*/
private List searchFolders;
/**
* InheritanceFolder - data object used hold aggregated concrete search
* folder references and view path to folder
*/
private class InheritanceFolder
{
public FolderWeakReference folderReference;
public String path;
public InheritanceFolder(FolderWeakReference folderReference, String path)
{
this.folderReference = folderReference;
this.path = path;
}
}
/**
* inheritanceFolders - inheritance graph folder list in most to
* least specific order
*/
private List inheritanceFolders;
/**
* newInstance - creates a new proxy instance that implements the Folder interface
*
* @param view site view owner of this proxy
* @param locatorName name of profile locator associated
* with the proxy delegate
* @param parentFolder view parent proxy folder
* @param folder proxy delegate
* @param forceReservedVisible suppress reserved/hidden folder visibility checks
*/
public static Folder newInstance(SearchPathsSiteView view, String locatorName, Folder parentFolder, Folder folder, boolean forceReservedVisible)
{
return (Folder)Proxy.newProxyInstance(folder.getClass().getClassLoader(), new Class[]{Folder.class}, new FolderProxy(view, locatorName, parentFolder, folder, forceReservedVisible));
}
/**
* FolderProxy - private constructor used by newInstance()
*
* @param view site view owner of this proxy
* @param locatorName name of profile locator associated
* with the proxy delegate
* @param parentFolder view parent proxy folder
* @param folder proxy delegate
* @param forceReservedVisible suppress reserved/hidden folder visibility checks
*/
private FolderProxy(SearchPathsSiteView view, String locatorName, Folder parentFolder, Folder folder, boolean forceReservedVisible)
{
super(view, locatorName, parentFolder, folder.getName(), folder.isHidden());
this.defaultFolderReference = selectDefaultFromAggregateFolders(folder);
this.titledFolderReference = selectTitledFromAggregateFolders(this.defaultFolderReference);
this.forceReservedVisible = forceReservedVisible;
}
/**
* invoke - method invocation dispatch for this proxy, (defaults to
* invocation of delegate unless method is implemented in this
* proxy handler or should be hidden/stubbed)
*
* @param proxy instance invoked against
* @param method Folder interface method invoked
* @param args method arguments
* @throws Throwable
*/
public Object invoke(Object proxy, Method m, Object [] args) throws Throwable
{
// proxy implementation method dispatch
if (m.equals(GET_ALL_METHOD))
{
return getAll(proxy);
}
else if (m.equals(GET_DEFAULT_PAGE_METHOD))
{
return getDefaultPage(proxy);
}
else if (m.equals(GET_DYNAMIC_PAGES_METHOD))
{
return getDynamicPages(proxy);
}
else if (m.equals(GET_DYNAMIC_PAGE_METHOD))
{
return getDynamicPage(proxy, (String)args[0]);
}
else if (m.equals(GET_FOLDERS_METHOD))
{
return getFolders(proxy);
}
else if (m.equals(GET_FOLDER_METHOD))
{
return getFolder(proxy, (String)args[0]);
}
else if (m.equals(GET_FRAGMENT_DEFINITIONS_METHOD))
{
return getFragmentDefinitions(proxy);
}
else if (m.equals(GET_FRAGMENT_DEFINITION_METHOD))
{
return getFragmentDefinition(proxy, (String)args[0]);
}
else if (m.equals(GET_LINKS_METHOD))
{
return getLinks(proxy);
}
else if (m.equals(GET_LINK_METHOD))
{
return getLink(proxy, (String)args[0]);
}
else if (m.equals(GET_MENU_DEFINITIONS_METHOD))
{
return getMenuDefinitions();
}
else if (m.equals(GET_METADATA_METHOD))
{
return getMetadata();
}
else if (m.equals(GET_NAME_METHOD))
{
return getName();
}
else if (m.equals(GET_PAGES_METHOD))
{
return getPages(proxy);
}
else if (m.equals(GET_PAGE_METHOD))
{
return getPage(proxy, (String)args[0]);
}
else if (m.equals(GET_PAGE_TEMPLATES_METHOD))
{
return getPageTemplates(proxy);
}
else if (m.equals(GET_PAGE_TEMPLATE_METHOD))
{
return getPageTemplate(proxy, (String)args[0]);
}
else if (m.equals(GET_SHORT_TITLE_LOCALE_METHOD))
{
return getShortTitle((Locale)args[0]);
}
else if (m.equals(GET_SHORT_TITLE_METHOD))
{
return getShortTitle();
}
else if (m.equals(GET_TITLE_LOCALE_METHOD))
{
return getTitle((Locale)args[0]);
}
else if (m.equals(GET_TITLE_METHOD))
{
return getTitle();
}
else if (m.equals(GET_PARENT_METHOD))
{
return getParent();
}
else if (m.equals(GET_PATH_METHOD))
{
return getPath();
}
else if (m.equals(GET_URL_METHOD))
{
return getUrl();
}
else if (m.equals(EQUALS_METHOD))
{
return new Boolean(equals(args[0]));
}
else if (m.equals(HASH_CODE_METHOD))
{
return new Integer(hashCode());
}
else if (m.equals(IS_HIDDEN_METHOD))
{
return new Boolean(isHidden());
}
else if (m.equals(TO_STRING_METHOD))
{
return toString();
}
// proxy suppression of not implemented or mutable methods
if (m.equals(GET_PAGE_SECURITY_METHOD) ||
m.getName().startsWith("set"))
{
throw new RuntimeException("Folder instance is immutable from proxy.");
}
try
{
// attempt to invoke method on delegate Folder instance
return m.invoke(defaultFolderReference.getFolder(), args);
}
catch (InvocationTargetException ite)
{
throw ite.getTargetException();
}
}
/**
* getAll - proxy implementation of Folder.getAll()
*
* @param proxy this folder proxy
* @return list containing sub-folders and documents in folder
* @throws DocumentException
*/
public NodeSet getAll(Object proxy) throws DocumentException
{
// latently aggregate all children
if (!childrenAggregated)
{
children = aggregateChildren(proxy);
childrenAggregated = true;
}
return children;
}
/**
* getDefaultPage - proxy implementation of Folder.getDefaultPage()
*
* @param proxy this folder proxy
* @return default page name
*/
public String getDefaultPage(Object proxy)
{
// attempt to get explicitly specified default page
return selectDefaultPageFromAggregateFolders(proxy);
}
/**
* getFolders - proxy implementation of Folder.getFolders()
*
* @param proxy this folder proxy
* @return list containing all sub-folders in folder
* @throws DocumentException
*/
public NodeSet getFolders(Object proxy) throws DocumentException
{
// latently subset folders by type from aggregated children
if (!foldersAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
folders = allChildren.subset(Folder.FOLDER_TYPE);
}
foldersAggregated = true;
}
return folders;
}
/**
* getFolder - proxy implementation of Folder.getFolder()
*
* @param proxy this folder proxy
* @param name sub-folder name
* @return sub-folder
* @throws FolderNotFoundException
* @throws DocumentException
*/
public Folder getFolder(Object proxy, String name) throws FolderNotFoundException, DocumentException
{
// search for folder by name or absolute path from
// aggregated folders
NodeSet allFolders = getFolders(proxy);
if (allFolders != null)
{
Folder folder = (Folder)allFolders.get(name);
if (folder != null)
{
return folder;
}
}
throw new FolderNotFoundException("Folder " + name + " not found at " + getPath());
}
/**
* getLinks - proxy implementation of Folder.getLinks()
*
* @param proxy this folder proxy
* @return list containing all links in folder
* @throws NodeException
*/
public NodeSet getLinks(Object proxy) throws NodeException
{
// latently subset links by type from aggregated children
if (!linksAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
links = allChildren.subset(Link.DOCUMENT_TYPE);
}
linksAggregated = true;
}
return links;
}
/**
* getLink - proxy implementation of Folder.getLink()
*
* @param proxy this folder proxy
* @param name link name including extension
* @return link
* @throws DocumentNotFoundException
* @throws NodeException
*/
public Link getLink(Object proxy, String name) throws DocumentNotFoundException, NodeException
{
// search for link by name or absolute path from
// aggregated links
NodeSet allLinks = getLinks(proxy);
if (allLinks != null)
{
Link link = (Link)allLinks.get(name);
if (link != null)
{
return link;
}
}
throw new DocumentNotFoundException("Link " + name + " not found at " + getPath());
}
/**
* getName - proxy implementation of Node.getName()
*
* @return name of folder
*/
public String getName()
{
// force root folder name since the folder is
// normally aggregated using more specific folders;
// otherwise, use concrete default folder name
if (getPath().equals(Folder.PATH_SEPARATOR))
{
return Folder.PATH_SEPARATOR;
}
return defaultFolderReference.getFolder().getName();
}
/**
* getPages - proxy implementation of Folder.getPages()
*
* @param proxy this folder proxy
* @return list containing all pages in folder
* @throws NodeException
*/
public NodeSet getPages(Object proxy) throws NodeException
{
// latently subset pages by type from aggregated children
if (!pagesAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
pages = allChildren.subset(Page.DOCUMENT_TYPE);
}
pagesAggregated = true;
}
return pages;
}
/**
* getPage - proxy implementation of Folder.getPage()
*
* @param proxy this folder proxy
* @param name page name including extension
* @return page
* @throws PageNotFoundException
* @throws NodeException
*/
public Page getPage(Object proxy, String name) throws PageNotFoundException, NodeException
{
// search for page by name or absolute path from
// aggregated pages
NodeSet allPages = getPages(proxy);
if (allPages != null)
{
Page page = (Page)allPages.get(name);
if (page != null)
{
return page;
}
}
throw new PageNotFoundException("Page " + name + " not found at " + getPath());
}
/**
* getDynamicPages - proxy implementation of Folder.getDynamicPages()
*
* @param proxy this folder proxy
* @return list containing all dynamic pages in folder
* @throws NodeException
*/
public NodeSet getDynamicPages(Object proxy) throws NodeException
{
// latently subset dynamic pages by type from aggregated children
if (!dynamicPagesAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
dynamicPages = allChildren.subset(DynamicPage.DOCUMENT_TYPE);
}
dynamicPagesAggregated = true;
}
return dynamicPages;
}
/**
* getDynamicPage - proxy implementation of Folder.getDynamicPage()
*
* @param proxy this folder proxy
* @param name dynamic page name including extension
* @return dynamic page
* @throws PageNotFoundException
* @throws NodeException
*/
public DynamicPage getDynamicPage(Object proxy, String name) throws PageNotFoundException, NodeException
{
// search for dynamic page by name or absolute path from
// aggregated dynamic pages
NodeSet allDynamicPages = getDynamicPages(proxy);
if (allDynamicPages != null)
{
DynamicPage dynamicPage = (DynamicPage)allDynamicPages.get(name);
if (dynamicPage != null)
{
return dynamicPage;
}
}
throw new PageNotFoundException("DynamicPage " + name + " not found at " + getPath());
}
/**
* getPageTemplates - proxy implementation of Folder.getPageTemplates()
*
* @param proxy this folder proxy
* @return list containing all page templates in folder
* @throws NodeException
*/
public NodeSet getPageTemplates(Object proxy) throws NodeException
{
// latently subset page templates by type from aggregated children
if (!pageTemplatesAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
pageTemplates = allChildren.subset(PageTemplate.DOCUMENT_TYPE);
}
pageTemplatesAggregated = true;
}
return pageTemplates;
}
/**
* getPageTemplate - proxy implementation of Folder.getPageTemplate()
*
* @param proxy this folder proxy
* @param name page template name including extension
* @return page template
* @throws PageNotFoundException
* @throws NodeException
*/
public PageTemplate getPageTemplate(Object proxy, String name) throws PageNotFoundException, NodeException
{
// search for page template by name or absolute path from
// aggregated page templates
NodeSet allPageTemplates = getPageTemplates(proxy);
if (allPageTemplates != null)
{
PageTemplate pageTemplate = (PageTemplate)allPageTemplates.get(name);
if (pageTemplate != null)
{
return pageTemplate;
}
}
throw new PageNotFoundException("PageTemplate " + name + " not found at " + getPath());
}
/**
* getFragmentDefinitions - proxy implementation of Folder.getFragmentDefinitions()
*
* @param proxy this folder proxy
* @return list containing all fragment definitions in folder
* @throws NodeException
*/
public NodeSet getFragmentDefinitions(Object proxy) throws NodeException
{
// latently subset fragment definition by type from aggregated children
if (!fragmentDefinitionsAggregated)
{
NodeSet allChildren = getAll(proxy);
if (allChildren != null)
{
fragmentDefinitions = allChildren.subset(FragmentDefinition.DOCUMENT_TYPE);
}
fragmentDefinitionsAggregated = true;
}
return fragmentDefinitions;
}
/**
* getFragmentDefinition - proxy implementation of Folder.getFragmentDefinition()
*
* @param proxy this folder proxy
* @param name fragment definition name including extension
* @return fragment definition
* @throws PageNotFoundException
* @throws NodeException
*/
public FragmentDefinition getFragmentDefinition(Object proxy, String name) throws PageNotFoundException, NodeException
{
// search for fragment definition by name or absolute path from
// aggregated fragment definitions
NodeSet allFragmentDefinitions = getFragmentDefinitions(proxy);
if (allFragmentDefinitions != null)
{
FragmentDefinition fragmentDefinition = (FragmentDefinition)allFragmentDefinitions.get(name);
if (fragmentDefinition != null)
{
return fragmentDefinition;
}
}
throw new PageNotFoundException("FragmentDefinition " + name + " not found at " + getPath());
}
/**
* getMetadata - proxy implementation of Folder.getMetadata()
*
* @return metadata
*/
public GenericMetadata getMetadata()
{
// return titled concrete folder metadata
return titledFolderReference.getFolder().getMetadata();
}
/**
* getTitle - proxy implementation of Folder.getTitle()
*
* @return default title
*/
public String getTitle()
{
// return titled concrete folder title
return titledFolderReference.getFolder().getTitle();
}
/**
* getShortTitle - proxy implementation of Folder.getShortTitle()
*
* @return default short title
*/
public String getShortTitle()
{
// return titled concrete folder short title
return titledFolderReference.getFolder().getShortTitle();
}
/**
* getTitle - proxy implementation of Folder.getTitle()
*
* @param locale preferred locale
* @return title
*/
public String getTitle(Locale locale)
{
// return titled concrete folder title
return titledFolderReference.getFolder().getTitle(locale);
}
/**
* getShortTitle - proxy implementation of Folder.getShortTitle()
*
* @param locale preferred locale
* @return short title
*/
public String getShortTitle(Locale locale)
{
// return titled concrete folder short title
return titledFolderReference.getFolder().getShortTitle(locale);
}
/**
* getDefaultFolder - get default proxy delegate folder instance
*
* @return default delegate folder
*/
public Folder getDefaultFolder()
{
return defaultFolderReference.getFolder();
}
/**
* checkAccessToFolderNotFound - checks security access to child folder
* nodes not found in aggregated children
* site view when accessed directly; folders
* part of the view are by definition
* accessible
*
* @param folderName name of child folder to check
* @throws SecurityException if view access to folder not granted
*/
public void checkAccessToFolderNotFound(String folderName)
{
try
{
// check access on concrete child in all search folders
Iterator foldersIter = getSearchFolders().iterator();
while (foldersIter.hasNext())
{
// test access against child in search folder
SearchFolder searchFolder = (SearchFolder)foldersIter.next();
Folder folder = searchFolder.folderReference.getFolder();
// ignore all folder access exceptions, (throws SecurityException on failed check access)
try
{
folder.getFolder(folderName);
}
catch (DocumentException de)
{
}
catch (FolderNotFoundException fnfe)
{
}
}
}
catch (FolderNotFoundException fnfe)
{
}
}
/**
* checkAccessToNodeNotFound - checks security access to child node
* nodes not found in aggregated children
* site view when accessed directly; pages,
* folders, and links part of the view are
* by definition accessible
*
* @throws SecurityException if view access to node not granted
*/
public void checkAccessToNodeNotFound(String nodeName)
{
try
{
// check access on concrete child in all search folders
Iterator foldersIter = getSearchFolders().iterator();
while (foldersIter.hasNext())
{
// test access against child in search folder
SearchFolder searchFolder = (SearchFolder)foldersIter.next();
Folder folder = searchFolder.folderReference.getFolder();
// ignore all folder access exceptions, (throws SecurityException on failed check access)
try
{
folder.getFolder(nodeName);
}
catch (DocumentException de)
{
}
catch (FolderNotFoundException fnfe)
{
}
// ignore all page access exceptions, (throws SecurityException on failed check access)
try
{
folder.getPage(nodeName);
}
catch (NodeException ne)
{
}
catch (PageNotFoundException ne)
{
}
// ignore all link access exceptions, (throws SecurityException on failed check access)
try
{
folder.getLink(nodeName);
}
catch (NodeException ne)
{
}
catch (DocumentNotFoundException ne)
{
}
}
}
catch (FolderNotFoundException fnfe)
{
}
}
/**
* aggregateMenuDefinitionLocators - aggregate all menu definition locators
* in site view for this folder or page
*/
protected void aggregateMenuDefinitionLocators()
{
// aggregate folder menu definition locators from most to least
// specific along inheritance folder graph by name
try
{
Iterator inheritanceFoldersIter = getInheritanceFolders().iterator();
while (inheritanceFoldersIter.hasNext())
{
// get menu definitions from inheritance folders and
// merge into aggregate menu definition locators
InheritanceFolder inheritanceFolder = (InheritanceFolder)inheritanceFoldersIter.next();
Folder folder = inheritanceFolder.folderReference.getFolder();
String path = inheritanceFolder.path;
mergeMenuDefinitionLocators(folder.getMenuDefinitions(), folder, path, false);
}
}
catch (FolderNotFoundException fnfe)
{
}
// aggregate standard menu definition locator defaults
mergeMenuDefinitionLocators(getView().getStandardMenuDefinitionLocators());
}
/**
* selectDefaultFromAggregateFolders - select most appropriate aggregate concrete
* folder to use generally in site view at
* this proxy folder view path
*
*
* @param defaultFolder default concrete folder
* @return selected concrete folder reference
*/
private FolderWeakReference selectDefaultFromAggregateFolders(Folder defaultFolder)
{
// select most specific folder, (i.e. first) along
// search paths ordered most to least specific
try
{
return ((SearchFolder)getSearchFolders().get(0)).folderReference;
}
catch (FolderNotFoundException fnfe)
{
}
return new FolderWeakReference(getView().getPageManager(), defaultFolder);
}
/**
* selectTitledFromAggregateFolders - select most appropriate aggregate concrete
* folder with a title to use in site view at
* this proxy folder view path
*
* @param defaultFolder default concrete folder reference
* @return selected concrete folder reference
*/
private FolderWeakReference selectTitledFromAggregateFolders(FolderWeakReference defaultFolder)
{
// select most specific folder along search paths
// with a specified title, short title, or metadata
try
{
Iterator foldersIter = getSearchFolders().iterator();
while (foldersIter.hasNext())
{
FolderWeakReference folderReference = ((SearchFolder)foldersIter.next()).folderReference;
Folder folder = folderReference.getFolder();
String name = folder.getName();
String title = folder.getTitle();
String shortTitle = folder.getShortTitle();
GenericMetadata folderMetadata = folder.getMetadata();
if (((title != null) && !title.equalsIgnoreCase(name)) ||
((shortTitle != null) && !shortTitle.equalsIgnoreCase(name)) ||
((folderMetadata != null) && (folderMetadata.getFields() != null) && !folderMetadata.getFields().isEmpty()))
{
return folderReference;
}
}
}
catch (FolderNotFoundException fnfe)
{
}
return defaultFolder;
}
/**
* selectDefaultPageFromAggregateFolders - select most specific default page
* proxy to use in site view at this
* proxy folder view path
*
* @param proxy this folder proxy
* @return selected default page name
*/
private String selectDefaultPageFromAggregateFolders(Object proxy)
{
// select most specific specified default page
// along search paths
try
{
// only test for fallback default page once
boolean fallbackDefaultPageNotFound = false;
Iterator foldersIter = getSearchFolders().iterator();
while (foldersIter.hasNext())
{
// get folder default page name or look for fallback default name
Folder folder = ((SearchFolder)foldersIter.next()).folderReference.getFolder();
String defaultPageName = folder.getDefaultPage();
if (defaultPageName != null)
{
// validate and return default page or folder
// if it exists as child in this folder
if (defaultPageName.equals(".."))
{
// default parent folder
if (getParent() != null)
{
return defaultPageName;
}
}
else
{
// default page
try
{
getPage(proxy, defaultPageName);
return defaultPageName;
}
catch (NodeException ne)
{
}
catch (NodeNotFoundException nnfe)
{
}
catch (SecurityException se)
{
}
// default folder
if (!defaultPageName.endsWith(Page.DOCUMENT_TYPE))
{
try
{
getFolder(proxy, defaultPageName);
return defaultPageName;
}
catch (NodeException ne)
{
}
catch (NodeNotFoundException nnfe)
{
}
catch (SecurityException se)
{
}
}
}
}
else if (!fallbackDefaultPageNotFound)
{
// validate and return fallback default page if
// it exists as child in this folder
try
{
getPage(proxy, Folder.FALLBACK_DEFAULT_PAGE);
return Folder.FALLBACK_DEFAULT_PAGE;
}
catch (NodeException ne)
{
fallbackDefaultPageNotFound = true;
}
catch (NodeNotFoundException nnfe)
{
fallbackDefaultPageNotFound = true;
}
catch (SecurityException se)
{
fallbackDefaultPageNotFound = true;
}
}
}
}
catch (FolderNotFoundException fnfe)
{
}
return null;
}
/**
* aggregateChildren - aggregate all children proxies in site view
*
* @param proxy this folder proxy
* @return list containing sub-folders, pages, and links in folder view
*/
private NodeSet aggregateChildren(Object proxy)
{
// extract all children and document ordering information
// from aggregate folders
try
{
// get children proxies
List allChildren = new ArrayList();
List folderDocumentOrder = null;
Iterator foldersIter = getSearchFolders().iterator();
while (foldersIter.hasNext())
{
// aggregate folders
SearchFolder searchFolder = (SearchFolder)foldersIter.next();
Folder folder = searchFolder.folderReference.getFolder();
String locatorName = searchFolder.locatorName;
// create and save proxies for concrete children
NodeSet children = folder.getAll();
Iterator childrenIter = children.iterator();
while (childrenIter.hasNext())
{
Node child = (Node)childrenIter.next();
String childName = child.getName();
// filter profiling property folders unless forced; they are
// normally accessed only via SiteView search path aggregation
// that directly utilizes the current view page manager
boolean visible = (forceReservedVisible || (!(child instanceof Folder) ||
(!childName.startsWith(Folder.RESERVED_SUBSITE_FOLDER_PREFIX) &&
!childName.startsWith(Folder.RESERVED_FOLDER_PREFIX))));
if (visible)
{
// test child name uniqueness
boolean childUnique = true ;
Iterator allChildrenIter = allChildren.iterator();
while (childUnique && allChildrenIter.hasNext())
{
childUnique = !childName.equals(((Node)allChildrenIter.next()).getName());
}
// add uniquely named children proxies
if (childUnique)
{
if (child instanceof Folder)
{
allChildren.add(FolderProxy.newInstance(getView(), locatorName, (Folder)proxy, (Folder)child, forceReservedVisible));
}
else if (child instanceof Page)
{
allChildren.add(PageProxy.newInstance(getView(), locatorName, (Folder)proxy, (Page)child));
}
else if (child instanceof PageTemplate)
{
allChildren.add(PageTemplateProxy.newInstance(getView(), locatorName, (Folder)proxy, (PageTemplate)child));
}
else if (child instanceof DynamicPage)
{
allChildren.add(DynamicPageProxy.newInstance(getView(), locatorName, (Folder)proxy, (DynamicPage)child));
}
else if (child instanceof FragmentDefinition)
{
allChildren.add(FragmentDefinitionProxy.newInstance(getView(), locatorName, (Folder)proxy, (FragmentDefinition)child));
}
else if (child instanceof Link)
{
allChildren.add(LinkProxy.newInstance(getView(), locatorName, (Folder)proxy, (Link)child));
}
}
}
}
// capture most specific document ordering
if (folderDocumentOrder == null)
{
List documentOrder = folder.getDocumentOrder();
if ((documentOrder != null) && !documentOrder.isEmpty())
{
folderDocumentOrder = documentOrder;
}
}
}
// sort children proxies if more than one by folder
// document order or strict collation order
if (allChildren.size() > 1)
{
final List order = folderDocumentOrder;
Comparator comparator = new Comparator()
{
public int compare(Object proxyNode1, Object proxyNode2)
{
// compare names of nodes against order or each other by default
String name1 = ((Node)proxyNode1).getName();
String name2 = ((Node)proxyNode2).getName();
if (order != null)
{
// compare names against order
int index1 = order.indexOf(name1);
int index2 = order.indexOf(name2);
if ((index1 != -1) || (index2 != -1))
{
if ((index1 == -1) && (index2 != -1))
{
return 1;
}
if ((index1 != -1) && (index2 == -1))
{
return -1;
}
return index1-index2;
}
}
// compare names against each other
return name1.compareTo(name2);
}
} ;
Collections.sort(allChildren, comparator);
}
// wrap ordered children in new NodeSet
if (!allChildren.isEmpty())
{
return new NodeSetImpl(allChildren);
}
}
catch (FolderNotFoundException fnfe)
{
}
catch (DocumentException de)
{
}
return null;
}
/**
* getSearchFolders - aggregate all concrete folders in site view
* at this proxy folder view path
*
* @return list containing concrete search folders in folder view
* @throws FolderNotFoundException
*/
private List getSearchFolders() throws FolderNotFoundException
{
// latently aggregate search folders
if (searchFolders == null)
{
// search for existing folders along search paths
List searchPaths = getView().getSearchPaths();
searchFolders = new ArrayList(searchPaths.size());
Iterator pathsIter = searchPaths.iterator();
while (pathsIter.hasNext())
{
// construct folder paths
SiteViewSearchPath searchPath = (SiteViewSearchPath)pathsIter.next();
String path = searchPath.toString();
if (!path.equals(Folder.PATH_SEPARATOR))
{
path += getPath();
}
else
{
path = getPath();
}
// get existing folders from PageManager, create
// corresponding search folder objects, and add to
// search folders list
try
{
PageManager pageManager = getView().getPageManager();
Folder folder = pageManager.getFolder(path);
if (folder != null)
{
searchFolders.add(new SearchFolder(new FolderWeakReference(pageManager, folder), searchPath.getLocatorName()));
}
}
catch (NodeException ne)
{
}
catch (NodeNotFoundException ne)
{
}
catch (SecurityException se)
{
}
}
}
// return search folders
if (!searchFolders.isEmpty())
{
return searchFolders;
}
throw new FolderNotFoundException("Search folders at " + getPath() + " not found or accessible");
}
/**
* getInheritanceFolders - aggregate all concrete inheritance folders
* in site view at this proxy folder view path
*
* @return list containing concrete inheritance folders in folder view
* @throws FolderNotFoundException
*/
private List getInheritanceFolders() throws FolderNotFoundException
{
// latently aggregate inheritance folders
if (inheritanceFolders == null)
{
// inheritance folders are aggregated from super/parent
// folder search paths for each proxy folder in the view
// path; concatenate all search paths from this proxy
// folder to the proxy root to create the inheritance
// graph folder list
FolderProxy folder = this;
List searchFolders = folder.getSearchFolders();
if (getParent() != null)
{
inheritanceFolders = new ArrayList(searchFolders.size() * 2);
}
else
{
inheritanceFolders = new ArrayList(searchFolders.size());
}
do
{
// copy ordered search path folders into inheritance
// graph folders list
Iterator foldersIter = searchFolders.iterator();
while (foldersIter.hasNext())
{
inheritanceFolders.add(new InheritanceFolder(((SearchFolder)foldersIter.next()).folderReference, folder.getPath()));
}
// get super/parent search paths
folder = (FolderProxy)getNodeProxy(folder.getParent());
if (folder != null)
{
searchFolders = folder.getSearchFolders();
}
}
while (folder != null);
}
// return inheritance folders
if (!inheritanceFolders.isEmpty())
{
return inheritanceFolders;
}
throw new FolderNotFoundException("Inheritance folders at " + getPath() + " not found or accessible");
}
/**
* getFolderProxy - utility method to access FolderProxy handler
* from Folder proxy instance
*
* @param folder folder proxy instance
* @return folder proxy invocation handler instance
*/
public static FolderProxy getFolderProxy(Object folder)
{
if ((folder != null) && Proxy.isProxyClass(folder.getClass()))
{
Object folderProxyHandler = Proxy.getInvocationHandler(folder);
if (folderProxyHandler instanceof FolderProxy)
{
return (FolderProxy)folderProxyHandler;
}
}
return null;
}
}