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