1/*2 * Licensed to the Apache Software Foundation (ASF) under one or more3 * contributor license agreements. See the NOTICE file distributed with4 * this work for additional information regarding copyright ownership.5 * The ASF licenses this file to You under the Apache License, Version 2.06 * (the "License"); you may not use this file except in compliance with7 * the License. You may obtain a copy of the License at8 * 9 * http://www.apache.org/licenses/LICENSE-2.010 * 11 * Unless required by applicable law or agreed to in writing, software12 * distributed under the License is distributed on an "AS IS" BASIS,13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14 * See the License for the specific language governing permissions and15 * limitations under the License.16 */17packageorg.apache.jetspeed.profiler.impl;
1819import java.io.IOException;
20import java.security.Principal;
21import java.util.HashMap;
22import java.util.Map;
2324import javax.security.auth.Subject;
25import javax.servlet.http.HttpServletResponse;
2627import org.apache.commons.logging.Log;
28import org.apache.commons.logging.LogFactory;
29import org.apache.jetspeed.PortalReservedParameters;
30import org.apache.jetspeed.decoration.PageActionAccess;
31import org.apache.jetspeed.om.page.ContentPageImpl;
32import org.apache.jetspeed.om.page.Page;
33import org.apache.jetspeed.page.document.NodeNotFoundException;
34import org.apache.jetspeed.pipeline.PipelineException;
35import org.apache.jetspeed.pipeline.valve.AbstractValve;
36import org.apache.jetspeed.pipeline.valve.PageProfilerValve;
37import org.apache.jetspeed.pipeline.valve.ValveContext;
38import org.apache.jetspeed.portalsite.PortalSite;
39import org.apache.jetspeed.portalsite.PortalSiteRequestContext;
40import org.apache.jetspeed.portalsite.PortalSiteSessionContext;
41import org.apache.jetspeed.profiler.ProfileLocator;
42import org.apache.jetspeed.profiler.Profiler;
43import org.apache.jetspeed.profiler.ProfilerException;
44import org.apache.jetspeed.request.RequestContext;
45import org.apache.jetspeed.security.SecurityHelper;
46import org.apache.jetspeed.security.UserPrincipal;
4748/***49 * ProfilerValveImpl50 * 51 * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>52 * @version $Id: ProfilerValveImpl.java 569464 2007-08-24 17:43:28Z taylor $53 */54publicclassProfilerValveImplextendsAbstractValve implements PageProfilerValve55 {
56protected Log log = LogFactory.getLog(ProfilerValveImpl.class);
5758/***59 * PORTAL_SITE_REQUEST_CONTEXT_ATTR_KEY - session portal site context attribute key60 */61publicstaticfinal String PORTAL_SITE_SESSION_CONTEXT_ATTR_KEY = "org.apache.jetspeed.portalsite.PortalSiteSessionContext";
6263/***64 * PORTAL_SITE_REQUEST_CONTEXT_ATTR_KEY - request portal site context attribute key65 */66publicstaticfinal String PORTAL_SITE_REQUEST_CONTEXT_ATTR_KEY = "org.apache.jetspeed.portalsite.PortalSiteRequestContext";
6768/***69 * PROFILED_PAGE_CONTEXT_ATTR_KEY - legacy request portal site context attribute key70 */71publicstaticfinal String PROFILED_PAGE_CONTEXT_ATTR_KEY = "org.apache.jetspeed.profiledPageContext";
7273/***74 * session key for storing map of PageActionAccess instances75 */76privatestaticfinal String PAGE_ACTION_ACCESS_MAP_SESSION_ATTR_KEY = "org.apache.jetspeed.profiler.pageActionAccessMap";
7778/***79 * profiler - profiler component80 */81private Profiler profiler;
8283/***84 * portalSite - portal site component85 */86private PortalSite portalSite;
8788/***89 * requestFallback - flag indicating whether request should fallback to root folder90 * if locators do not select a page or access is forbidden91 */92privateboolean requestFallback;
9394/***95 * useHistory - flag indicating whether to use visited page96 * history to select default page per site folder97 */98privateboolean useHistory;
99100/***101 * ProfilerValveImpl - constructor102 *103 * @param profiler profiler component reference104 * @param portalSite portal site component reference105 * @param requestFallback flag to enable root folder fallback106 * @param useHistory flag to enable selection of last visited folder page107 */108publicProfilerValveImpl( Profiler profiler, PortalSite portalSite,
109boolean requestFallback, boolean useHistory)
110 {
111this.profiler = profiler;
112this.portalSite = portalSite;
113this.requestFallback = requestFallback;
114this.useHistory = useHistory;
115 }
116117/***118 * ProfilerValveImpl - constructor119 *120 * @param profiler profiler component reference121 * @param portalSite portal site component reference122 * @param requestFallback flag to enable root folder fallback123 */124publicProfilerValveImpl(Profiler profiler, PortalSite portalSite,
125boolean requestFallback)
126 {
127this(profiler, portalSite, requestFallback, true);
128 }
129130/***131 * ProfilerValveImpl - constructor132 *133 * @param profiler profiler component reference134 * @param portalSite portal site component reference135 */136publicProfilerValveImpl(Profiler profiler, PortalSite portalSite)
137 {
138this(profiler, portalSite, true, true);
139 }
140141/*142 * (non-Javadoc)143 * 144 * @see org.apache.jetspeed.pipeline.valve.Valve#invoke(org.apache.jetspeed.request.RequestContext,145 * org.apache.jetspeed.pipeline.valve.ValveContext)146 */147publicvoid invoke( RequestContext request, ValveContext context ) throws PipelineException
148 {
149try150 {
151// get profiler locators for request subject/principal using the profiler152 Subject subject = request.getSubject();
153if (subject == null)
154 {
155thrownew ProfilerException("Missing subject for request: " + request.getPath());
156 }
157 Principal principal = SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
158if (principal == null)
159 {
160thrownew ProfilerException("Missing principal for request: " + request.getPath());
161 }
162163// get request specific profile locators if required164 Map locators = null;
165 String locatorName = (String)request.getAttribute(PROFILE_LOCATOR_REQUEST_ATTR_KEY);
166if ( locatorName != null )
167 {
168 ProfileLocator locator = profiler.getProfile(request,locatorName);
169if ( locator != null )
170 {
171 locators = new HashMap();
172 locators.put(ProfileLocator.PAGE_LOCATOR, locator);
173 }
174 }
175176// get specified or default locators for the current user,177// falling back to global defaults and, if necessary, explicity178// fallback to 'page' profile locators179if ( locators == null )
180 {
181 locators = profiler.getProfileLocators(request, principal);
182 }
183if (locators.size() == 0)
184 {
185 locators = profiler.getDefaultProfileLocators(request);
186 }
187if (locators.size() == 0)
188 {
189 locators.put(ProfileLocator.PAGE_LOCATOR, profiler.getProfile(request, ProfileLocator.PAGE_LOCATOR));
190 }
191192// get profiled page using the profiler, page manager,193// and portal site components194if (locators != null)
195 {
196// get or create portalsite session context; the session197// context maintains the user view of the site and is198// searched against to locate the requested page and199// used to build site menus from its extent; this is200// cached in the session because locators seldom change201// during the session so the session view of the site can202// be cached unless locators do change; if the context203// is invalid, (perhaps because the session was persisted204// and is now being reloaded in a new server), it must be205// replaced with a newly created session context206 PortalSiteSessionContext sessionContext = (PortalSiteSessionContext)request.getSessionAttribute(PORTAL_SITE_SESSION_CONTEXT_ATTR_KEY);
207 String pipeline = request.getPipeline().getName();
208if ((sessionContext == null) || !sessionContext.isValid() || hasPipelineChanged(pipeline, sessionContext.getPipeline()))
209 {
210 sessionContext = portalSite.newSessionContext();
211 sessionContext.setPipeline(pipeline);
212 request.setSessionAttribute(PORTAL_SITE_SESSION_CONTEXT_ATTR_KEY, sessionContext);
213 }
214215// construct and save a new portalsite request context216// using session context, locators map, fallback, and217// folder page histories; the request context uses the218// locators to initialize or resets the session context if219// locators have changed for this request; the request220// context also acts as a short term request cache for the221// selected page and built menus; however, creating the222// request context here does not select the page or build223// menus: that is done when the request context is224// accessed subsequently225 PortalSiteRequestContext requestContext = sessionContext.newRequestContext(locators, requestFallback, useHistory);
226 request.setAttribute(PORTAL_SITE_REQUEST_CONTEXT_ATTR_KEY, requestContext);
227228// additionally save request context under legacy key229// to support existing decorator access230 request.setAttribute(PROFILED_PAGE_CONTEXT_ATTR_KEY, requestContext);
231232// get profiled page from portalsite request context233// and save profile locators map; accessing the request234// context here and in subsequent valves/decorators235// latently selects the page and builds menus from the236// user site view using the request context locators;237// the managed page accesed here is the raw selected page238// as returned by the PageManager component; accessing239// the managed page here selects the current page for the240// request241 request.setPage(new ContentPageImpl(requestContext.getManagedPage()));
242 request.setProfileLocators(requestContext.getLocators());
243244 request.setAttribute(PortalReservedParameters.PAGE_EDIT_ACCESS_ATTRIBUTE,getPageActionAccess(request));
245 }
246247// continue248 context.invokeNext(request);
249 }
250catch (SecurityException se)
251 {
252// fallback to portal root folder/default page if253// no user is available and request path is not254// already attempting to access the root folder;255// this is rarely the case since the anonymous256// user is normally defined unless the default257// security system has been replaced/overridden258if (request.getRequest().getUserPrincipal() == null &&
259 request.getPath() != null &&
260 !request.getPath().equals("/"))
261 {
262try263 {
264 request.getResponse().sendRedirect(request.getRequest().getContextPath());
265 }
266catch (IOException ioe){}
267return;
268 }
269270// return standard HTTP 403 - FORBIDDEN status271 log.error(se.getMessage(), se);
272try273 {
274 request.getResponse().sendError(HttpServletResponse.SC_FORBIDDEN, se.getMessage());
275 }
276catch (IOException ioe)
277 {
278 log.error("Failed to invoke HttpServletReponse.sendError: " + ioe.getMessage(), ioe);
279 }
280 }
281catch (NodeNotFoundException nnfe)
282 {
283// return standard HTTP 404 - NOT FOUND status284 log.error(nnfe.getMessage(), nnfe);
285try286 {
287 request.getResponse().sendError(HttpServletResponse.SC_NOT_FOUND, nnfe.getMessage());
288 }
289catch (IOException ioe)
290 {
291 log.error("Failed to invoke HttpServletReponse.sendError: " + ioe.getMessage(), ioe);
292 }
293 }
294catch (Exception e)
295 {
296 log.error("Exception in request pipeline: " + e.getMessage(), e);
297thrownew PipelineException(e.toString(), e);
298 }
299 }
300301protectedboolean hasPipelineChanged(String requestPipeline, String sessionPipeline)
302 {
303if (!requestPipeline.equals(sessionPipeline))
304 {
305if (requestPipeline.equals(PortalReservedParameters.JETSPEED_CONFIG_PIPELINE_NAME)
306 || sessionPipeline.equals(PortalReservedParameters.JETSPEED_CONFIG_PIPELINE_NAME))
307returntrue;
308 }
309return false;
310 }
311312/***313 * Returns the <code>PageActionAccess</code> for the current user request.314 * @see PageActionAccess315 * @param requestContext RequestContext of the current portal request.316 * @return PageActionAccess for the current user request.317 */318protectedPageActionAccess getPageActionAccess(RequestContext requestContext)
319 {
320 Page page = requestContext.getPage();
321 String key = page.getId();
322boolean loggedOn = requestContext.getRequest().getUserPrincipal() != null;
323boolean anonymous = !loggedOn;
324PageActionAccess pageActionAccess = null;
325326 Map sessionActions = null;
327synchronized (this)
328 {
329 sessionActions = (Map) requestContext.getSessionAttribute(PAGE_ACTION_ACCESS_MAP_SESSION_ATTR_KEY);
330if (sessionActions == null)
331 {
332 sessionActions = new HashMap();
333 requestContext.setSessionAttribute(PAGE_ACTION_ACCESS_MAP_SESSION_ATTR_KEY, sessionActions);
334 }
335else336 {
337 pageActionAccess = (PageActionAccess) sessionActions.get(key);
338 }
339 }
340synchronized (sessionActions)
341 {
342if (pageActionAccess == null)
343 {
344 pageActionAccess = newPageActionAccess(anonymous, page);
345 sessionActions.put(key, pageActionAccess);
346 }
347else348 {
349 pageActionAccess.checkReset(anonymous, page);
350 }
351 }
352353return pageActionAccess;
354 }
355356public String toString()
357 {
358return"ProfilerValve";
359 }
360361 }