001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.portalsite.impl;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Set;
026: import java.util.Collections;
027:
028: import org.apache.jetspeed.om.folder.Folder;
029: import org.apache.jetspeed.om.page.Page;
030: import org.apache.jetspeed.page.document.Node;
031: import org.apache.jetspeed.page.document.NodeException;
032: import org.apache.jetspeed.page.document.NodeNotFoundException;
033: import org.apache.jetspeed.page.document.NodeSet;
034: import org.apache.jetspeed.page.document.proxy.NodeSetImpl;
035: import org.apache.jetspeed.portalsite.Menu;
036: import org.apache.jetspeed.portalsite.PortalSiteRequestContext;
037: import org.apache.jetspeed.portalsite.PortalSiteSessionContext;
038: import org.apache.jetspeed.portalsite.view.SiteViewMenuDefinitionLocator;
039:
040: /**
041: * This class encapsulates managed request state for and
042: * interface to the portal-site component.
043: *
044: * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
045: * @version $Id: PortalSiteRequestContextImpl.java 517121 2007-03-12 07:45:49Z ate $
046: */
047: public class PortalSiteRequestContextImpl implements
048: PortalSiteRequestContext {
049: /**
050: * sessionContext - component session state/interface
051: */
052: private PortalSiteSessionContextImpl sessionContext;
053:
054: /**
055: * requestProfileLocators - map of request profile locators by locator names
056: */
057: private Map requestProfileLocators;
058:
059: /**
060: * requestFallback - flag indicating whether request should fallback to root folder
061: * if locators do not select a page or access is forbidden
062: */
063: private boolean requestFallback;
064:
065: /**
066: * useHistory - flag indicating whether to use visited page
067: * history to select default page per site folder
068: */
069: private boolean useHistory;
070:
071: /**
072: * page - cached request profiled page proxy
073: */
074: private Page requestPage;
075:
076: /**
077: * siblingPages - cached node set of visible sibling page proxies
078: */
079: private NodeSet siblingPages;
080:
081: /**
082: * siblingPagesCached - cached flag for sibling page proxies
083: */
084: private boolean siblingPagesCached;
085:
086: /**
087: * siblingFolders - cached node set of visible sibling folder proxies
088: */
089: private NodeSet siblingFolders;
090:
091: /**
092: * siblingFoldersCached - cached flag for sibling folder proxies
093: */
094: private boolean siblingFoldersCached;
095:
096: /**
097: * rootFolder - cached request profiled root folder proxy
098: */
099: private Folder requestRootFolder;
100:
101: /**
102: * rootLinks - cached node set of visible link proxies
103: */
104: private NodeSet rootLinks;
105:
106: /**
107: * rootLinksCached - cached flag for link proxies
108: */
109: private boolean rootLinksCached;
110:
111: /**
112: * pageMenuDefinitionNames - cached menu definition names for request page
113: */
114: private Set pageMenuDefinitionNames;
115:
116: /**
117: * menuDefinitionLocatorCache - cached menu definition locators for
118: * relative menus valid for request
119: */
120: private Map menuDefinitionLocatorCache;
121:
122: /**
123: * PortalSiteRequestContextImpl - constructor
124: *
125: * @param sessionContext session context
126: * @param requestProfileLocators request profile locators
127: * @param requestFallback flag specifying whether to fallback to root folder
128: * if locators do not select a page or access is forbidden
129: * @param useHistory flag indicating whether to use visited page
130: * history to select default page per site folder
131: */
132: public PortalSiteRequestContextImpl(
133: PortalSiteSessionContextImpl sessionContext,
134: Map requestProfileLocators, boolean requestFallback,
135: boolean useHistory) {
136: this .sessionContext = sessionContext;
137: this .requestProfileLocators = requestProfileLocators;
138: this .requestFallback = requestFallback;
139: this .useHistory = useHistory;
140: }
141:
142: /**
143: * PortalSiteRequestContextImpl - constructor
144: *
145: * @param sessionContext session context
146: * @param requestProfileLocators request profile locators
147: * @param requestFallback flag specifying whether to fallback to root folder
148: * if locators do not select a page or access is forbidden
149: */
150: public PortalSiteRequestContextImpl(
151: PortalSiteSessionContextImpl sessionContext,
152: Map requestProfileLocators, boolean requestFallback) {
153: this (sessionContext, requestProfileLocators, requestFallback,
154: true);
155: }
156:
157: /**
158: * PortalSiteRequestContextImpl - constructor
159: *
160: * @param sessionContext session context
161: * @param requestProfileLocators request profile locators
162: */
163: public PortalSiteRequestContextImpl(
164: PortalSiteSessionContextImpl sessionContext,
165: Map requestProfileLocators) {
166: this (sessionContext, requestProfileLocators, true, true);
167: }
168:
169: /**
170: * getSessionContext - get component session context
171: *
172: * @return component session context
173: */
174: public PortalSiteSessionContext getSessionContext() {
175: return sessionContext;
176: }
177:
178: /**
179: * getLocators - get profile locators by locator names
180: *
181: * @return request profile locators
182: */
183: public Map getLocators() {
184: return requestProfileLocators;
185: }
186:
187: /**
188: * getManagedPage - get request profiled concrete page instance
189: * as managed by the page manager
190: *
191: * @return managed page
192: * @throws NodeNotFoundException if page not found
193: * @throws SecurityException if page view access not granted
194: */
195: public Page getManagedPage() throws NodeNotFoundException {
196: return sessionContext.getManagedPage(getPage());
197: }
198:
199: /**
200: * getPage - get request profiled page proxy
201: *
202: * @return page proxy
203: * @throws NodeNotFoundException if page not found
204: * @throws SecurityException if page view access not granted
205: */
206: public Page getPage() throws NodeNotFoundException {
207: // select request page from session context using
208: // request profile locators if not previously
209: // cached in this context
210: if (requestPage == null) {
211: requestPage = sessionContext
212: .selectRequestPage(requestProfileLocators,
213: requestFallback, useHistory);
214: }
215: return requestPage;
216: }
217:
218: /**
219: * getFolder - get folder proxy relative to request profiled page
220: *
221: * @return page folder proxy
222: * @throws NodeNotFoundException if page not found
223: * @throws SecurityException if page view access not granted
224: */
225: public Folder getFolder() throws NodeNotFoundException {
226: // return parent folder of request page
227: Page page = getPage();
228: if (page != null) {
229: return (Folder) page.getParent();
230: }
231: return null;
232: }
233:
234: /**
235: * getSiblingPages - get node set of sibling page proxies relative
236: * to request profiled page, (includes profiled
237: * page proxy)
238: *
239: * @return sibling page proxies
240: * @throws NodeNotFoundException if page not found
241: * @throws SecurityException if page view access not granted
242: */
243: public NodeSet getSiblingPages() throws NodeNotFoundException {
244: // cache filtered return value
245: if (!siblingPagesCached) {
246: // return pages from parent folder of request page
247: Folder folder = getFolder();
248: if (folder != null) {
249: try {
250: // access, filter hidden, and cache
251: siblingPages = filterHiddenNodes(folder.getPages());
252: siblingPagesCached = true;
253: } catch (NodeException ne) {
254: NodeNotFoundException nnfe = new NodeNotFoundException(
255: "Sibling pages not found.");
256: nnfe.initCause(ne);
257: throw nnfe;
258: }
259: }
260: }
261: return siblingPages;
262: }
263:
264: /**
265: * getParentFolder - get parent folder proxy relative to request
266: * profiled page
267: *
268: * @return parent folder proxy or null
269: * @throws NodeNotFoundException if page not found
270: * @throws SecurityException if page view access not granted
271: */
272: public Folder getParentFolder() throws NodeNotFoundException {
273: // return parent folder of parent folder of request page
274: Folder folder = getFolder();
275: if (folder != null) {
276: // access, filter hidden, and return
277: Folder parent = (Folder) folder.getParent();
278: if ((parent != null) && !parent.isHidden()) {
279: return parent;
280: }
281: }
282: return null;
283: }
284:
285: /**
286: * getSiblingFolders - get node set of sibling folder proxies relative
287: * to request profiled page, (includes profiled
288: * page folder proxy)
289: *
290: * @return sibling folder proxies
291: * @throws NodeNotFoundException if page not found
292: * @throws SecurityException if page view access not granted
293: */
294: public NodeSet getSiblingFolders() throws NodeNotFoundException {
295: // cache filtered return value
296: if (!siblingFoldersCached) {
297: // return folders from parent folder of request page
298: Folder folder = getFolder();
299: if (folder != null) {
300: try {
301: // access, filter hidden, and cache
302: siblingFolders = filterHiddenNodes(folder
303: .getFolders());
304: siblingFoldersCached = true;
305: } catch (NodeException ne) {
306: NodeNotFoundException nnfe = new NodeNotFoundException(
307: "Sibling folders not found.");
308: nnfe.initCause(ne);
309: throw nnfe;
310: }
311: }
312: }
313: return siblingFolders;
314: }
315:
316: /**
317: * getRootFolder - get root profiled folder proxy
318: *
319: * @return parent folder proxy
320: * @throws NodeNotFoundException if page not found
321: * @throws SecurityException if page view access not granted
322: */
323: public Folder getRootFolder() throws NodeNotFoundException {
324: // get request root folder from session context
325: // using request profile locators if not previously
326: // cached in this context
327: if (requestRootFolder == null) {
328: requestRootFolder = sessionContext
329: .getRequestRootFolder(requestProfileLocators);
330: }
331: return requestRootFolder;
332: }
333:
334: /**
335: * getRootLinks - get node set of link proxies relative to
336: * profiled root folder
337: *
338: * @return root link proxies
339: * @throws NodeNotFoundException if page not found
340: * @throws SecurityException if page view access not granted
341: */
342: public NodeSet getRootLinks() throws NodeNotFoundException {
343: // cache filtered return value
344: if (!rootLinksCached) {
345: // return links from request root folder
346: Folder rootFolder = getRootFolder();
347: if (rootFolder != null) {
348: try {
349: // access, filter hidden, and cache
350: rootLinks = filterHiddenNodes(rootFolder.getLinks());
351: rootLinksCached = true;
352: } catch (NodeException ne) {
353: NodeNotFoundException nnfe = new NodeNotFoundException(
354: "Root links not found.");
355: nnfe.initCause(ne);
356: throw nnfe;
357: }
358: }
359: }
360: return rootLinks;
361: }
362:
363: /**
364: * getStandardMenuNames - get set of available standard menu names
365: *
366: * @return menu names set
367: */
368: public Set getStandardMenuNames() {
369: // return standard menu names defined for session
370: return sessionContext.getStandardMenuNames();
371: }
372:
373: /**
374: * getCustomMenuNames - get set of custom menu names available as
375: * defined for the request profiled page and folder
376: *
377: * @return menu names set
378: * @throws NodeNotFoundException if page not found
379: * @throws SecurityException if page view access not granted
380: */
381: public Set getCustomMenuNames() throws NodeNotFoundException {
382: // access page to force request page resolution
383: Page page = getPage();
384:
385: // return available menu definition names from
386: // current request page if not previously cached
387: // in this context
388: Set standardMenuNames = sessionContext.getStandardMenuNames();
389: if ((page != null) && (standardMenuNames != null)
390: && (pageMenuDefinitionNames == null)) {
391: List locators = sessionContext
392: .getMenuDefinitionLocators(page);
393: if (locators != null) {
394: // get custom definition names
395: pageMenuDefinitionNames = Collections
396: .synchronizedSet(new HashSet(locators.size()));
397: Iterator locatorsIter = locators.iterator();
398: while (locatorsIter.hasNext()) {
399: // get definition name; filter standard menu names
400: String definitionName = ((SiteViewMenuDefinitionLocator) locatorsIter
401: .next()).getName();
402: if (!standardMenuNames.contains(definitionName)) {
403: pageMenuDefinitionNames.add(definitionName);
404: }
405: }
406: } else {
407: pageMenuDefinitionNames = Collections
408: .synchronizedSet(new HashSet(0));
409: }
410: }
411: return pageMenuDefinitionNames;
412: }
413:
414: /**
415: * getMenu - get instantiated menu available for the request
416: * profiled page and folder
417: *
418: * @param name menu definition name
419: * @return menu instance
420: * @throws NodeNotFoundException if page not found
421: * @throws SecurityException if page view access not granted
422: */
423: public Menu getMenu(String name) throws NodeNotFoundException {
424: // get menu initiating at menu definition root
425: // with no related menu definition names
426: return getMenu(name, null);
427: }
428:
429: /**
430: * getMenu - get instantiated menu available for the request
431: * profiled page and folder, avoiding cyclic
432: * menu definition loops by propagating related menu
433: * names set from menu construction
434: *
435: * @param name menu definition name
436: * @param names set of related menu definition names
437: * @return menu instance
438: * @throws NodeNotFoundException if page not found
439: * @throws SecurityException if page view access not granted
440: */
441: public Menu getMenu(String name, Set names)
442: throws NodeNotFoundException {
443: // access page to force request page resolution
444: Page page = getPage();
445: if ((page != null) && (name != null)) {
446: // get menu definition locator
447: SiteViewMenuDefinitionLocator locator = sessionContext
448: .getMenuDefinitionLocator(page, name);
449: if (locator != null) {
450: // lookup and return cached relative/request menus
451: if (menuDefinitionLocatorCache != null) {
452: MenuImpl menu = (MenuImpl) menuDefinitionLocatorCache
453: .get(locator);
454: if (menu != null) {
455: return menu;
456: }
457: }
458:
459: // lookup and return cached absolute/session menus
460: // if current page is not hidden; hidden pages generate
461: // menus that should be considered relative since
462: // explicitly addressed hidden pages are added to
463: // menus for display purposes
464: if (sessionContext.getMenuDefinitionLocatorCache() != null) {
465: MenuImpl menu = (MenuImpl) sessionContext
466: .getMenuDefinitionLocatorCache().get(
467: locator);
468: if (menu != null) {
469: return menu;
470: }
471: }
472:
473: // construct new menu from menu definition in locator
474: // using current request context and propagating related
475: // names set to detect cyclic menu definitions
476: MenuImpl menu = new MenuImpl(locator
477: .getMenuDefinition(), this , names);
478:
479: // determine whether menu definition locator is
480: // relative/request, based on hidden page, or
481: // absolute/session cachable and cache accordingly
482: if (page.isHidden() || menu.isElementRelative()) {
483: // cache relative menu for request
484: if (menuDefinitionLocatorCache == null) {
485: menuDefinitionLocatorCache = Collections
486: .synchronizedMap(new HashMap(8));
487: }
488: menuDefinitionLocatorCache.put(locator, menu);
489: } else {
490: // cache absolute menu for session
491: if (sessionContext.getMenuDefinitionLocatorCache() == null) {
492: sessionContext
493: .setMenuDefinitionLocatorCache(Collections
494: .synchronizedMap(new HashMap(8)));
495: }
496: sessionContext.getMenuDefinitionLocatorCache().put(
497: locator, menu);
498: }
499:
500: // return new cached menu
501: return menu;
502: }
503: }
504: return null;
505: }
506:
507: /**
508: * filterHiddenNodes - utility to filter hidden node proxies out of node sets
509: *
510: * @param nodes proxy node set to filter
511: * @return input or filtered proxy node set
512: */
513: private static NodeSet filterHiddenNodes(NodeSet nodes) {
514: if ((nodes != null) && !nodes.isEmpty()) {
515: // filter node proxies in node set
516: List filteredNodes = null;
517: Iterator nodesIter = nodes.iterator();
518: while (nodesIter.hasNext()) {
519: // test hidden status of individual node proxies
520: Node node = (Node) nodesIter.next();
521: if (node.isHidden()) {
522: // if not copying, create new node set
523: // and copy preceding node proxies
524: if (filteredNodes == null) {
525: filteredNodes = new ArrayList(nodes.size());
526: Iterator copyIter = nodes.iterator();
527: while (copyIter.hasNext()) {
528: Node copyNode = (Node) copyIter.next();
529: if (copyNode != node) {
530: filteredNodes.add(copyNode);
531: } else {
532: break;
533: }
534: }
535: }
536: } else if (filteredNodes != null) {
537: // if copying, copy node proxy to filtered set
538: filteredNodes.add(node);
539: }
540: }
541:
542: // return filteredNodes node proxies if generated
543: // in new immutable proxy node set
544: if (filteredNodes != null) {
545: return new NodeSetImpl(filteredNodes);
546: }
547: }
548: return nodes;
549: }
550: }
|