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.aggregator.impl;
18  
19  import java.io.IOException;
20  import java.util.Iterator;
21  import java.util.Map;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  
27  import javax.portlet.Portlet;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  
32  import org.apache.jetspeed.aggregator.FailedToRenderFragmentException;
33  import org.apache.jetspeed.aggregator.PageAggregator;
34  import org.apache.jetspeed.container.state.NavigationalState;
35  import org.apache.jetspeed.container.url.BasePortalURL;
36  import org.apache.jetspeed.container.window.PortletWindowAccessor;
37  import org.apache.jetspeed.decoration.DecorationFactory;
38  import org.apache.jetspeed.exception.JetspeedException;
39  import org.apache.jetspeed.factory.PortletFactory;
40  import org.apache.jetspeed.headerresource.HeaderResource;
41  import org.apache.jetspeed.headerresource.HeaderResourceFactory;
42  import org.apache.jetspeed.headerresource.HeaderResourceLib;
43  import org.apache.jetspeed.om.common.portlet.PortletApplication;
44  import org.apache.jetspeed.om.page.ContentFragment;
45  import org.apache.jetspeed.om.page.ContentPage;
46  import org.apache.jetspeed.portlet.PortletHeaderRequest;
47  import org.apache.jetspeed.portlet.PortletHeaderResponse;
48  import org.apache.jetspeed.portlet.SupportsHeaderPhase;
49  import org.apache.jetspeed.request.RequestContext;
50  import org.apache.jetspeed.PortalReservedParameters;
51  import org.apache.pluto.om.portlet.PortletDefinition;
52  import org.apache.pluto.om.window.PortletWindow;
53  
54  /***
55   * HeaderAggregator builds the content required to render a page of portlets.
56   * 
57   * @author <a href="mailto:raphael@apache.org">Rapha?l Luta </a>
58   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
59   * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
60   * @version $Id: HeaderAggregatorImpl.java 359125 2005-12-26 23:16:39Z rwatler $
61   */
62  public class HeaderAggregatorImpl implements PageAggregator
63  {
64      protected final static Log log = LogFactory.getLog( HeaderAggregatorImpl.class );
65      protected final static String EOL = "\r\n";   // html eol
66  
67      private PortletFactory factory;
68      private PortletWindowAccessor windowAccessor;
69      private HeaderResourceFactory headerResourceFactory;
70      private DecorationFactory decorationFactory;
71      
72      private boolean isDesktop;
73      
74      private Map headerConfiguration;
75      private Map headerResourceRegistry;
76      private Map headerDynamicConfigurationDefault;
77      private Map headerNamedResourcesDefault;
78      private Map headerNamedResourcesAddedFragmentsDefault;
79      
80      /*** base portal URL to override default URL server info from servlet */
81      private BasePortalURL baseUrlAccess = null;
82      
83      
84      public HeaderAggregatorImpl( PortletFactory factory,
85                                   PortletWindowAccessor windowAccessor,
86                                   HeaderResourceFactory headerResourceFactory,
87                                   boolean isDesktop,
88                                   Map headerConfiguration,
89                                   Map headerResourceRegistry,
90                                   DecorationFactory decorationFactory )
91      {
92          this( factory, windowAccessor, headerResourceFactory, isDesktop, headerConfiguration, headerResourceRegistry, decorationFactory, null );
93      }
94      
95      public HeaderAggregatorImpl( PortletFactory factory,
96                                   PortletWindowAccessor windowAccessor,
97                                   HeaderResourceFactory headerResourceFactory,
98                                   boolean isDesktop,
99                                   Map headerConfiguration,
100                                  Map headerResourceRegistry,
101                                  DecorationFactory decorationFactory,
102                                  BasePortalURL baseUrlAccess )
103     {
104         this.factory = factory;
105         this.windowAccessor = windowAccessor;
106         this.headerResourceFactory = headerResourceFactory;
107         this.isDesktop = isDesktop;
108         this.baseUrlAccess = baseUrlAccess;
109         this.decorationFactory = decorationFactory;
110         initializeHeaderConfiguration( headerConfiguration, headerResourceRegistry );   
111     }
112     
113     /***
114      * Initialize header configuration, making immutable copies of the data structures and 
115      * compiling as much finished static header content as possible (to minimize repetitive work per request)
116      */
117     private void initializeHeaderConfiguration( Map headerConfigArg, Map headerRsrcRegistryArg )
118     {
119         this.headerConfiguration = null;
120         this.headerResourceRegistry = null;
121         this.headerDynamicConfigurationDefault = null;
122         this.headerNamedResourcesDefault = null;
123         this.headerNamedResourcesAddedFragmentsDefault = null;
124         
125         if ( headerConfigArg != null && headerConfigArg.size() > 0 )
126         {
127             // attempt to make safe immutable copy of headerConfigArg
128             HashMap headerConfig = new HashMap();
129             Iterator headerConfigEntryIter = headerConfigArg.entrySet().iterator();
130             while ( headerConfigEntryIter.hasNext() )
131             {
132                 Map.Entry headerConfigEntry = (Map.Entry)headerConfigEntryIter.next();
133                 Object headerConfigKey = headerConfigEntry.getKey();
134                 Object headerConfigVal = headerConfigEntry.getValue();
135                 if ( headerConfigVal instanceof Map )
136                 {
137                     headerConfig.put( headerConfigKey, Collections.unmodifiableMap( new HashMap( (Map)headerConfigVal ) ) );
138                 }
139                 else if ( headerConfigVal instanceof List )
140                 {
141                     headerConfig.put( headerConfigKey, Collections.unmodifiableList( new ArrayList( (List)headerConfigVal ) ) );
142                 }
143                 else
144                 {
145                     headerConfig.put( headerConfigKey, headerConfigVal );
146                 }
147             }
148             this.headerConfiguration = Collections.unmodifiableMap( headerConfig );
149             
150             // make modifiable copy of headerRsrcRegistryArg - is made immutable at end of initializeHeaderConfiguration()
151             Map headerRsrcRegistry = null;
152             if ( headerRsrcRegistryArg != null && headerRsrcRegistryArg.size() > 0 )
153             {
154                 headerRsrcRegistry = new HashMap( headerRsrcRegistryArg );
155                 // leave modifiable during initializeHeaderConfigurationDefaults() protocol
156                 //    (so that entries can be removed - possibly leading to an empty map which will save a bunch of gratuitous lookups)
157             }
158             else
159             {
160                 headerRsrcRegistry = new HashMap();
161             }
162             this.headerResourceRegistry = headerRsrcRegistry;   
163 
164             HashMap namedResourcesDefault = new HashMap();
165             HashMap namedResourcesAddedFragmentsDefault = new HashMap();
166             
167             Map dynamicConfigurationDefault = initializeHeaderConfigurationDefaults( namedResourcesDefault, namedResourcesAddedFragmentsDefault );
168             if ( dynamicConfigurationDefault != null )
169                 this.headerDynamicConfigurationDefault = Collections.unmodifiableMap( dynamicConfigurationDefault );
170             
171             this.headerNamedResourcesDefault = Collections.unmodifiableMap( namedResourcesDefault );
172             this.headerNamedResourcesAddedFragmentsDefault = Collections.unmodifiableMap( namedResourcesAddedFragmentsDefault );
173             
174             this.headerResourceRegistry = null;
175             if ( headerRsrcRegistry != null && headerRsrcRegistry.size() > 0 )
176             {
177                 this.headerResourceRegistry = Collections.unmodifiableMap( headerRsrcRegistry );
178             }
179         }
180     }
181 
182     /***
183      * Initialize dynamic-header-configuration and call initializeHeaderConfigurationEntryDefaults() for
184      * each key in headerConfiguration Map, allowing for each to add resources and settings to:
185      * headerNamedResourcesDefault, headerNamedResourcesAddedFragmentsDefault and headerDynamicConfigurationDefault
186      * 
187      * If no specific handler is defined for a headerConfiguration key, the entry is copied to headerDynamicConfigurationDefault
188      * otherwise the handler is responsible for adding information to headerDynamicConfigurationDefault
189      * 
190      * headerConfiguration handlers are currently defined for the headerConfiguration keys:
191      *    "header.order"         - HeaderResource.HEADER_CONFIG_ORDER
192      *    "header.types"         - HeaderResource.HEADER_CONFIG_TYPES
193      *    "header.requiredflag"  - HeaderResource.HEADER_CONFIG_REQUIREDFLAG
194      *    "dojo"                 - HeaderResource.HEADER_CONFIG_DOJO
195      *    "desktop"              - HeaderResource.HEADER_CONFIG_DESKTOP
196      */
197     protected Map initializeHeaderConfigurationDefaults( HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault )
198     {
199         if ( this.headerConfiguration == null )
200         {
201             return null;
202         }
203         
204         HashMap headerDynamicConfigurationDefault = new HashMap();
205         
206         initializeHeaderOrderConfigurationDefaults( namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
207 
208         // setting header.basetag type - without adding it to order
209         setNamedHeaderResourceProperties( HeaderResource.HEADER_SECTION_BASE_TAG, HeaderResource.HEADER_TYPE_BASE_TAG, null, headerDynamicConfigurationDefault );
210         
211         Iterator hConfigEntryIter = this.headerConfiguration.entrySet().iterator();
212         while ( hConfigEntryIter.hasNext() )
213         {
214             Map.Entry hConfigEntry = (Map.Entry)hConfigEntryIter.next();
215             Object hConfigKey = hConfigEntry.getKey();
216             Object hConfigVal = hConfigEntry.getValue();
217             
218             if ( ! initializeHeaderConfigurationEntryDefaults( hConfigKey, hConfigVal, namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault ) )
219             {
220                 if ( hConfigVal instanceof Map )
221                 {
222                     headerDynamicConfigurationDefault.put( hConfigKey, Collections.unmodifiableMap( new HashMap( (Map)hConfigVal ) ) );
223                 }
224                 else if ( hConfigVal instanceof List )
225                 {
226                     headerDynamicConfigurationDefault.put( hConfigKey, Collections.unmodifiableList( new ArrayList( (List)hConfigVal ) ) );
227                 }
228                 else
229                 {
230                     headerDynamicConfigurationDefault.put( hConfigKey, hConfigVal );
231                 }
232             }
233         }
234         initializeMissingHeaderConfigurationEntryDefaults( namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
235         
236         postinitializeHeaderOrderConfigurationDefaults( headerDynamicConfigurationDefault );
237         
238         return headerDynamicConfigurationDefault;
239     }
240     
241     protected void initializeHeaderOrderConfigurationDefaults( HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault, HashMap headerDynamicConfigurationDefault )
242     {
243         if ( this.headerConfiguration != null )
244         {
245             List headerOrderConfigList = (List)this.headerConfiguration.get( HeaderResource.HEADER_CONFIG_ORDER );
246             if ( headerOrderConfigList != null && headerOrderConfigList.size() > 0 )
247             {
248                 ArrayList headerOrderList = new ArrayList();
249                 Map headerNames = new HashMap();
250                 Iterator headerOrderListIter = headerOrderConfigList.iterator();
251                 while ( headerOrderListIter.hasNext() )
252                 {
253                     Object headerNameObj = headerOrderListIter.next();
254                     if ( headerNameObj != null )
255                     {
256                         String headerName = headerNameObj.toString();
257                         if ( headerName != null && headerName.length() > 0 )
258                         {
259                             headerOrderList.add( headerName );
260                             headerNames.put( headerName, Boolean.TRUE );
261                         }
262                     }
263                 }
264                 // add modifiable structures at this point - so that later initialization steps can manipulate the defaults
265                 // needs to be made unmodifiable at end of processing by calling postinitializeHeaderOrderConfigurationDefaults()
266                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_ORDER, headerOrderList );
267                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_INTERNAL_INCLUDED_NAMES, headerNames );
268             }
269             
270             Map headerTypes = null;
271             Map headerTypesConfig = (Map)this.headerConfiguration.get( HeaderResource.HEADER_CONFIG_TYPES );
272             if ( headerTypesConfig != null && headerTypesConfig.size() > 0 )
273             {
274                 headerTypes = new HashMap();
275                 Iterator headerTypesConfigIter = headerTypesConfig.entrySet().iterator();
276                 while ( headerTypesConfigIter.hasNext() )
277                 {
278                     Map.Entry headerTypeEntry = (Map.Entry)headerTypesConfigIter.next();
279                     Object headerNameObj = headerTypeEntry.getKey();
280                     Object headerTypeObj = headerTypeEntry.getValue();
281                     if ( headerNameObj != null && headerTypeObj != null )
282                     {
283                         String headerName = headerNameObj.toString();
284                         int headerTypeId = HeaderResourceLib.getHeaderTypeId( headerTypeObj.toString() );
285                         if ( headerName != null )
286                         {
287                             if ( headerTypeId >= 0 )
288                             {
289                                 headerTypes.put( headerName, new Object[] { new Integer( headerTypeId ), null } );
290                             }
291                             else
292                             {
293                                 log.error( "HeaderAggregatorImpl.initializeHeaderOrderConfigurationDefaults() ignoring specification of unknown header section type; header-section-name=" + headerName + " header-section-type=" + headerTypeObj.toString() );
294                             }
295                         }
296                     }
297                 }
298             }
299             
300             Map headerRequiredFlagConfig = (Map)this.headerConfiguration.get( HeaderResource.HEADER_CONFIG_REQUIREDFLAG );
301             if ( headerRequiredFlagConfig != null && headerRequiredFlagConfig.size() > 0 )
302             {
303                 if ( headerTypes == null )
304                 {
305                     headerTypes = new HashMap();
306                 }
307                 Iterator headerRequiredFlagConfigIter = headerRequiredFlagConfig.entrySet().iterator();
308                 while ( headerRequiredFlagConfigIter.hasNext() )
309                 {
310                     Map.Entry headerRequiredFlagEntry = (Map.Entry)headerRequiredFlagConfigIter.next();
311                     Object headerNameObj = headerRequiredFlagEntry.getKey();
312                     Object headerReqFlagObj = headerRequiredFlagEntry.getValue();
313                     if ( headerNameObj != null && headerReqFlagObj != null )
314                     {
315                         String headerName = headerNameObj.toString();
316                         String headerReqFlag = headerReqFlagObj.toString();
317                         if ( headerName != null && headerName.length() > 0 && headerReqFlag != null )
318                         {
319                             Object[] headerTypePair = (Object[])headerTypes.get( headerName );
320                             if ( headerTypePair != null )
321                             {
322                                 headerTypePair[1] = headerReqFlag;
323                             }
324                             else
325                             {
326                                 headerTypePair = new Object[] { null, headerReqFlag };
327                                 headerTypes.put( headerName, headerTypePair );
328                             }
329                         }
330                     }
331                 }
332             }
333             if ( headerTypes != null && headerTypes.size() > 0 )
334             {
335                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_TYPES, headerTypes );
336             }
337         }
338     }
339     protected void postinitializeHeaderOrderConfigurationDefaults( HashMap headerDynamicConfigurationDefault )
340     {
341         if ( headerDynamicConfigurationDefault != null )
342         {
343             Map headerNames = (Map)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_INTERNAL_INCLUDED_NAMES );
344             if ( headerNames != null )
345             {
346                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_INTERNAL_INCLUDED_NAMES, Collections.unmodifiableMap( headerNames ) );
347             }
348             Map headerTypes = (Map)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_CONFIG_TYPES );
349             if ( headerTypes != null )
350             {
351                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_TYPES, Collections.unmodifiableMap( headerTypes ) );
352             }
353             List headerOrderList = (List)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_CONFIG_ORDER );
354             if ( headerOrderList != null )
355             {
356                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_ORDER, Collections.unmodifiableList( headerOrderList ) );
357             }
358         }
359     }
360     
361     /***
362      * Intended as derived class hook into header configuration process
363      * 
364      * @return true if headerConfigKey has been processed or false if default processing should occur
365      */
366     protected boolean initializeHeaderConfigurationEntryDefaults( Object headerConfigKey, Object headerConfigValue, HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault, HashMap headerDynamicConfigurationDefault )
367     {
368         if ( headerConfigKey.equals( HeaderResource.HEADER_CONFIG_ORDER ) || headerConfigKey.equals( HeaderResource.HEADER_CONFIG_TYPES ) || headerConfigKey.equals( HeaderResource.HEADER_CONFIG_REQUIREDFLAG ) )
369         {
370             // do nothing - processed earlier with call to initializeHeaderOrderConfigurationDefaults()
371             return true;
372         }
373         else if ( headerConfigKey.equals( HeaderResource.HEADER_CONFIG_DOJO ) )
374         {
375             initializeDojoHeaderConfigurationDefaults( (Map)headerConfigValue, namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
376             return true;
377         }
378         else if ( headerConfigKey.equals( HeaderResource.HEADER_CONFIG_DESKTOP ) )
379         {
380             initializeDesktopHeaderConfigurationDefaults( (Map)headerConfigValue, namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
381             return true;
382         }
383         return false;
384     }
385     
386     protected void initializeMissingHeaderConfigurationEntryDefaults( HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault, HashMap headerDynamicConfigurationDefault )
387     {
388         if ( isDesktop() )
389         {
390             if ( this.headerConfiguration.get( HeaderResource.HEADER_CONFIG_DOJO ) == null )
391             {
392                 initializeDojoHeaderConfigurationDefaults( null, namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
393             }
394             if ( this.headerConfiguration.get( HeaderResource.HEADER_CONFIG_DESKTOP ) == null )
395             {
396                 initializeDesktopHeaderConfigurationDefaults( null, namedResourcesDefault, namedResourcesAddedFragmentsDefault, headerDynamicConfigurationDefault );
397             }
398         }
399     }
400     
401     protected void registerAndOrderNamedHeaderResource( String headerName, String headerType, String headerReqFlag, Map headerDynamicConfigurationDefault )
402     {
403         orderNamedHeaderResource( headerName, headerDynamicConfigurationDefault );
404         setNamedHeaderResourceProperties( headerName, headerType, headerReqFlag, headerDynamicConfigurationDefault );
405     }
406     
407     protected void orderNamedHeaderResource( String headerName, Map headerDynamicConfigurationDefault )
408     {
409         if ( headerName != null )
410         {
411             Map headerNames = (Map)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_INTERNAL_INCLUDED_NAMES );
412             if ( headerNames == null )
413             {
414                 headerNames = new HashMap();
415                 headerDynamicConfigurationDefault.put( HeaderResource.HEADER_INTERNAL_INCLUDED_NAMES, headerNames );
416             }
417             
418             Object headerNamesVal = headerNames.get( headerName );
419             if ( headerNamesVal == null )
420             {
421                 List headerOrderList = (List)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_CONFIG_ORDER );
422                 if ( headerOrderList == null )
423                 {
424                     headerOrderList = new ArrayList();
425                     headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_ORDER, headerOrderList );
426                 }
427                 
428                 headerOrderList.add( headerName );
429                 headerNames.put( headerName, Boolean.TRUE );
430             }
431         }
432     }
433     
434     protected void setNamedHeaderResourceProperties( String headerName, String headerType, String headerReqFlag, Map headerDynamicConfigurationDefault )
435     {
436         if ( headerName != null )
437         {
438             int headerTypeId = HeaderResourceLib.getHeaderTypeId( headerType );
439             
440             boolean headerRefFlagSpecified = ( headerReqFlag != null && headerReqFlag.length() > 0 );
441             if ( headerTypeId < 0 && ! headerRefFlagSpecified )
442             {
443                 log.error( "HeaderAggregatorImpl.registerAndOrderNamedHeaderResource() ignoring specification of unknown header section type; header-section-name=" + headerName + " header-section-type=" + headerType );
444             }
445             
446             if ( ( headerTypeId >= 0 ) || headerRefFlagSpecified )
447             {
448                 Map headerTypes = (Map)headerDynamicConfigurationDefault.get( HeaderResource.HEADER_CONFIG_TYPES );
449                 if ( headerTypes == null )
450                 {
451                     headerTypes = new HashMap();
452                     headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_TYPES, headerTypes );
453                 }
454                 
455                 Object[] headerTypePair = (Object[])headerTypes.get( headerName );
456                 if ( headerTypePair == null )
457                 {
458                     headerTypePair = new Object[] { null, null };
459                     headerTypes.put( headerName, headerTypePair );
460                 }
461                 if ( headerTypePair[0] == null && headerTypeId >= 0 )
462                 {   // change only if value from configuration is null
463                     headerTypePair[0] = new Integer( headerTypeId );
464                 }
465                 if ( headerTypePair[1] == null && headerReqFlag != null && headerReqFlag.length() > 0 )
466                 {   // change only if value from configuration is null
467                     headerTypePair[1] = headerReqFlag;
468                 }
469             }
470         }
471     }
472     
473     protected boolean canAddHeaderNamedResourceFragment( String headerFragmentName, HashMap namedResourcesAddedFragmentsDefault, String[] registryContent )
474     {
475         if ( headerFragmentName != null && ! namedResourcesAddedFragmentsDefault.containsKey( headerFragmentName ) )
476         {
477             namedResourcesAddedFragmentsDefault.put( headerFragmentName, Boolean.TRUE );
478             if ( registryContent != null )
479             {
480                 String registryContentVal = (String)this.headerResourceRegistry.get( headerFragmentName );
481                 registryContent[0] = registryContentVal;
482                 if ( registryContentVal != null )
483                 {
484                     this.headerResourceRegistry.remove( headerFragmentName );
485                 }
486             }
487             return true;
488         }
489         if ( registryContent != null )
490         {
491             registryContent[0] = null;
492         }
493         return false;
494     }
495         
496     protected void initializeDesktopHeaderConfigurationDefaults( Map desktopConfigMap, HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault, HashMap headerDynamicConfigurationDefault )
497     {
498         if ( desktopConfigMap == null )
499         {
500             desktopConfigMap = new HashMap();
501         }
502         
503         StringBuffer desktopDojoConfigContent = new StringBuffer();
504         
505         String layoutDecorationDefaultName = HeaderResource.HEADER_CONFIG_DESKTOP_LAYOUT_DECORATION_DEFAULT;
506         String layoutDecoration = (String)desktopConfigMap.get( layoutDecorationDefaultName );
507         if ( layoutDecoration != null && layoutDecoration.length() > 0 )
508         {
509             decorationFactory.setDefaultDesktopLayoutDecoration( layoutDecoration );
510         }
511         
512         String portletDecorationDefaultName = HeaderResource.HEADER_CONFIG_DESKTOP_PORTLET_DECORATION_DEFAULT;
513         String portletDecoration = (String)desktopConfigMap.get( portletDecorationDefaultName );
514         if ( portletDecoration == null || portletDecoration.length() == 0 )
515         {
516             portletDecoration = decorationFactory.getDefaultDesktopPortletDecoration();
517         }
518         if ( portletDecoration != null && portletDecoration.length() > 0 )
519         {
520             if ( canAddHeaderNamedResourceFragment( portletDecorationDefaultName, namedResourcesAddedFragmentsDefault, null ) )
521             {
522                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowDecoration = \"" ).append( portletDecoration ).append( "\";" ).append( EOL );
523             }
524             decorationFactory.setDefaultDesktopPortletDecoration( portletDecoration );
525         }
526         
527         String desktopPageAjaxNavName = HeaderResource.HEADER_CONFIG_DESKTOP_PAGE_AJAXNAVIGATION;
528         String desktopPageAjaxNav = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( desktopPageAjaxNavName ) );
529         if ( desktopPageAjaxNav != null && canAddHeaderNamedResourceFragment( desktopPageAjaxNavName, namedResourcesAddedFragmentsDefault, null ) )
530         {
531             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".ajaxPageNavigation = " ).append( desktopPageAjaxNav ).append( ";" ).append( EOL );
532         }
533         
534         String desktopWindowTilingName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_TILING;
535         String desktopWindowTiling = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( desktopWindowTilingName ) );
536         if ( desktopWindowTiling != null && canAddHeaderNamedResourceFragment( desktopWindowTilingName, namedResourcesAddedFragmentsDefault, null ) )
537         {
538             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowTiling = " ).append( desktopWindowTiling ).append( ";" ).append( EOL );
539         }
540         
541         String desktopWindowHeightExpandName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_HEIGHT_EXPAND;
542         String desktopWindowHeightExpand = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( desktopWindowHeightExpandName ) );
543         if ( desktopWindowHeightExpand != null && canAddHeaderNamedResourceFragment( desktopWindowHeightExpandName, namedResourcesAddedFragmentsDefault, null ) )
544         {
545             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowHeightExpand = " ).append( desktopWindowHeightExpand ).append( ";" ).append( EOL );
546         }
547 
548         String desktopWindowHeightName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_HEIGHT;
549         String desktopWindowHeight = HeaderResourceLib.makeJSONInteger( desktopConfigMap.get( desktopWindowHeightName ), true );
550         if ( desktopWindowHeight != null && canAddHeaderNamedResourceFragment( desktopWindowHeightName, namedResourcesAddedFragmentsDefault, null ) )
551         {
552             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowHeight = " ).append( desktopWindowHeight ).append( ";" ).append( EOL );
553         }
554         
555         String desktopWindowWidthName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_WIDTH;
556         String desktopWindowWidth = HeaderResourceLib.makeJSONInteger( desktopConfigMap.get( desktopWindowWidthName ), true );
557         if ( desktopWindowWidth != null && canAddHeaderNamedResourceFragment( desktopWindowWidthName, namedResourcesAddedFragmentsDefault, null ) )
558         {
559             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowWidth = " ).append( desktopWindowWidth ).append( ";" ).append( EOL );
560         }
561         
562         List actionList = new ArrayList();
563         
564         String windowActionButtonOrderName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_BUTTON_ORDER;
565         String actionButtonOrderContent = HeaderResourceLib.makeJSONStringArray( (List)desktopConfigMap.get( windowActionButtonOrderName ), actionList );
566         if ( actionButtonOrderContent != null && actionButtonOrderContent.length() > 0 )
567         {
568             if ( canAddHeaderNamedResourceFragment( windowActionButtonOrderName, namedResourcesAddedFragmentsDefault, null ) )
569             {
570                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionButtonOrder = " ).append( actionButtonOrderContent ).append( ";" ).append( EOL );
571             }
572         }
573         
574         String windowActionNoImageName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_NOIMAGE;
575         String actionNoImageContent = HeaderResourceLib.makeJSONStringArray( (List)desktopConfigMap.get( windowActionNoImageName ), actionList );
576         if ( actionNoImageContent != null && actionNoImageContent.length() > 0 )
577         {
578             if ( canAddHeaderNamedResourceFragment( windowActionNoImageName, namedResourcesAddedFragmentsDefault, null ) )
579             {
580                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionNoImage = " ).append( actionNoImageContent ).append( ";" ).append( EOL );
581             }
582         }
583         
584         String windowActionMenuOrderName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_MENU_ORDER;
585         String actionMenuOrderContent = HeaderResourceLib.makeJSONStringArray( (List)desktopConfigMap.get( windowActionMenuOrderName ), actionList );
586         if ( actionMenuOrderContent != null && actionMenuOrderContent.length() > 0 )
587         {
588             if ( canAddHeaderNamedResourceFragment( windowActionMenuOrderName, namedResourcesAddedFragmentsDefault, null ) )
589             {
590                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionMenuOrder = " ).append( actionMenuOrderContent ).append( ";" ).append( EOL );
591             }
592         }
593 
594         headerDynamicConfigurationDefault.put( HeaderResource.HEADER_INTERNAL_CONFIG_DESKTOP_WINDOW_ACTION, actionList );
595 
596 
597         String windowActionButtonHideName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_BUTTON_HIDE;
598         String windowActionButtonHide = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( windowActionButtonHideName ) );
599         if ( windowActionButtonHide != null && canAddHeaderNamedResourceFragment( windowActionButtonHideName, namedResourcesAddedFragmentsDefault, null ) )
600         {
601             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionButtonHide = " ).append( windowActionButtonHide ).append( ";" ).append( EOL );
602         }
603         
604         String windowActionButtonTooltipName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_BUTTON_TOOLTIP;
605         String windowActionButtonTooltip = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( windowActionButtonTooltipName ) );
606         if ( windowActionButtonTooltip != null && canAddHeaderNamedResourceFragment( windowActionButtonTooltipName, namedResourcesAddedFragmentsDefault, null ) )
607         {
608             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionButtonTooltip = " ).append( windowActionButtonTooltip ).append( ";" ).append( EOL );
609         }
610 
611         String windowActionButtonMaxName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ACTION_BUTTON_MAX;
612         String windowActionButtonMax = HeaderResourceLib.makeJSONInteger( desktopConfigMap.get( windowActionButtonMaxName ), false );
613         if ( windowActionButtonMax != null && canAddHeaderNamedResourceFragment( windowActionButtonMaxName, namedResourcesAddedFragmentsDefault, null ) )
614         {
615             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowActionButtonMax = " ).append( windowActionButtonMax ).append( ";" ).append( EOL );
616         }
617         
618         String windowIconEnabledName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ICON_ENABLED;
619         String iconEnabledContent = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( windowIconEnabledName ) );
620         if ( iconEnabledContent != null && iconEnabledContent.length() > 0 )
621         {
622             if ( canAddHeaderNamedResourceFragment( windowIconEnabledName, namedResourcesAddedFragmentsDefault, null ) )
623             {
624                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowIconEnabled = " ).append( iconEnabledContent ).append( ";" ).append( EOL );
625             }
626         }
627         
628         String windowIconPathName = HeaderResource.HEADER_CONFIG_DESKTOP_WINDOW_ICON_PATH;
629         String iconPathContent = (String)desktopConfigMap.get( windowIconPathName );
630         if ( iconPathContent != null && iconPathContent.length() > 0 )
631         {
632             if ( canAddHeaderNamedResourceFragment( windowIconPathName, namedResourcesAddedFragmentsDefault, null ) )
633             {
634                 desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".windowIconPath = \"" ).append( iconPathContent ).append( "\";" ).append( EOL );
635             }
636         }
637         
638         String pageActionButtonTooltipName = HeaderResource.HEADER_CONFIG_DESKTOP_PAGE_ACTION_BUTTON_TOOLTIP;
639         String pageActionButtonTooltip = HeaderResourceLib.makeJSONBoolean( desktopConfigMap.get( pageActionButtonTooltipName ) );
640         if ( pageActionButtonTooltip != null && canAddHeaderNamedResourceFragment( pageActionButtonTooltipName, namedResourcesAddedFragmentsDefault, null ) )
641         {
642             desktopDojoConfigContent.append( "    " ).append( HeaderResource.HEADER_INTERNAL_DOJO_CONFIG_JETSPEED_VAR_NAME ).append( ".pageActionButtonTooltip = " ).append( pageActionButtonTooltip ).append( ";" ).append( EOL );
643         }
644 
645         if ( desktopDojoConfigContent.length() > 0 )
646         {
647             namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_CONFIG, desktopDojoConfigContent.toString() );
648         }
649         
650         StringBuffer desktopInitScript = new StringBuffer();
651         desktopInitScript.append( "    function doRender(bindArgs,portletEntityId) { " );
652         desktopInitScript.append( "jetspeed.doRender(bindArgs,portletEntityId); }" ).append( EOL );
653         desktopInitScript.append( "    function doAction(bindArgs,portletEntityId) { " );
654         desktopInitScript.append( "jetspeed.doAction(bindArgs,portletEntityId); }" ).append( EOL );
655         desktopInitScript.append( "    dojo.addOnLoad( jetspeed.initializeDesktop );" ).append( EOL );
656         if ( canAddHeaderNamedResourceFragment( "desktop.init", namedResourcesAddedFragmentsDefault, null ) )
657         {
658             namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DESKTOP_INIT, desktopInitScript.toString() );
659             setNamedHeaderResourceProperties( HeaderResource.HEADER_SECTION_DESKTOP_INIT, HeaderResource.HEADER_TYPE_SCRIPT_BLOCK_START, null, headerDynamicConfigurationDefault );
660         }
661     }
662     
663     /***
664      * Read dojo header configuration settings and compile dojo header resource defaults
665      */
666     protected void initializeDojoHeaderConfigurationDefaults( Map dojoConfigMap, HashMap namedResourcesDefault, HashMap namedResourcesAddedFragmentsDefault, HashMap headerDynamicConfigurationDefault )
667     {
668         if ( dojoConfigMap == null )
669         {
670             dojoConfigMap = new HashMap();
671         }
672         String[] registryContent = new String[] { null };
673         
674         // add dojo.enable and dojo.path to dynamic configuration
675         String dojoEnableName = HeaderResource.HEADER_CONFIG_DOJO_ENABLE;
676         Object dojoEnableObj = dojoConfigMap.get( dojoEnableName );
677         String dojoEnable = ( ( dojoEnableObj == null ) ? (String)null : dojoEnableObj.toString() );
678         if ( dojoEnable == null || ! dojoEnable.equals( "true" ) )
679         {
680             dojoEnable = "false";
681         }
682         headerDynamicConfigurationDefault.put( dojoEnableName, dojoEnable );
683         String dojoPath = (String)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_PATH );
684         if ( dojoPath == null || dojoPath.length() == 0 )
685         {
686             dojoPath = "/javascript/dojo/";
687         }
688         headerDynamicConfigurationDefault.put( HeaderResource.HEADER_CONFIG_DOJO_PATH, dojoPath );
689         
690         // dojo parameters - djConfig parameters
691         String dojoParamDebug = (String)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_PARAM_ISDEBUG );
692         String dojoParamDebugAtAllCosts = (String)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_PARAM_DEBUGALLCOSTS );
693         String dojoParamPreventBackBtnFix = (String)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_PARAM_PREVENT_BACKBUTTON_FIX );
694         String dojoParams = (String)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_PARAMS );
695         if ( dojoParamDebug != null || dojoParamDebugAtAllCosts != null || dojoParamPreventBackBtnFix != null || dojoParams != null )
696         {
697             StringBuffer dojoConfigContent = new StringBuffer();
698             boolean addedMembers = false;
699             if ( dojoParams != null && dojoParams.length() > 0 )
700             {
701                 dojoConfigContent.append( dojoParams );
702                 addedMembers = true;
703             }
704             if ( dojoParamDebug != null && dojoParamDebug.length() > 0 )
705             {
706                 if ( addedMembers )
707                 {
708                     dojoConfigContent.append( ", " );
709                 }
710                 dojoConfigContent.append( "isDebug: " ).append( dojoParamDebug ) ;
711                 addedMembers = true;
712             }
713             if ( dojoParamDebugAtAllCosts != null && dojoParamDebugAtAllCosts.length() > 0 )
714             {
715                 if ( addedMembers )
716                 {
717                     dojoConfigContent.append( ", " );
718                 }
719                 dojoConfigContent.append( "debugAtAllCosts: " ).append( dojoParamDebugAtAllCosts ) ;
720                 addedMembers = true;
721             }
722             if ( dojoParamPreventBackBtnFix != null && dojoParamPreventBackBtnFix.length() > 0 )
723             {
724                 if ( addedMembers )
725                 {
726                     dojoConfigContent.append( ", " );
727                 }
728                 dojoConfigContent.append( "preventBackButtonFix: " ).append( dojoParamPreventBackBtnFix ) ;
729                 addedMembers = true;
730             }
731             if ( addedMembers )
732             {
733                 dojoConfigContent.append( ", " );
734             }
735             dojoConfigContent.append( HeaderResource.HEADER_INTERNAL_JETSPEED_VAR_NAME ).append( ": {}" ) ;
736             addedMembers = true;
737             
738             if ( canAddHeaderNamedResourceFragment( HeaderResource.HEADER_CONFIG_DOJO_PARAMS, namedResourcesAddedFragmentsDefault, registryContent ) )
739             {
740                 String dojoParamContent = dojoConfigContent.toString();
741                 if ( registryContent[0] != null )
742                 {
743                     dojoParamContent = registryContent[0];
744                 }
745                 if ( dojoParamContent.length() > 0 )
746                 {
747                     namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_PARAMETERS, ( "    var djConfig = {" + dojoParamContent + "};" + EOL ) );
748                 }
749             }
750             registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_PARAMETERS, HeaderResource.HEADER_TYPE_SCRIPT_BLOCK_START, dojoEnableName, headerDynamicConfigurationDefault );
751         }
752         
753         // dojo preinit - for automatically added members to djConfig (eg. djConfig.baseScriptUri="...")
754         //    - adding to order only at this point
755         //    - if header contains content, generated content will not be added
756         registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_PREINIT, null, dojoEnableName, headerDynamicConfigurationDefault );
757         
758         // dojo config - for adding members to djConfig (eg. djConfig.parseWidgets=false)
759         //    - adding to order only at this point
760         registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_CONFIG, null, dojoEnableName, headerDynamicConfigurationDefault );
761         
762         // dojo init - script tag for dojo.js
763         //    - adding to order only at this point
764         //    - if header contains content, generated content will not be added
765         registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_INIT, HeaderResource.HEADER_TYPE_SCRIPT_TAG, dojoEnableName, headerDynamicConfigurationDefault );
766         
767         // dojo requires - core libraries
768         List dojoRequiresCore = (List)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_REQUIRES_CORE );
769         if ( dojoRequiresCore != null && dojoRequiresCore.size() > 0 )
770         {
771             StringBuffer dojoRequiresContent = new StringBuffer();
772             Iterator dojoRequiresCoreIter = dojoRequiresCore.iterator();
773             while ( dojoRequiresCoreIter.hasNext() )
774             {
775                 String dojoReq = (String)dojoRequiresCoreIter.next();
776                 if ( dojoReq != null && dojoReq.length() > 0 )
777                 {
778                     if ( canAddHeaderNamedResourceFragment( dojoReq, namedResourcesAddedFragmentsDefault, registryContent ) )
779                     {
780                         if ( registryContent[0] != null )
781                         {
782                             String dojoReqFromRegistry = HeaderResourceLib.makeJavascriptStatement( registryContent[0], "    ", true );
783                             if ( dojoReqFromRegistry.length() > 0 )
784                             {
785                                 dojoRequiresContent.append( registryContent[0] );
786                             }
787                         }
788                         else
789                         {
790                             dojoRequiresContent.append( "    dojo.require(\"").append( dojoReq ).append( "\");" ).append( EOL );
791                         }
792                     }
793                 }
794             }
795             namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_REQUIRES_CORE, dojoRequiresContent.toString() );
796             registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_REQUIRES_CORE, null, dojoEnableName, headerDynamicConfigurationDefault );
797         }
798         
799         // dojo modules path definition
800         List dojoModulesPath = (List)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_MODULES_PATH );
801         if ( dojoModulesPath != null && dojoModulesPath.size() > 0 )
802         {
803             StringBuffer dojoModulesPathContent = new StringBuffer();
804             boolean addedContent = false;
805             Iterator dojoModulesPathIter = dojoModulesPath.iterator();
806             while ( dojoModulesPathIter.hasNext() )
807             {
808                 String dojoModule = (String)dojoModulesPathIter.next();
809                 if ( dojoModule != null && dojoModule.length() > 0 )
810                 {
811                     if ( canAddHeaderNamedResourceFragment( dojoModule, namedResourcesAddedFragmentsDefault, registryContent ) )
812                     {
813                         String dojoModuleContent = null;
814                         if ( registryContent[0] != null )
815                         {
816                             dojoModuleContent = registryContent[0];
817                         }
818                         else
819                         {
820                             dojoModuleContent = dojoModule;
821                         }
822                         dojoModuleContent = HeaderResourceLib.makeJavascriptStatement( dojoModuleContent, "    ", true );
823                         if ( dojoModuleContent.length() > 0 )
824                         {
825                             dojoModulesPathContent.append( dojoModuleContent );
826                             addedContent = true;
827                         }
828                     }
829                 }
830             }
831             if ( addedContent )
832             {
833                 namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_MODULES_PATH, dojoModulesPathContent.toString() );
834                 registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_MODULES_PATH, null, dojoEnableName, headerDynamicConfigurationDefault );
835             }
836         }
837         
838         // dojo modules namespace definition
839         List dojoModulesNamespace = (List)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_MODULES_NAMESPACE );
840         if ( dojoModulesNamespace != null && dojoModulesNamespace.size() > 0 )
841         {
842             StringBuffer dojoModulesNamespaceContent = new StringBuffer();
843             boolean addedContent = false;
844             Iterator dojoModulesNamespaceIter = dojoModulesNamespace.iterator();
845             while ( dojoModulesNamespaceIter.hasNext() )
846             {
847                 String dojoModuleWidget = (String)dojoModulesNamespaceIter.next();
848                 if ( dojoModuleWidget != null && dojoModuleWidget.length() > 0 )
849                 {
850                     if ( canAddHeaderNamedResourceFragment( dojoModuleWidget, namedResourcesAddedFragmentsDefault, registryContent ) )
851                     {
852                         String dojoModuleContent = null;
853                         if ( registryContent[0] != null )
854                         {
855                             dojoModuleContent = registryContent[0];
856                         }
857                         else
858                         {
859                             dojoModuleContent = dojoModuleWidget;
860                         }
861                         dojoModuleContent = HeaderResourceLib.makeJavascriptStatement( dojoModuleContent, "    ", true );
862                         if ( dojoModuleContent.length() > 0 )
863                         {
864                             dojoModulesNamespaceContent.append( dojoModuleContent );
865                             addedContent = true;
866                         }
867                     }
868                 }
869             }
870             if ( addedContent )
871             {
872                 namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_MODULES_NAMESPACE, dojoModulesNamespaceContent.toString() );
873                 // registerAndOrderNamedHeaderResource called below
874             }
875         }
876         
877         // dojo requires - module libraries (from add-on modules)
878         List dojoRequiresModules = (List)dojoConfigMap.get( HeaderResource.HEADER_CONFIG_DOJO_REQUIRES_MODULES );
879         if ( dojoRequiresModules != null && dojoRequiresModules.size() > 0 )
880         {
881             StringBuffer dojoRequiresContent = new StringBuffer();
882             Iterator dojoRequiresModulesIter = dojoRequiresModules.iterator();
883             while ( dojoRequiresModulesIter.hasNext() )
884             {
885                 String dojoReq = (String)dojoRequiresModulesIter.next();
886                 if ( dojoReq != null && dojoReq.length() > 0 )
887                 {
888                     if ( canAddHeaderNamedResourceFragment( dojoReq, namedResourcesAddedFragmentsDefault, registryContent ) )
889                     {
890                         if ( registryContent[0] != null )
891                         {
892                             String dojoReqFromRegistry = HeaderResourceLib.makeJavascriptStatement( registryContent[0], "    ", true );
893                             if ( dojoReqFromRegistry.length() > 0 )
894                             {
895                                 dojoRequiresContent.append( registryContent[0] );
896                             }
897                         }
898                         else
899                         {
900                             dojoRequiresContent.append( "    dojo.require(\"").append( dojoReq ).append( "\");" ).append( EOL );
901                         }
902                     }
903                 }
904             }
905             namedResourcesDefault.put( HeaderResource.HEADER_SECTION_DOJO_REQUIRES_MODULES, dojoRequiresContent.toString() );
906             registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_REQUIRES_MODULES, null, dojoEnableName, headerDynamicConfigurationDefault );
907         }
908         
909         // dojo writeincludes
910         //    - adding to order only at this point
911         //    - if header contains content, generated content will not be added
912         registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_WRITEINCLUDES, HeaderResource.HEADER_TYPE_SCRIPT_BLOCK_START, dojoEnableName, headerDynamicConfigurationDefault );
913         
914         // dojo widget module - register widget packages (eg. dojo.widget.manager.registerWidgetPackage('jetspeed.ui.widget'))
915         //    - default resource added above
916         registerAndOrderNamedHeaderResource( HeaderResource.HEADER_SECTION_DOJO_MODULES_NAMESPACE, HeaderResource.HEADER_TYPE_SCRIPT_BLOCK_START, dojoEnableName, headerDynamicConfigurationDefault );
917         
918         // dojo style bodyexpand
919         setNamedHeaderResourceProperties( HeaderResource.HEADER_SECTION_DOJO_STYLE_BODYEXPAND, HeaderResource.HEADER_TYPE_STYLE_BLOCK, dojoEnableName, headerDynamicConfigurationDefault );
920         
921         // dojo style bodyexpand noscroll
922         setNamedHeaderResourceProperties( HeaderResource.HEADER_SECTION_DOJO_STYLE_BODYEXPAND_NOSCROLL, HeaderResource.HEADER_TYPE_STYLE_BLOCK, dojoEnableName, headerDynamicConfigurationDefault );
923     }
924 
925     
926     /***
927      * Builds the portlet set defined in the context into a portlet tree.
928      * 
929      * @return Unique Portlet Entity ID
930      */
931     public void build( RequestContext context ) throws JetspeedException, IOException
932     {
933         ContentPage page = context.getPage();
934         if ( null == page )
935         {
936             throw new JetspeedException( "Failed to find PSML Pin ContentPageAggregator.build" );
937         }
938 
939         ContentFragment root = page.getRootContentFragment();
940 
941         if ( root == null )
942         {
943             throw new JetspeedException( "No root ContentFragment found in ContentPage" );
944         }
945 
946         // add named-resources and named-resources-added maps as request attributes
947         Map dynamicConfigDefault = getHeaderDynamicConfigurationDefault();
948         Map namedResourcesDefault = getHeaderNamedResourcesDefault();
949         Map namedResourcesAddedFragmentsDefault = getHeaderNamedResourcesAddedFragmentsDefault();
950         
951         /*if ( log.isDebugEnabled() && namedResourcesDefault != null )
952         {
953             Iterator namedResourcesDefaultIter = namedResourcesDefault.entrySet().iterator();
954             while ( namedResourcesDefaultIter.hasNext() )
955             {
956                 Map.Entry rsrcEntry = (Map.Entry)namedResourcesDefaultIter.next();
957                 Object rsrcVal = rsrcEntry.getValue();
958                 log.debug( rsrcEntry.getKey().toString() + ": " + EOL + ( rsrcVal != null ? rsrcVal.toString() : "null" ) );
959             }
960         }*/
961         
962         if ( dynamicConfigDefault != null || namedResourcesDefault != null || namedResourcesAddedFragmentsDefault != null )
963         {
964             Map existingNamedResources = (Map)context.getAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ATTRIBUTE );
965             if ( existingNamedResources == null )
966             {
967                 if ( dynamicConfigDefault == null )
968                 {
969                     context.setAttribute( PortalReservedParameters.HEADER_CONFIGURATION_ATTRIBUTE, new HashMap() );
970                 }
971                 else
972                 {
973                     HashMap dynamicConfig = new HashMap();
974                     Iterator hConfigEntryIter = dynamicConfigDefault.entrySet().iterator();
975                     while ( hConfigEntryIter.hasNext() )
976                     {
977                         Map.Entry hConfigEntry = (Map.Entry)hConfigEntryIter.next();
978                         Object hConfigKey = hConfigEntry.getKey();
979                         Object hConfigVal = hConfigEntry.getValue();
980                         if ( hConfigVal instanceof Map )
981                         {
982                             dynamicConfig.put( hConfigKey, new HashMap( (Map)hConfigVal ) );
983                         }
984                         else if ( hConfigVal instanceof List )
985                         {
986                             dynamicConfig.put( hConfigKey, new ArrayList( (List)hConfigVal ) );
987                         }
988                         else
989                         {
990                             dynamicConfig.put( hConfigKey, hConfigVal );
991                         }
992                     }
993                     context.setAttribute( PortalReservedParameters.HEADER_CONFIGURATION_ATTRIBUTE, dynamicConfig );
994                 }
995                 
996                 if ( namedResourcesDefault != null )
997                 {
998                     context.setAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ATTRIBUTE, new HashMap( namedResourcesDefault ) );
999                 }
1000                 if ( namedResourcesAddedFragmentsDefault != null )
1001                 {
1002                     context.setAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ADDED_FRAGMENTS_ATTRIBUTE, new HashMap( namedResourcesAddedFragmentsDefault ) );
1003                 }
1004             }
1005         }
1006         if ( getHeaderResourceRegistry() != null )
1007         {
1008             context.setAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_REGISTRY_ATTRIBUTE, getHeaderResourceRegistry() );
1009         }
1010         
1011         // handle maximized state
1012         boolean atLeastOneHasHeaderPhase = false;
1013         NavigationalState nav = context.getPortalURL().getNavigationalState();
1014         PortletWindow window = nav.getMaximizedWindow();
1015         if ( null != window )
1016         {
1017             ContentFragment maxedContentFragment = page.getContentFragmentById( window.getId().toString() );
1018             if ( maxedContentFragment != null )
1019             {
1020                 atLeastOneHasHeaderPhase = renderHeaderFragment( context, maxedContentFragment );
1021             }
1022         }
1023         else
1024         {
1025             atLeastOneHasHeaderPhase = aggregateAndRender( root, context, page );
1026         }
1027         
1028         if ( atLeastOneHasHeaderPhase )
1029         {
1030             
1031         }
1032     }
1033 
1034     protected boolean aggregateAndRender( ContentFragment fragment, RequestContext context, ContentPage page )
1035             throws FailedToRenderFragmentException
1036     {
1037         boolean atLeastOneHasHeaderPhase = false;
1038         boolean hasHeaderPhase = false;
1039         if ( fragment.getContentFragments() != null && fragment.getContentFragments().size() > 0 )
1040         {
1041             Iterator children = fragment.getContentFragments().iterator();
1042             while (children.hasNext())
1043             {
1044                 ContentFragment child = (ContentFragment) children.next();
1045                 if ( ! "hidden".equals( fragment.getState() ) )
1046                 {
1047                     hasHeaderPhase = aggregateAndRender( child, context, page );
1048                     if ( hasHeaderPhase )
1049                     {
1050                         atLeastOneHasHeaderPhase = true;
1051                     }
1052                 }
1053             }
1054         }
1055         hasHeaderPhase = renderHeaderFragment( context, fragment );
1056         if ( hasHeaderPhase )
1057         {
1058             atLeastOneHasHeaderPhase = true;
1059         }
1060         return atLeastOneHasHeaderPhase;
1061     }
1062     
1063     protected boolean renderHeaderFragment( RequestContext context, ContentFragment fragment )
1064     {
1065         try
1066         {
1067             if ( !fragment.getType().equals( ContentFragment.LAYOUT ) )
1068             {
1069                 PortletWindow portletWindow = getPortletWindowAccessor().getPortletWindow( fragment );
1070                 PortletDefinition pd = portletWindow.getPortletEntity().getPortletDefinition();
1071                 if ( pd != null && getPortletFactory().isPortletApplicationRegistered((PortletApplication)pd.getPortletApplicationDefinition() ) )
1072                 {
1073                     String portletApplicationContextPath = pd.getPortletApplicationDefinition().getWebApplicationDefinition().getContextRoot();
1074                     Portlet portlet = getPortletFactory().getPortletInstance( context.getConfig().getServletContext().getContext( portletApplicationContextPath ), pd ).getRealPortlet();            
1075                     if ( portlet != null && portlet instanceof SupportsHeaderPhase )
1076                     {
1077                         log.debug( "renderHeaderFragment: " + pd.getName() + " supports header phase" );
1078                         
1079                         HeaderResource hr = getHeaderResourceFactory().getHeaderResource( context, this.baseUrlAccess, isDesktop(), getHeaderConfiguration() );
1080                         PortletHeaderRequest headerRequest = new PortletHeaderRequestImpl( context, portletWindow, portletApplicationContextPath );
1081                         PortletHeaderResponse headerResponse = new PortletHeaderResponseImpl( context, hr, isDesktop(), getHeaderConfiguration(), getHeaderResourceRegistry() );
1082                         ((SupportsHeaderPhase)portlet).doHeader( headerRequest, headerResponse );
1083                         return true;
1084                     }
1085                 }
1086             }
1087             return false;
1088         }
1089         catch ( Exception e )
1090         {
1091             log.error( "renderHeaderFragment failed", e );
1092         }
1093         return false;
1094     }
1095     
1096     protected PortletFactory getPortletFactory()
1097     {
1098         return this.factory;
1099     }
1100     protected PortletWindowAccessor getPortletWindowAccessor()
1101     {
1102         return this.windowAccessor;
1103     }
1104     protected HeaderResourceFactory getHeaderResourceFactory()
1105     {
1106         return this.headerResourceFactory;
1107     }
1108     protected boolean isDesktop()
1109     {
1110         return this.isDesktop;
1111     }
1112     protected Map getHeaderConfiguration()
1113     {
1114         return this.headerConfiguration;
1115     }
1116     protected Map getHeaderResourceRegistry()
1117     {
1118         return this.headerResourceRegistry;
1119     }
1120     protected Map getHeaderDynamicConfigurationDefault()
1121     {
1122         return this.headerDynamicConfigurationDefault;
1123     }
1124     protected Map getHeaderNamedResourcesDefault()
1125     {
1126         return this.headerNamedResourcesDefault;
1127     }
1128     protected Map getHeaderNamedResourcesAddedFragmentsDefault()
1129     {
1130         return this.headerNamedResourcesAddedFragmentsDefault;
1131     }
1132     protected BasePortalURL getBaseUrlAccess()
1133     {
1134         return this.baseUrlAccess;
1135     }
1136 }