Coverage report

  %line %branch
org.apache.jetspeed.pipeline.valve.impl.ActionValveImpl
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * 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 and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.pipeline.valve.impl;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.util.Collection;
 21  
 import java.util.HashMap;
 22  
 import java.util.Iterator;
 23  
 
 24  
 import javax.portlet.PortletException;
 25  
 import javax.servlet.http.HttpServletRequest;
 26  
 import javax.servlet.http.HttpServletResponse;
 27  
 
 28  
 import org.apache.commons.logging.Log;
 29  
 import org.apache.commons.logging.LogFactory;
 30  
 import org.apache.jetspeed.PortalReservedParameters;
 31  
 import org.apache.jetspeed.cache.ContentCacheKey;
 32  
 import org.apache.jetspeed.cache.JetspeedContentCache;
 33  
 import org.apache.jetspeed.container.window.PortletWindowAccessor;
 34  
 import org.apache.jetspeed.container.state.MutableNavigationalState;
 35  
 import org.apache.jetspeed.exception.JetspeedException;
 36  
 import org.apache.jetspeed.om.common.portlet.MutablePortletEntity;
 37  
 import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
 38  
 import org.apache.jetspeed.om.page.ContentFragment;
 39  
 import org.apache.jetspeed.om.page.ContentFragmentImpl;
 40  
 import org.apache.jetspeed.om.page.ContentPage;
 41  
 import org.apache.jetspeed.om.page.Fragment;
 42  
 import org.apache.jetspeed.om.page.Page;
 43  
 import org.apache.jetspeed.pipeline.PipelineException;
 44  
 import org.apache.jetspeed.pipeline.valve.AbstractValve;
 45  
 import org.apache.jetspeed.pipeline.valve.ActionValve;
 46  
 import org.apache.jetspeed.pipeline.valve.ValveContext;
 47  
 import org.apache.jetspeed.request.RequestContext;
 48  
 import org.apache.pluto.PortletContainer;
 49  
 import org.apache.pluto.PortletContainerException;
 50  
 import org.apache.pluto.om.entity.PortletEntity;
 51  
 import org.apache.pluto.om.window.PortletWindow;
 52  
 
 53  
 /**
 54  
  * <p>
 55  
  * ActionValveImpl
 56  
  * </p>
 57  
  * 
 58  
  * Default implementation of the ActionValve interface.  Expects to be
 59  
  * called after the ContainerValve has set up the appropriate action window
 60  
  * within the request context.  This should come before ANY rendering takes
 61  
  * place.
 62  
  * 
 63  
  * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
 64  
  * @version $Id: ActionValveImpl.java 589933 2007-10-30 01:51:50Z woonsan $
 65  
  *
 66  
  */
 67  
 public class ActionValveImpl extends AbstractValve implements ActionValve
 68  
 {
 69  
 
 70  0
     private static final Log log = LogFactory.getLog(ActionValveImpl.class);
 71  
     private PortletContainer container;
 72  
     private PortletWindowAccessor windowAccessor;
 73  0
     private boolean patchResponseCommitted = false;
 74  
     private JetspeedContentCache portletContentCache;
 75  
 
 76  
     public ActionValveImpl(PortletContainer container, PortletWindowAccessor windowAccessor, JetspeedContentCache portletContentCache)
 77  0
     {
 78  0
         this.container = container;
 79  0
         this.windowAccessor = windowAccessor;
 80  0
         this.portletContentCache = portletContentCache;
 81  0
     }
 82  
     
 83  
     public ActionValveImpl(PortletContainer container, PortletWindowAccessor windowAccessor, JetspeedContentCache portletContentCache, boolean patchResponseCommitted)
 84  0
     {
 85  0
         this.container = container;
 86  0
         this.windowAccessor = windowAccessor;
 87  0
         this.portletContentCache = portletContentCache;        
 88  0
         this.patchResponseCommitted = patchResponseCommitted;
 89  0
     }
 90  
 
 91  
     /**
 92  
      * @see org.apache.jetspeed.pipeline.valve.Valve#invoke(org.apache.jetspeed.request.RequestContext, org.apache.jetspeed.pipeline.valve.ValveContext)
 93  
      */
 94  
     public void invoke(RequestContext request, ValveContext context) throws PipelineException
 95  
     {     
 96  0
         boolean responseCommitted = false;
 97  
         try
 98  
         {            
 99  0
             PortletWindow actionWindow = request.getActionWindow();
 100  0
             if (actionWindow != null)
 101  
             {
 102  
                 // If portlet entity is null, try to refresh the actionWindow.
 103  
                 // Under some clustered environments, a cached portlet window could have null entity.
 104  0
                 if (null == actionWindow.getPortletEntity())
 105  
                 {
 106  
                     try 
 107  
                     {
 108  0
                         Fragment fragment = request.getPage().getFragmentById(actionWindow.getId().toString());
 109  
                         
 110  0
                         if (fragment != null)
 111  
                         {
 112  0
                             ContentFragment contentFragment = new ContentFragmentImpl(fragment, class="keyword">new HashMap());
 113  0
                             actionWindow = this.windowAccessor.getPortletWindow(contentFragment);
 114  
                         }
 115  
                     } 
 116  0
                     catch (Exception e)
 117  
                     {
 118  0
                         log.error("Failed to refresh action window.", e);
 119  0
                     }
 120  
                 }
 121  
                 
 122  0
                 if (actionWindow.getPortletEntity() == null)
 123  
                 {
 124  
                     // a session is expired and the target actionWindow doesn't have portlet entity.
 125  
                     // Redirect the user back to the target page (with possibly retaining the other windows navigational state).
 126  0
                     log.warn("Portlet action was canceled because the session was expired. The actionWindow's id is " + actionWindow.getId());
 127  
                     
 128  0
                     request.setActionWindow(null);
 129  0
                     MutableNavigationalState state = (MutableNavigationalState) request.getPortalURL().getNavigationalState();
 130  
                     
 131  0
                     if (state != null)
 132  
                     {
 133  0
                         state.removeState(actionWindow);
 134  0
                         state.sync(request);
 135  0
                         request.getResponse().sendRedirect(request.getPortalURL().getPortalURL());
 136  
                         return;
 137  
                     }
 138  
                 }
 139  
 
 140  0
                 initWindow(actionWindow, request);
 141  0
                 HttpServletResponse response = request.getResponseForWindow(actionWindow);
 142  0
                 HttpServletRequest requestForWindow = request.getRequestForWindow(actionWindow);
 143  0
                 requestForWindow.setAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE, request);
 144  
                 
 145  
                 //PortletMessagingImpl msg = new PortletMessagingImpl(windowAccessor);
 146  
                 
 147  0
                 requestForWindow.setAttribute("JETSPEED_ACTION", request);
 148  0
                 container.processPortletAction(
 149  
                     actionWindow,
 150  
                     requestForWindow,
 151  
                     response);
 152  
                 // The container redirects the client after PortletAction processing
 153  
                 // so there is no need to continue the pipeline
 154  
                 
 155  
                 //msg.processActionMessage("todo", request);
 156  
                 
 157  
                 // clear the cache for all portlets on the current page
 158  0
                 clearPortletCacheForPage(request, actionWindow);
 159  
                 
 160  0
                 if (patchResponseCommitted)
 161  
                 {
 162  0
                     responseCommitted = true;
 163  
                 }
 164  
                 else
 165  
                 {
 166  0
                     responseCommitted = response.isCommitted();
 167  
                 }
 168  0
                 request.setAttribute(PortalReservedParameters.PIPELINE, null); // clear the pipeline
 169  
             }
 170  
         }
 171  0
         catch (PortletContainerException e)
 172  
         {
 173  0
             log.fatal("Unable to retrieve portlet container!", e);
 174  0
             throw new PipelineException("Unable to retrieve portlet container!", e);
 175  
         }
 176  0
         catch (PortletException e)
 177  
         {
 178  0
             log.warn("Unexpected PortletException in ActionValveImpl", e);
 179  
             //  throw new PipelineException("Unexpected PortletException in ActionValveImpl", e);
 180  
 
 181  
         }
 182  0
         catch (IOException e)
 183  
         {
 184  0
             log.error("Unexpected IOException in ActionValveImpl", e);
 185  
             // throw new PipelineException("Unexpected IOException in ActionValveImpl", e);
 186  
         }
 187  0
         catch (IllegalStateException e)
 188  
         {
 189  0
             log.error("Illegal State Exception. Response was written to in Action Phase", e);
 190  0
             responseCommitted = true;
 191  
         }
 192  0
         catch (Throwable t)
 193  
         {
 194  0
             log.error("Unknown exception processing Action", t);
 195  
         }
 196  
         finally
 197  
         {
 198  
             // Check if an action was processed and if its response has been committed
 199  
             // (Pluto will redirect the client after PorletAction processing)
 200  0
             if ( responseCommitted )
 201  
             {
 202  0
                 log.info("Action processed and response committed (pipeline processing stopped)");
 203  
             }
 204  
             else
 205  
             {
 206  
                 // Pass control to the next Valve in the Pipeline
 207  0
                 context.invokeNext(request);
 208  
             }
 209  0
         }
 210  
 
 211  0
     }
 212  
 
 213  
     protected void clearPortletCacheForPage(RequestContext request, PortletWindow actionWindow)
 214  
     throws JetspeedException
 215  
     {
 216  0
         ContentPage page = request.getPage();
 217  0
         if (null == page)
 218  
         {
 219  0
             throw new JetspeedException("Failed to find PSML Pin ContentPageAggregator.build");
 220  
         }
 221  0
         ContentFragment root = page.getRootContentFragment();
 222  0
         if (root == null)
 223  
         {
 224  0
             throw new JetspeedException("No root ContentFragment found in ContentPage");
 225  
         }
 226  0
         if (!isNonStandardAction(actionWindow))
 227  
         {
 228  0
             notifyFragments(root, request, page);
 229  
             
 230  
             // if the fragment is rendered from a decorator template, the target cache would not be cleared by the above notification.
 231  
             // so, let's clear target cache of action window directly again.
 232  0
             String fragmentId = actionWindow.getId().toString();
 233  0
             if (page.getFragmentById(fragmentId) == null)
 234  
             {
 235  0
                 clearTargetCache(fragmentId, request);
 236  
             }
 237  0
         }
 238  
         else
 239  
         {
 240  0
             ContentFragment fragment = page.getContentFragmentById(actionWindow.getId().toString());
 241  
             
 242  0
             if (fragment != null)
 243  
             {
 244  0
                 clearTargetCache(fragment, request);
 245  
             }
 246  
             else
 247  
             {
 248  0
                 clearTargetCache(actionWindow.getId().toString(), request);
 249  
             }
 250  
         }
 251  0
     }
 252  
     
 253  
     /**
 254  
      * Actions can be marked as non-standard if they don't participate in
 255  
      * JSR-168 standard action behavior. By default, actions are supposed
 256  
      * to clear the cache of all other portlets on the page.
 257  
      * By setting this parameter, we can ignore the standard behavior
 258  
      * and not clear the cache on actions. This is useful for portlets
 259  
      * which never participate with other portlets.
 260  
      * 
 261  
      */    
 262  
     protected boolean isNonStandardAction(PortletWindow actionWindow)
 263  
     {
 264  0
         PortletEntity entity = actionWindow.getPortletEntity();
 265  0
         if (entity != null)
 266  
         {
 267  0
             PortletDefinitionComposite portletDefinition = (PortletDefinitionComposite)entity.getPortletDefinition();
 268  0
             if (portletDefinition != null)
 269  
             {
 270  0
                 Collection actionList = null;
 271  
         
 272  0
                 if (portletDefinition != null)
 273  
                 {
 274  0
                     actionList = portletDefinition.getMetadata().getFields(PortalReservedParameters.PORTLET_EXTENDED_DESCRIPTOR_NON_STANDARD_ACTION);
 275  
                 }
 276  0
                 if (actionList != null) 
 277  
                 {
 278  0
                     if (!actionList.isEmpty())
 279  0
                         return true;
 280  
                 }
 281  
             }
 282  
         }
 283  0
         return false;
 284  
     }
 285  
    
 286  
     protected void notifyFragments(ContentFragment f, RequestContext context, ContentPage page)
 287  
     {
 288  0
         if (f.getContentFragments() != null && f.getContentFragments().size() > 0)
 289  
         {
 290  0
             Iterator children = f.getContentFragments().iterator();
 291  0
             while (children.hasNext())
 292  
             {
 293  0
                 ContentFragment child = (ContentFragment) children.next();
 294  0
                 if (!"hidden".equals(f.getState()))
 295  
                 {
 296  0
                     notifyFragments(child, context, page);
 297  
                 }
 298  0
             } 
 299  
         }    
 300  0
         ContentCacheKey cacheKey = portletContentCache.createCacheKey(context, f.getId());
 301  0
         if (portletContentCache.isKeyInCache(cacheKey))
 302  
         {
 303  0
             portletContentCache.remove(cacheKey);
 304  0
             portletContentCache.invalidate(context);
 305  
         }
 306  0
     }
 307  
 
 308  
     protected void clearTargetCache(ContentFragment f, RequestContext context)
 309  
     {
 310  0
         clearTargetCache(f.getId(), context);
 311  0
     }
 312  
     
 313  
     protected void clearTargetCache(String fragmentId, RequestContext context)
 314  
     {
 315  0
         ContentCacheKey cacheKey = portletContentCache.createCacheKey(context, fragmentId);
 316  
         
 317  0
         if (portletContentCache.isKeyInCache(cacheKey))
 318  
         {
 319  0
             portletContentCache.remove(cacheKey);
 320  0
             portletContentCache.invalidate(context);
 321  
         }
 322  0
     }
 323  
     
 324  
     /**
 325  
      * @see java.lang.Object#toString()
 326  
      */
 327  
     public String toString()
 328  
     {
 329  
         // TODO Auto-generated method stub
 330  0
         return "ActionValveImpl";
 331  
     }
 332  
     
 333  
     /**
 334  
      * Makes sure that this PortletWindow's PortletEntity is set to have the
 335  
      * current requests fragment.
 336  
      * @param window
 337  
      * @param request
 338  
      */
 339  
     protected void initWindow(PortletWindow window, RequestContext request)
 340  
     {
 341  0
         Page page = request.getPage();
 342  0
         Fragment fragment = page.getFragmentById(window.getId().toString());
 343  
         
 344  0
         if (fragment != null)
 345  
         {
 346  0
             ((MutablePortletEntity)window.getPortletEntity()).setFragment(fragment);
 347  
         }
 348  0
     }
 349  
 
 350  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.