View Javadoc

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.decoration;
18  
19  import java.util.ArrayList;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Properties;
25  
26  import javax.portlet.PortletMode;
27  import javax.portlet.WindowState;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.apache.jetspeed.JetspeedActions;
32  import org.apache.jetspeed.PortalReservedParameters;
33  import org.apache.jetspeed.cache.CacheElement;
34  import org.apache.jetspeed.cache.ContentCacheKey;
35  import org.apache.jetspeed.cache.JetspeedContentCache;
36  import org.apache.jetspeed.components.portletentity.PortletEntityNotStoredException;
37  import org.apache.jetspeed.container.url.PortalURL;
38  import org.apache.jetspeed.container.window.FailedToRetrievePortletWindow;
39  import org.apache.jetspeed.container.window.PortletWindowAccessor;
40  import org.apache.jetspeed.decoration.caches.SessionPathResolverCache;
41  import org.apache.jetspeed.om.common.portlet.PortletApplication;
42  import org.apache.jetspeed.om.common.portlet.PortletDefinitionComposite;
43  import org.apache.jetspeed.om.page.ContentFragment;
44  import org.apache.jetspeed.om.page.ContentPage;
45  import org.apache.jetspeed.om.page.Fragment;
46  import org.apache.jetspeed.om.page.Page;
47  import org.apache.jetspeed.pipeline.PipelineException;
48  import org.apache.jetspeed.pipeline.valve.AbstractValve;
49  import org.apache.jetspeed.pipeline.valve.Valve;
50  import org.apache.jetspeed.pipeline.valve.ValveContext;
51  import org.apache.jetspeed.request.RequestContext;
52  import org.apache.jetspeed.security.SecurityAccessController;
53  import org.apache.pluto.om.portlet.ContentTypeSet;
54  import org.apache.pluto.om.window.PortletWindow;
55  
56  /***
57   * Assigns decorations and page actions to all of the portlet Fragments within
58   * the current request. 
59   * 
60   * @see org.apache.jetspeed.om.page.Fragment 
61   * @see org.apache.jetspeed.om.page.Page
62   * @see org.apache.jetspeed.decoration.Decoration
63   * @see org.apache.jetspeed.decoration.LayoutDecoration
64   * @see org.apache.jetspeed.decoration.PortletDecoration
65   * @see org.apache.jetspeed.decoration.Theme
66   * 
67   * @author <href a="mailto:weaver@apache.org">Scott T. Weaver</a>
68   * @author <href a="mailto:firevelocity@gmail.com">Vivek Kumar</a>
69   *
70   */
71  public class DecorationValve extends AbstractValve implements Valve
72  {
73      public static final String ACTION_IMAGE_EXTENSION_ATTR = "actionImageExtension";
74      public static final String IS_AJAX_DECORATION_REQUEST = "org.apache.jetspeed.decoration.ajax";
75      
76      protected final static Log log = LogFactory.getLog(DecorationValve.class);
77      
78      private final DecorationFactory decorationFactory;
79  
80      private final PortletWindowAccessor windowAccessor;
81      
82      private HashMap decoratorActionsAdapterCache = new HashMap();
83      
84      private DecoratorActionsFactory defaultDecoratorActionsFactory;
85  
86      private JetspeedContentCache cache = null;
87      
88      private boolean useSessionForThemeCaching = false;
89      
90      private boolean maxOnEdit = false;
91      
92      private boolean maxOnConfig = false;
93      
94      private boolean maxOnEditDefaults = false;
95      
96      /***
97       * When edit_defaults mode is not supported by a portlet, support the mode automatically.
98       */
99      private boolean autoSwitchingForConfigMode = false;
100 
101     /***
102      * When edit_defaults mode is not supported by a portlet, support the mode automatically.
103      */
104     private boolean autoSwitchingToEditDefaultsModes = true;
105          
106      /***
107       * For security constraint checks
108       */
109      protected SecurityAccessController accessController;
110 
111      public DecorationValve(DecorationFactory decorationFactory, PortletWindowAccessor windowAccessor,SecurityAccessController accessController)
112      {
113          this(decorationFactory, windowAccessor, accessController, null);
114      }
115      
116      public DecorationValve(DecorationFactory decorationFactory, PortletWindowAccessor windowAccessor,
117                             SecurityAccessController accessController, JetspeedContentCache cache)
118      {    
119          this(decorationFactory, windowAccessor, accessController, cache, false);
120      }
121      
122      public DecorationValve(DecorationFactory decorationFactory, PortletWindowAccessor windowAccessor,
123                                  SecurityAccessController accessController, JetspeedContentCache cache,
124                                  boolean useSessionForThemeCaching)
125      {       
126         this.decorationFactory = decorationFactory;
127         this.windowAccessor = windowAccessor;
128         this.defaultDecoratorActionsFactory = new DefaultDecoratorActionsFactory();        
129         //added the accessController in portlet decorater for checking the actions
130         this.accessController = accessController;        
131         this.cache = cache;
132         this.useSessionForThemeCaching = useSessionForThemeCaching;
133     }
134     
135     public void invoke(RequestContext requestContext, ValveContext context) throws PipelineException
136     {
137         //long start = System.currentTimeMillis();
138         boolean isAjaxRequest = (context == null);        
139         initFragments( requestContext, isAjaxRequest, null );        
140         //long end = System.currentTimeMillis();
141         //System.out.println(end - start);
142         if (!isAjaxRequest)
143         {
144             context.invokeNext(requestContext);
145         }
146     }
147 
148 
149     public void initFragments( RequestContext requestContext, boolean isAjaxRequest, List fragments )
150     {
151         if (isAjaxRequest)
152         {
153             requestContext.setAttribute(IS_AJAX_DECORATION_REQUEST, new Boolean(true));
154         }
155 
156         ContentPage page = requestContext.getPage();
157 
158         // Globaly override all psml themes if override session attribute has been set
159         if (requestContext
160                 .getSessionAttribute(PortalReservedParameters.PAGE_THEME_OVERRIDE_ATTRIBUTE) != null)
161         {
162             String decoratorName = (String) requestContext
163                     .getSessionAttribute(PortalReservedParameters.PAGE_THEME_OVERRIDE_ATTRIBUTE);
164             page.setDefaultDecorator(decoratorName, Fragment.LAYOUT);
165         }
166         
167         PageActionAccess pageActionAccess = (PageActionAccess)requestContext.getAttribute(PortalReservedParameters.PAGE_EDIT_ACCESS_ATTRIBUTE);
168         String themeCacheKey = null;
169         ContentCacheKey themeContentCacheKey = null;
170         Theme theme = null;
171         
172         if (useCache())
173         {
174             if (pageActionAccess.isEditing() == false)
175             {
176                 // user helps us with the funky way jetspeed doesn't create  a new session on login
177                 if (this.useSessionForThemeCaching)
178                 {
179                     themeCacheKey = cache.createSessionKey(requestContext);
180                     theme = (Theme) requestContext.getSessionAttribute(themeCacheKey);
181                 }
182                 else
183                 {
184                     themeContentCacheKey = cache.createCacheKey(requestContext, page.getId());
185                     CacheElement themeCacheElem = cache.get(themeContentCacheKey);
186                     
187                     if (themeCacheElem != null)
188                     {
189                         theme = (Theme) themeCacheElem.getContent();
190                     }
191                 }
192             }
193         }
194 
195         if (theme != null)
196         {
197             theme.init(page, decorationFactory, requestContext);
198             requestContext.setAttribute(PortalReservedParameters.PAGE_THEME_ATTRIBUTE, theme);
199             boolean solo = isSoloMode(requestContext);            
200             SessionPathResolverCache sessionPathResolver = new SessionPathResolverCache( requestContext.getRequest().getSession() );
201             initDepthFragmentDecorations(requestContext, theme, page.getRootContentFragment(),
202                                                     pageActionAccess, isAjaxRequest,
203                                                     ((DecorationFactoryImpl) decorationFactory).getResourceValidator(),
204                                                     sessionPathResolver, (theme.isInvalidated() && !solo));
205             
206             if (theme.isInvalidated() && !solo)
207             {
208                 if (this.useSessionForThemeCaching)
209                 {
210                     requestContext.setSessionAttribute(themeCacheKey, theme);
211                 }
212                 else
213                 {                    
214                     CacheElement themeCacheElem = cache.createElement(themeContentCacheKey, theme);
215                     cache.put(themeCacheElem);
216                 }
217                 theme.setInvalidated(false);                            
218             }                        
219             return;
220         }
221         theme = decorationFactory.getTheme(page, requestContext);        
222         requestContext.setAttribute(PortalReservedParameters.PAGE_THEME_ATTRIBUTE, theme);
223         if ( fragments == null || fragments.size() == 0 )
224         {
225             ContentFragment rootFragment = page.getRootContentFragment();
226             initDepthFragments(requestContext, theme, rootFragment, pageActionAccess, isAjaxRequest, fragments);
227         }
228         else
229         {
230             Iterator fragmentsIter = fragments.iterator();
231             while ( fragmentsIter.hasNext() )
232             {
233                 ContentFragment fragment = (ContentFragment)fragmentsIter.next();
234                 initFragment(requestContext, theme, fragment, pageActionAccess, isAjaxRequest);
235             }
236         }
237         
238         if (useCache() && !isSoloMode(requestContext))
239         {
240             if (themeContentCacheKey == null && themeCacheKey == null)
241             {
242                 if (this.useSessionForThemeCaching)
243                 {
244                     themeCacheKey = cache.createSessionKey(requestContext);                    
245                     requestContext.getRequest().getSession().removeAttribute(themeCacheKey);
246                 }
247                 else
248                 {
249                     themeContentCacheKey = cache.createCacheKey(requestContext, page.getId());
250                     cache.remove(themeContentCacheKey);
251                 }                
252             }
253             else
254             {
255                 if (this.useSessionForThemeCaching)
256                 {
257                     themeContentCacheKey = cache.createCacheKey(requestContext, page.getId());
258                     requestContext.setSessionAttribute(themeCacheKey, theme);
259                 }
260                 else
261                 {
262                     CacheElement themeCacheElem = cache.createElement(themeContentCacheKey, theme);
263                     cache.put(themeCacheElem);
264                 }
265             }
266         }                
267     }
268 
269     protected boolean isSoloMode(RequestContext requestContext)
270     {
271         boolean solo = false;
272         PortletWindow window = requestContext.getPortalURL().getNavigationalState().getMaximizedWindow();
273         boolean maximized = (window != null);
274         if (maximized)
275         {
276             solo = JetspeedActions.SOLO_STATE.equals(requestContext.getPortalURL().getNavigationalState().getMappedState(window));
277         }
278         return solo;
279     }
280     
281     protected boolean useCache()
282     {
283         return this.cache != null;
284     }
285     
286     public String toString()
287     {
288         return "DecorationValve";
289     }
290     
291     public DecoratorActionsFactory getDecoratorActionsAdapter(Decoration decoration)
292     {
293         // FIXME: why always get this property
294         String decoratorActionsAdapterClassName = decoration.getProperty("actions.factory");
295         if ( decoratorActionsAdapterClassName == null )
296         {
297             decoratorActionsAdapterClassName = defaultDecoratorActionsFactory.getClass().getName();
298         }
299         synchronized (decoratorActionsAdapterCache)
300         {
301             DecoratorActionsFactory adapter = (DecoratorActionsFactory)decoratorActionsAdapterCache.get(decoratorActionsAdapterClassName);
302             if ( adapter == null )
303             {
304                 try
305                 {
306                     adapter = (DecoratorActionsFactory)Class.forName(decoratorActionsAdapterClassName).newInstance();
307                     adapter.setMaximizeOnEdit(this.maxOnEdit);
308                     adapter.setMaximizeOnConfig(this.maxOnConfig);
309                     adapter.setMaximizeOnEditDefaults(this.maxOnEditDefaults);
310                 }
311                 catch (Exception e)
312                 {
313                     log.error("Failed to instantiate custom DecoratorActionsAdaptor "+decoratorActionsAdapterClassName+", falling back to default.",e);
314                     adapter = (DecoratorActionsFactory)decoratorActionsAdapterCache.get(defaultDecoratorActionsFactory.getClass().getName());
315                     if ( adapter == null )
316                     {
317                         adapter = defaultDecoratorActionsFactory;
318                     }
319                 }
320                 decoratorActionsAdapterCache.put(decoratorActionsAdapterClassName,adapter);
321             }
322             return adapter;
323         }
324     }
325     
326     /***
327      * Builds and assigns a list of available portlet modes and window states for
328      * the target <code>Fragment</code>.
329      * 
330      * @param requestContext RequestContext of the current portal request.
331      * @param fragment Fragment to initialize modes and states for.
332      * @return
333      * @throws PortletEntityNotStoredException 
334      * @throws FailedToRetrievePortletWindow 
335      */
336     protected boolean initActionsForFragment(RequestContext requestContext, 
337                                              ContentFragment fragment, 
338                                              PageActionAccess pageActionAccess, 
339                                              Decoration decoration,
340                                              boolean isAjaxRequest) throws FailedToRetrievePortletWindow, PortletEntityNotStoredException
341     {
342         boolean fragmentSupportsActions = false;
343         PortletWindow window = windowAccessor.getPortletWindow(fragment); 
344         PortletDefinitionComposite portlet = (PortletDefinitionComposite) window.getPortletEntity().getPortletDefinition();
345         
346         if (null == portlet)
347         {
348             return fragmentSupportsActions; // allow nothing
349         }
350 
351         List actions = Collections.EMPTY_LIST;
352         
353         PortletMode currentMode = requestContext.getPortalURL().getNavigationalState().getMode(window);
354         WindowState currentState = requestContext.getPortalURL().getNavigationalState().getState(window);
355         ContentTypeSet content = portlet.getContentTypeSet();
356         
357         if ( fragment.equals(requestContext.getPage().getRootFragment()) )
358         {
359             fragmentSupportsActions = true;
360             actions = getPageModes(requestContext, window, content, currentMode, currentState, pageActionAccess, decoration, isAjaxRequest);
361         }
362         else if ( !Fragment.LAYOUT.equals(fragment.getType()) )
363         {
364             fragmentSupportsActions = true;
365             String fragmentId = fragment.getId();
366             PortletApplication pa = (PortletApplication)window.getPortletEntity().getPortletDefinition().getPortletApplicationDefinition();
367 
368             String portletName = portlet.getUniqueName();
369 
370             PortletMode currentMappedMode = pa.getMappedPortletMode(currentMode);
371             WindowState currentMappedState = pa.getMappedWindowState(currentState);
372 
373             Object action;
374             PortletMode mappedMode;
375             PortletMode customMode;
376             WindowState mappedState;
377             WindowState customState;
378             
379             ArrayList actionTemplates = new ArrayList();
380             
381             DecoratorActionsFactory actionsAdapter = getDecoratorActionsAdapter(decoration);
382             
383             List supportedActions = actionsAdapter.getSupportedActions(requestContext, pa, window, currentMappedMode, currentMappedState, decoration);
384             Iterator iter = supportedActions.iterator();
385             
386             String currentModeAction = null;
387             String currentStateAction = null;
388 
389             while ( iter.hasNext() )
390             {
391                 action = iter.next();
392                 if ( action instanceof PortletMode )
393                 {
394                     mappedMode = (PortletMode)action;
395                     customMode = pa.getCustomPortletMode(mappedMode);
396                     
397                     if ( customMode != null )
398                     {
399                         boolean equalsCurrentMode = customMode.equals(currentMode);
400                         if ( equalsCurrentMode )
401                         {
402                             currentModeAction = mappedMode.toString();
403                         }
404                         if ( ! equalsCurrentMode || isAjaxRequest )
405                         {
406                             if ( (content.supportsPortletMode(customMode) || isAutoSwitchableCustomMode(content, customMode))
407                                  && (!PortletMode.EDIT.equals(customMode) || pageActionAccess.isEditAllowed())
408                                  && pageActionAccess.checkPortletMode(fragmentId, portletName, mappedMode)
409                                  )
410                             {
411                                 actionTemplates.add(new DecoratorActionTemplate(mappedMode, customMode));
412                             }
413                         }
414                     }
415                 }
416                 else if ( action instanceof WindowState )
417                 {
418                     mappedState = (WindowState)action;
419                     customState = pa.getCustomWindowState(mappedState);
420 
421                     if ( customState != null )
422                     {
423                         boolean equalsCurrentState = customState.equals(currentState);
424                         if ( equalsCurrentState )
425                         {
426                             currentStateAction = mappedState.toString();
427                         }
428                         if ( ! equalsCurrentState || isAjaxRequest )
429                         {
430                             if ( pageActionAccess.checkWindowState(fragmentId, portletName, mappedState ) )
431                             {
432                                 actionTemplates.add(new DecoratorActionTemplate(mappedState, customState));
433                             }
434                         }
435                     }
436                 }
437             }
438             actions = actionsAdapter.getDecoratorActions(requestContext, pa, window, currentMode, currentState, decoration, actionTemplates,portlet,fragment,accessController);            
439             
440             decoration.setCurrentModeAction( currentModeAction );
441             decoration.setCurrentStateAction( currentStateAction );
442         }
443         
444         decoration.setActions( actions );
445         
446         return fragmentSupportsActions;
447     }
448     
449     /***
450      * Builds a list of portlet modes that can be executed on the current
451      * <code>fragment</code> excluding the portlet's current mode.
452      * 
453      * @param requestContext RequestContext of the current portal request.
454      * @param pageActionAccess
455      * @param mode
456      * @param content
457      * @param portletName
458      * @param window
459      * @param fragment
460      * @return <code>java.util.List</code> of modes excluding the current one.
461      * @throws PortletEntityNotStoredException 
462      */
463     protected List getPageModes(RequestContext requestContext, PortletWindow window, ContentTypeSet content, 
464                                 PortletMode mode, WindowState state, PageActionAccess pageActionAccess, Decoration decoration,
465                                 boolean isAjaxRequest)
466     {
467         List pageModes = new ArrayList();
468         
469         
470         try
471         {
472             if (mode.equals(PortletMode.HELP) || !state.equals(WindowState.NORMAL))
473             {
474                 // switch back to VIEW mode and NORMAL state.
475                 PortalURL portalURL = requestContext.getPortalURL();
476                 String action = requestContext.getResponse().encodeURL( (isAjaxRequest)
477                   ? portalURL.createNavigationalEncoding(window, PortletMode.VIEW, WindowState.NORMAL)                          
478                   : portalURL.createPortletURL(window, PortletMode.VIEW, WindowState.NORMAL, portalURL.isSecure()).toString() );
479                 String actionName = PortletMode.VIEW.toString();
480                 pageModes.add(new DecoratorAction(actionName, requestContext.getLocale(), decoration.getResource("images/" + actionName + ".gif"),action,DecoratorActionTemplate.ACTION_TYPE_MODE));
481             }
482             else if ( pageActionAccess.isEditAllowed() )
483             {
484                 String targetMode = pageActionAccess.isEditing() ? PortletMode.VIEW.toString() : PortletMode.EDIT.toString();
485                 PortalURL portalURL = requestContext.getPortalURL();
486                 HashMap parameters = new HashMap();
487                 String[] paramValues = new String[]{targetMode};
488                 parameters.put("pageMode",paramValues);
489 
490                 // Use an ActionURL to set the oposite pageMode and always set VIEW mode and state NORMAL 
491                 String action = requestContext.getResponse().encodeURL( (isAjaxRequest)
492                     ? portalURL.createNavigationalEncoding(window, parameters, PortletMode.VIEW, WindowState.NORMAL, true)                                              
493                     : portalURL.createPortletURL(window, parameters, PortletMode.VIEW, WindowState.NORMAL, true, portalURL.isSecure()).toString() );
494                 pageModes.add(new DecoratorAction(targetMode, requestContext.getLocale(), decoration.getResource("images/" + targetMode + ".gif"), action,DecoratorActionTemplate.ACTION_TYPE_MODE));
495                 
496                 //window.getPortletEntity().getPortletDefinition().getInitParameterSet().get( "xxxx" );
497                 
498                 if (content.supportsPortletMode(PortletMode.HELP))
499                 {
500                     if ( pageActionAccess.isEditing() )
501                     {
502                         // force it back to VIEW mode first with an ActionURL, as well as setting HELP mode and MAXIMIZED state
503                         paramValues[0] = PortletMode.VIEW.toString();
504                         action = requestContext.getResponse().encodeURL( (isAjaxRequest)
505                             ? portalURL.createNavigationalEncoding(window, parameters, PortletMode.HELP, WindowState.MAXIMIZED, true)                                                  
506                             : portalURL.createPortletURL(window, parameters, PortletMode.HELP, WindowState.MAXIMIZED, true, portalURL.isSecure()).toString() );
507                     }
508                     else
509                     {
510                         // switch to mode HELP and state MAXIMIZED
511                         action = requestContext.getResponse().encodeURL( (isAjaxRequest)
512                             ? portalURL.createNavigationalEncoding(window, PortletMode.HELP, WindowState.MAXIMIZED)                        
513                             : portalURL.createPortletURL(window,PortletMode.HELP, WindowState.MAXIMIZED, portalURL.isSecure()).toString() );
514                     }
515                     String actionName = PortletMode.HELP.toString();
516                     pageModes.add(new DecoratorAction(actionName, requestContext.getLocale(), decoration.getResource("images/" + actionName + ".gif"), action,DecoratorActionTemplate.ACTION_TYPE_MODE));
517                 }
518             }
519         }
520         catch (Exception e)
521         {
522             log.warn("Unable to initalize PageLayout actions", e);
523             pageModes = null;
524         }
525         
526         return pageModes;
527     }  
528     
529     /***
530      * Intializes all fragments with there decorations and portlet modes 
531      * and winodw states.
532      * 
533      * 
534      * @param requestContext RequestContext of the current portal request.
535      * @param theme
536      * @param fragment
537      * @param pageActionAccess
538      */
539     protected void initDepthFragments(RequestContext requestContext, 
540                                       Theme theme, 
541                                       ContentFragment fragment, 
542                                       PageActionAccess pageActionAccess,
543                                       boolean isAjaxRequest,
544                                       List collectFragments )
545     {
546         final List contentFragments = fragment.getContentFragments();
547         
548         if(contentFragments != null && contentFragments.size() > 0)
549         {
550             Iterator itr = contentFragments.iterator();
551             while(itr.hasNext())
552             {
553                 ContentFragment aFragment = (ContentFragment) itr.next();
554                 initDepthFragments(requestContext, theme, aFragment, pageActionAccess, isAjaxRequest, collectFragments);
555             }
556         }
557         
558         if ( initFragment(requestContext, theme, fragment, pageActionAccess, isAjaxRequest) )
559         {
560             if ( collectFragments != null )
561             {
562                 collectFragments.add( fragment );
563             }
564         }
565     }
566 
567     protected boolean initFragment(RequestContext requestContext, 
568                                    Theme theme, 
569                                    ContentFragment fragment, 
570                                    PageActionAccess pageActionAccess,
571                                    boolean isAjaxRequest)
572     {
573         boolean fragmentSupportsActions = false;
574         try
575         {
576             Decoration decoration = theme.getDecoration(fragment);
577             fragment.setDecoration(decoration);
578             fragmentSupportsActions = initActionsForFragment(requestContext, fragment, pageActionAccess, decoration, isAjaxRequest);
579         }
580         catch (Exception e)
581         {
582             log.warn("Unable to initalize actions for fragment "+fragment.getId(), e);
583         }
584         return fragmentSupportsActions;
585     }
586 
587     /***
588      * Reintializes all fragments with there decorations and portlet modes 
589      * and winodw states after theme is restored from cache.
590      * 
591      * @param requestContext RequestContext of the current portal request.
592      * @param theme
593      * @param fragment
594      * @param pageActionAccess
595      * @param isAjaxRequest
596      * @param validator
597      * @param pathResolverCache
598      */
599     protected void initDepthFragmentDecorations(RequestContext requestContext,
600                                                 Theme theme,
601                                                 ContentFragment fragment, 
602                                                 PageActionAccess pageActionAccess,
603                                                 boolean isAjaxRequest,
604                                                 ResourceValidator validator,
605                                                 PathResolverCache pathResolverCache,
606                                                 boolean reloadActionList)
607     {
608         final List contentFragments = fragment.getContentFragments();
609         
610         if(contentFragments != null && contentFragments.size() > 0)
611         {
612             Iterator itr = contentFragments.iterator();
613             while(itr.hasNext())
614             {
615                 ContentFragment aFragment = (ContentFragment) itr.next();
616                 initDepthFragmentDecorations(requestContext, theme, aFragment,
617                                              pageActionAccess, isAjaxRequest,
618                                              validator, pathResolverCache, reloadActionList);
619             }
620         }
621 
622         try 
623         {
624             // PageTheme::getDecoration retrieves cached decoration only.
625             Decoration decoration = theme.getDecoration(fragment);
626             // re-init to set transient memebers.
627             Properties config = ((DecorationFactoryImpl) decorationFactory).getConfiguration(decoration.getName(), fragment.getType());
628             ((BaseDecoration) decoration).init(config, validator, pathResolverCache);
629             // fragment is newly created on every request, so reset decoration for fragment.
630             fragment.setDecoration(decoration);
631             
632             if (reloadActionList)
633             {
634                 initActionsForFragment(requestContext, fragment, pageActionAccess, decoration, isAjaxRequest);
635             }
636         }
637         catch (Exception e)
638         {
639             log.warn("Unable to initalize actions for fragment "+fragment.getId(), e);
640         }
641     }
642     
643     public void setMaximizeOnEdit(boolean maxOnEdit)
644     {
645         this.maxOnEdit = maxOnEdit;
646         this.defaultDecoratorActionsFactory.setMaximizeOnEdit(maxOnEdit);
647     }
648     
649     public boolean getMaximizeOnEdit()
650     {
651         return this.maxOnEdit;
652     }
653     
654     public void setMaximizeOnConfig(boolean maxOnConfig)
655     {
656         this.maxOnConfig = maxOnConfig;
657         this.defaultDecoratorActionsFactory.setMaximizeOnConfig(maxOnConfig);
658     }
659     
660     public boolean getMaximizeOnConfig()
661     {
662         return this.maxOnConfig;
663     }
664     
665     public void setMaximizeOnEditDefaults(boolean maxOnEditDefaults)
666     {
667         this.maxOnEditDefaults = maxOnEditDefaults;
668         this.defaultDecoratorActionsFactory.setMaximizeOnEditDefaults(maxOnEditDefaults);
669     }
670     
671     public boolean getMaximizeOnEditDefaults()
672     {
673         return this.maxOnEditDefaults;
674     }
675     
676     public void setAutoSwitchingToEditDefaultsModes(boolean autoSwitchingToEditDefaultsModes)
677     {
678         this.autoSwitchingToEditDefaultsModes = autoSwitchingToEditDefaultsModes;
679     }
680     
681     public boolean getAutoSwitchingToEditDefaultsModes()
682     {
683         return this.autoSwitchingToEditDefaultsModes;
684     }
685     
686     public void setAutoSwitchingForConfigMode(boolean autoSwitchingForConfigMode)
687     {
688         this.autoSwitchingForConfigMode = autoSwitchingForConfigMode;
689     }
690     
691     public boolean getAutoSwitchingForConfigMode()
692     {
693         return this.autoSwitchingForConfigMode;
694     }
695     
696     private boolean isAutoSwitchableCustomMode(ContentTypeSet content, PortletMode customMode)
697     {
698         if (this.autoSwitchingForConfigMode && JetspeedActions.CONFIG_MODE.equals(customMode))
699         {
700             return true;
701         }
702         
703         if (this.autoSwitchingToEditDefaultsModes)
704         {
705             if (content.supportsPortletMode(PortletMode.EDIT) && JetspeedActions.EDIT_DEFAULTS_MODE.equals(customMode))
706             {
707                 return true;
708             }
709         }
710         
711         return false;
712     }
713 }