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.headerresource.impl;
18  
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.LinkedHashSet;
22  import java.util.Map;
23  import java.util.List;
24  import java.util.ArrayList;
25  import java.util.Set;
26  
27  import org.apache.jetspeed.PortalReservedParameters;
28  import org.apache.jetspeed.container.url.BasePortalURL;
29  import org.apache.jetspeed.headerresource.HeaderResource;
30  import org.apache.jetspeed.headerresource.HeaderResourceLib;
31  import org.apache.jetspeed.request.RequestContext;
32  
33  import org.apache.commons.lang.StringUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /***
38   * Default implementation for HeaderResource
39   * 
40   * @author <a href="mailto:shinsuke@yahoo.co.jp">Shinsuke Sugaya</a>
41   * @author <a href="mailto:smilek@apache.org">Steve Milek</a>
42   * @version $Id: HeaderResourceImpl.java 188569 2005-05-13 13:35:18Z weaver $
43   */
44  public class HeaderResourceImpl implements HeaderResource
45  {
46      protected final static Log log = LogFactory.getLog( HeaderResourceImpl.class );
47      
48      protected final static String EOL = "\r\n";   // html eol
49      protected final static String UNNAMED_CONTENT_HEADER_NAME = "org.apache.jetspeed.headerresource.unnamed";
50      
51      private RequestContext requestContext;
52      
53      // base portal url to override default url server info from servlet
54      private BasePortalURL baseUrlAccess = null;
55      
56      private boolean isDesktop;
57      
58      private Map headerConfiguration;
59      
60  
61      // ... mutable output tracking
62      //     - when depending on this feature, one HeaderResourceImpl instance must process all header inclusion
63      private HashMap namedResourcesAlreadyOutput;
64      
65      // ... as needed, these are obtained from request attributes
66      private Map headerDynamicConfiguration;
67      private Map headerNamedResources;
68      private Map headerNamedResourcesAddedFragments;
69      private Map headerResourceRegistry;
70      
71      // ... save generated portal urls to avoid duplicate effort
72      private String portalBaseUrl;
73      private String portalUrl;
74      
75      /***
76       * Default Constructor
77       * 
78       * @param context
79       */
80      public HeaderResourceImpl( RequestContext context )
81      {
82          this.requestContext = context;
83      }
84      public HeaderResourceImpl( RequestContext context, BasePortalURL baseUrlAccess, boolean isDesktop, Map headerConfiguration )
85      {
86          this.requestContext = context;
87          this.baseUrlAccess = baseUrlAccess;
88          
89          this.isDesktop = isDesktop;
90          
91          this.headerConfiguration = headerConfiguration;
92      }
93          
94      /***
95       * Output all content (that has not already been output)
96       * 
97       * @return content string for inclusion in html &lt;head&gt;
98       */
99      public String getContent()
100     {
101         StringBuffer header = new StringBuffer();
102         getNamedResourceContent( null, false, header );
103         getUnnamedContent( header );
104         return header.toString();
105     }
106     
107     /***
108      * Output all content (that has not already been output)
109      * 
110      * @return content string for inclusion in html &lt;head&gt;
111      */
112     public String toString()
113     {
114         return getContent();
115     }
116 
117     /***
118      * Output all unnamed (getHeaderInfoSet()) content (that has not already been output)
119      * 
120      * @return content string for inclusion in html &lt;head&gt;
121      */
122     public String getUnnamedContent()
123     {
124         StringBuffer header = new StringBuffer();
125         getUnnamedContent( header );
126         return header.toString();
127     }
128 
129     /***
130      * Output all getHeaderSections() content (that has not already been output)
131      * 
132      * @return content string for inclusion in html &lt;head&gt;
133      */
134     public String getNamedContent()
135     {
136         StringBuffer header = new StringBuffer();
137         getNamedResourceContent( null, false, header );
138         return header.toString();
139     }
140     
141     /***
142      * Output the one getHeaderSections() content entry with a key that matches headerName (if it has not already been output)
143      * 
144      * @return content string for inclusion in html &lt;head&gt;
145      */
146     public String getNamedContent( String headerName )
147     {
148         StringBuffer header = new StringBuffer();
149         getNamedResourceContent( headerName, false, header );
150         return header.toString();
151     }
152     
153     /***
154      * Output getHeaderSections() content entries with key prefixes that match headerNamePrefix (if it has not already been output)
155      * 
156      * @return content string for inclusion in html &lt;head&gt;
157      */
158     public String getNamedContentForPrefix( String headerNamePrefix )
159     {
160         if ( headerNamePrefix == null )
161             headerNamePrefix = "";
162         if ( ! headerNamePrefix.endsWith( "." ) )
163             headerNamePrefix = headerNamePrefix + ".";
164         StringBuffer header = new StringBuffer();
165         getNamedResourceContent( headerNamePrefix, true, header );
166         return header.toString();
167     }
168     
169     /*
170      * Output all getHeaderInfoSet() content (that has not already been output)
171      */
172     protected void getUnnamedContent( StringBuffer header )
173     {
174         HashMap namedResourcesInOutput = getNamedResourcesAlreadyOutput();
175         if ( namedResourcesInOutput == null )
176         {
177             namedResourcesInOutput = new HashMap();
178             setNamedResourcesAlreadyOutput( namedResourcesInOutput );
179         }
180         if ( ! namedResourcesInOutput.containsKey( UNNAMED_CONTENT_HEADER_NAME ) )
181         {
182             namedResourcesInOutput.put( UNNAMED_CONTENT_HEADER_NAME, Boolean.TRUE );
183             Set headerInfoSet = getHeaderInfoSet();
184             for ( Iterator ite = headerInfoSet.iterator(); ite.hasNext(); )
185             {
186                 header.append( ((HeaderInfo) ite.next()).toString() );
187                 header.append( EOL );
188             }
189         }
190     }
191     
192     /*
193      * Output getHeaderSections() content (that has not already been output) with regard to optional match arguments
194      */
195     protected void getNamedResourceContent( String headerNameMatch, boolean headerNameMatchPrefixOnly, StringBuffer header )
196     {
197         List headerOrderList = getHeaderSectionOrderList( false );
198         if ( headerOrderList != null && headerOrderList.size() > 0 )
199         {
200             HashMap namedResourcesInOutput = getNamedResourcesAlreadyOutput();
201             if ( namedResourcesInOutput == null )
202             {
203                 namedResourcesInOutput = new HashMap();
204                 setNamedResourcesAlreadyOutput( namedResourcesInOutput );
205             }
206             Map namedResources = getHeaderSections();
207             Map dynamicConfig = getHeaderDynamicConfiguration();
208             Map headerTypes = getHeaderSectionTypes( false );
209             Map headerRsrcRegistry = getHeaderResourceRegistry();
210             HashMap headerReqFlagResults = new HashMap();
211             boolean inScriptBlock = false;
212             boolean inStyleBlock = false;
213             Iterator headerOrderListIter = headerOrderList.iterator();
214             while ( headerOrderListIter.hasNext() )
215             {
216                 String headerName = (String)headerOrderListIter.next();
217                 if ( namedResourcesInOutput.containsKey( headerName ) )
218                 {
219                     continue;
220                 }
221                 if ( headerNameMatch != null )
222                 {
223                     if ( headerNameMatchPrefixOnly )
224                     {
225                         if ( ! headerName.startsWith( headerNameMatch ) )
226                         {
227                             continue;
228                         }
229                     }
230                     else
231                     {
232                         if ( ! headerName.equals( headerNameMatch ) )
233                         {
234                             continue;
235                         }
236                     }
237                 }
238                 boolean includeHeader = true;
239                 Object[] headerTypePair = ( ( headerTypes != null ) ? (Object[])headerTypes.get( headerName ) : (Object[])null );
240                 String headerReqFlag = ( ( headerTypePair != null ) ? (String)headerTypePair[1] : (String)null );
241                 if ( headerReqFlag != null && headerReqFlag.length() > 0 )
242                 {
243                     Boolean headerReqFlagResult = (Boolean)headerReqFlagResults.get( headerReqFlag );
244                     if ( headerReqFlagResult == null )
245                     {
246                         headerReqFlagResult = Boolean.FALSE;
247                         Object headerReqFlagValObj = dynamicConfig.get( headerReqFlag );
248                         if ( headerReqFlagValObj != null )
249                             headerReqFlagResult = new Boolean( headerReqFlagValObj.toString() );
250                         headerReqFlagResults.put( headerReqFlag, headerReqFlagResult );
251                     }
252                     includeHeader = headerReqFlagResult.booleanValue();
253                 }
254                 if ( includeHeader )
255                 {
256                     namedResourcesInOutput.put( headerName, Boolean.TRUE );
257                     Integer headerTypeIdObj = ( ( headerTypePair != null ) ? (Integer)headerTypePair[0] : (Integer)null );
258                     int headerTypeId = ( ( headerTypeIdObj != null ) ? headerTypeIdObj.intValue() : HeaderResource.HEADER_TYPE_ID_SCRIPT_BLOCK );
259 
260                     boolean requiresScriptBlock = false;
261                     boolean requiresStyleBlock = false;
262                     boolean preCloseBlock = false;
263                     boolean postCloseBlock = false;
264                     
265                     switch ( headerTypeId )
266                     {
267                         case HeaderResource.HEADER_TYPE_ID_SCRIPT_BLOCK:
268                         {
269                             requiresScriptBlock = true;
270                             break;
271                         }
272                         case HeaderResource.HEADER_TYPE_ID_SCRIPT_BLOCK_START:
273                         {
274                             preCloseBlock = true;
275                             requiresScriptBlock = true;
276                             break;
277                         }
278                         case HeaderResource.HEADER_TYPE_ID_SCRIPT_TAG:
279                         {
280                             preCloseBlock = true;
281                             break;
282                         }
283                         case HeaderResource.HEADER_TYPE_ID_SCRIPT_BLOCK_END:
284                         {
285                             postCloseBlock = true;
286                             requiresScriptBlock = true;
287                             break;
288                         }
289                         case HeaderResource.HEADER_TYPE_ID_STYLE_BLOCK:
290                         {
291                             requiresStyleBlock = true;
292                             break;
293                         }
294                         case HeaderResource.HEADER_TYPE_ID_LINK_TAG:
295                         {
296                             preCloseBlock = true;
297                             break;
298                         }
299                         case HeaderResource.HEADER_TYPE_ID_BASE_TAG:
300                         {
301                             preCloseBlock = true;
302                             break;
303                         }
304                         default:
305                         {
306                             log.error( "HeaderResource.getNamedResourceContent() cannot include header section with unknown type; header-section-name=" + headerName + " header-section-type-id=" + headerTypeId );
307                             includeHeader = false;
308                             break;
309                         }
310                     }
311                     if ( includeHeader )
312                     {
313                         if ( requiresScriptBlock && inStyleBlock )
314                         {
315                             preCloseBlock = true;
316                         }
317                         else if ( requiresStyleBlock && inScriptBlock )
318                         {
319                             preCloseBlock = true;
320                         }
321                         if ( preCloseBlock )
322                         {
323                             if ( inScriptBlock )
324                             {
325                                 header.append( "</script>" ).append( EOL );
326                                 inScriptBlock = false;
327                             }
328                             else if ( inStyleBlock )
329                             {
330                                 header.append( "</style>" ).append( EOL );
331                                 inStyleBlock = false;
332                             }
333                         }
334                         
335                         String headerText = (String)namedResources.get( headerName );
336                         if ( headerText == null )
337                         {
338                             headerText = generateHeaderSection( headerName );
339                             if ( headerText == null && headerRsrcRegistry != null )
340                             {                                
341                                 headerText = (String)headerRsrcRegistry.get( headerName );
342                                 log.debug( "header resource registry text for header section=" + headerName + " headerText=" + headerText );
343                             }
344                         }
345                         if ( headerText != null && headerText.length() > 0 )
346                         {
347                             if ( requiresScriptBlock && ! inScriptBlock )
348                             {
349                                 header.append( "<script language=\"JavaScript\" type=\"text/javascript\">" ).append( EOL );
350                                 inScriptBlock = true;
351                             }
352                             else if ( requiresStyleBlock && ! inStyleBlock )
353                             {
354                                 header.append( "<style>" ).append( EOL );
355                                 inStyleBlock = true;
356                             }
357                             header.append( headerText ).append( EOL );
358                         }
359                         if ( postCloseBlock )
360                         {
361                             if ( inScriptBlock )
362                             {
363                                 header.append( "</script>" ).append( EOL );
364                                 inScriptBlock = false;
365                             }
366                             else if ( inStyleBlock )
367                             {
368                                 header.append( "</style>" ).append( EOL );
369                                 inStyleBlock = false;
370                             }
371                         }
372                     }
373                 }   // if ( includeHeader )
374             }   // while ( headerOrderListIter.hasNext() )
375             if ( inScriptBlock )
376             {
377                 header.append( "</script>" ).append( EOL );
378                 inScriptBlock = false;
379             }
380             else if ( inStyleBlock )
381             {
382                 header.append( "</style>" ).append( EOL );
383                 inStyleBlock = false;
384             }
385         }   // if ( headerOrderList != null && headerOrderList.size() > 0 )
386     }
387     
388     /*
389      * Intended as derived class hook into late, auto-generated header resources
390      */
391     protected String generateHeaderSection( String headerName )
392     {
393         if ( headerName != null )
394         {
395             if ( headerName.equals( HEADER_SECTION_BASE_TAG ) )
396             {
397                 return jetspeedGenerateBasetag();
398             }
399             else if ( headerName.startsWith( HEADER_SECTION_NAME_PREFIX_DOJO ) )
400             {
401                 if ( headerName.equals( HEADER_SECTION_DOJO_PREINIT ) )
402                 {
403                     return dojoGeneratePreinit();
404                 }
405                 else if ( headerName.equals( HEADER_SECTION_DOJO_INIT ) )
406                 {
407                     return dojoGenerateInit();
408                 }
409                 else if ( headerName.equals( HEADER_SECTION_DOJO_WRITEINCLUDES ) )
410                 {
411                     return dojoGenerateWriteincludes();
412                 }
413                 else if ( headerName.equals( HEADER_SECTION_DOJO_STYLE_BODYEXPAND ) )
414                 {
415                     return dojoGenerateBodyExpandStyle();
416                 }
417                 else if ( headerName.equals( HEADER_SECTION_DOJO_STYLE_BODYEXPAND_NOSCROLL ) )
418                 {
419                     return dojoGenerateBodyExpandNoScrollStyle();
420                 }
421             }
422         }
423         return null;
424     }
425     
426     /***
427      * Add text argument to the getHeaderSections() content entry with a key that matches addToHeaderName argument
428      * 
429      */
430     public void addHeaderSectionFragment( String addToHeaderName, String text )
431     {
432         addHeaderSectionFragment( null, addToHeaderName, text, false );
433     }
434     
435     /***
436      * If no previous call using value of headerFragmentName argument has been added to any getHeaderSections() content entry,
437      * add text argument to the getHeaderSections() content entry with a key that matches addToHeaderName argument
438      * 
439      */
440     public void addHeaderSectionFragment( String headerFragmentName, String addToHeaderName, String text )
441     {
442         addHeaderSectionFragment( headerFragmentName, addToHeaderName, text, false );
443     }
444     
445     protected void addHeaderSectionFragment( String headerFragmentName, String addToHeaderName, String text, boolean alreadyCheckedFragName )
446     {
447         if ( addToHeaderName != null && text != null )
448         {
449             boolean addText = true;
450             if ( ! alreadyCheckedFragName && headerFragmentName != null && hasHeaderSectionFragment( headerFragmentName, true ) )
451             {
452                 addText = false;
453             }
454             if ( addText )
455             {
456                 Map headerRsrcRegistry = getHeaderResourceRegistry();
457                 if ( headerRsrcRegistry != null )
458                 {
459                     String overrideText = (String)headerRsrcRegistry.get( headerFragmentName );
460                     if ( overrideText != null )
461                     {
462                         text = overrideText;
463                     }
464                 }
465                 Map namedResources = getHeaderSections();
466                 String nText = (String)namedResources.get( addToHeaderName );
467                 if ( nText == null )
468                 {
469                     nText = text + EOL;
470                     orderHeaderSection( addToHeaderName );
471                 }
472                 else
473                 {
474                     nText = nText + text + EOL;
475                 }
476                 namedResources.put( addToHeaderName, nText );
477             }
478         }
479     }
480     
481     /***
482      * Indicate whether value of headerFragmentName argument has been used to add to any getHeaderSections() content entry
483      * 
484      * @return true if headerFragmentName argument has been used to add to any getHeaderSections() content entry
485      */
486     public boolean hasHeaderSectionFragment( String headerFragmentName )
487     {
488         return hasHeaderSectionFragment( headerFragmentName, false );
489     }
490     protected boolean hasHeaderSectionFragment( String headerFragmentName, boolean setToTrue )
491     {
492         if ( headerFragmentName != null )
493         {
494             Map namedResourcesAddedFragments = getHeaderSectionsAddedFragments();
495             if ( namedResourcesAddedFragments.containsKey( headerFragmentName ) )
496             {
497                 return true;
498             }
499             else if ( setToTrue )
500             {
501                 namedResourcesAddedFragments.put( headerFragmentName, Boolean.TRUE );
502             }
503         }
504         return false;
505     }
506     
507     protected void orderHeaderSection( String headerName )
508     {
509         if ( headerName != null )
510         {
511             Map headerNames = getHeaderSectionNames( true );
512             if ( ! headerNames.containsKey( headerName ) )
513             {
514                 List headerOrderList = getHeaderSectionOrderList( true );
515                 
516                 headerOrderList.add( headerName );
517                 headerNames.put( headerName, Boolean.TRUE );
518             }
519         }
520     }
521     
522     /***
523      * Indicate whether value of headerName is an included header section
524      * 
525      * @return true if headerName argument is an included header section
526      */
527     public boolean isHeaderSectionIncluded( String headerName )
528     {
529         if ( headerName != null )
530         {
531             Map headerNames = getHeaderSectionNames( false );
532             if ( headerNames != null && headerNames.get( headerName ) != null )
533             {
534                 return true;
535             }
536         }
537         return false;
538     }
539     
540     /***
541      * Get the type of the getHeaderSections() content entry with a key that matches headerName argument
542      * 
543      * @return type of header section
544      */
545     public String getHeaderSectionType( String headerName )
546     {
547         if ( headerName != null )
548         {
549             Map headerTypes = getHeaderSectionTypes( false );
550             if ( headerTypes != null )
551             {
552                 Object[] headerTypePair = (Object[])headerTypes.get( headerName );
553                 if ( headerTypePair != null )
554                 {
555                     Integer headerTypeId = (Integer)headerTypePair[0];
556                     return HeaderResourceLib.getHeaderType( headerTypeId );
557                 }
558             }
559         }
560         return null;
561     }
562     
563     /***
564      * Set the type of the getHeaderSections() content entry with a key that matches headerName argument
565      * to the value of the headerType argument
566      */
567     public void setHeaderSectionType( String headerName, String headerType  )
568     {
569         if ( headerName != null )
570         {
571             int headerTypeId = HeaderResourceLib.getHeaderTypeId( headerType );
572             if ( headerTypeId < 0 )
573             {
574                 log.error( "HeaderResourceImpl.setHeaderSectionType() ignoring specification of unknown header section type; header-section-name=" + headerName + " header-section-type=" + headerType );
575             }
576             else
577             {
578                 Map headerTypes = getHeaderSectionTypes( true );
579                 Object[] headerTypePair = (Object[])headerTypes.get( headerName );
580                 if ( headerTypePair == null )
581                 {
582                     if ( headerType != null )
583                     {
584                         headerTypePair = new Object[] { new Integer( headerTypeId ), null };
585                         headerTypes.put( headerName, headerTypePair );
586                     }
587                 }
588                 else
589                 {
590                     headerTypePair[0] = new Integer( headerTypeId );
591                 }
592             }
593         }
594     }
595     
596     /***
597      * Get the requiredflag of the getHeaderSections() content entry with a key that matches headerName argument
598      * 
599      * @return requiredflag for header section
600      */
601     public String getHeaderSectionRequiredFlag( String headerName )
602     {
603         if ( headerName != null )
604         {
605             Map headerTypes = getHeaderSectionTypes( false );
606             if ( headerTypes != null )
607             {
608                 Object[] headerTypePair = (Object[])headerTypes.get( headerName );
609                 if ( headerTypePair != null )
610                 {
611                     return (String)headerTypePair[1];
612                 }
613             }
614         }
615         return null;
616     }
617     
618     /***
619      * Set the requiredflag of the getHeaderSections() content entry with a key that matches headerName argument
620      * to the value of the headerReqFlag argument
621      */
622     public void setHeaderSectionRequiredFlag( String headerName, String headerReqFlag )
623     {
624         if ( headerName != null )
625         {
626             if ( headerReqFlag != null && headerReqFlag.length() == 0 )
627                 headerReqFlag = null;
628             
629             Map headerTypes = getHeaderSectionTypes( true );
630             Object[] headerTypePair = (Object[])headerTypes.get( headerName );
631             if ( headerTypePair == null )
632             {
633                 if ( headerReqFlag != null )
634                 {
635                     headerTypePair = new Object[] { null, headerReqFlag };
636                     headerTypes.put( headerName, headerTypePair );
637                 }
638             }
639             else
640             {
641                 headerTypePair[1] = headerReqFlag;
642             }
643         }
644     }
645     
646     protected Map getHeaderSectionTypes( boolean create )
647     {
648         Map dynamicConfig = getHeaderDynamicConfiguration();
649         Map headerTypes = (Map)dynamicConfig.get( HEADER_CONFIG_TYPES );
650         if ( headerTypes == null && create )
651         {
652             headerTypes = new HashMap();
653             dynamicConfig.put( HEADER_CONFIG_TYPES, headerTypes );
654         }
655         return headerTypes;
656     }
657     protected Map getHeaderSectionNames( boolean create )
658     {
659         Map dynamicConfig = getHeaderDynamicConfiguration();
660         Map headerNames = (Map)dynamicConfig.get( HEADER_INTERNAL_INCLUDED_NAMES );
661         if ( headerNames == null && create )
662         {
663             headerNames = new HashMap();
664             dynamicConfig.put( HEADER_INTERNAL_INCLUDED_NAMES, headerNames );
665         }
666         return headerNames;
667     }
668     protected List getHeaderSectionOrderList( boolean create )
669     {
670         Map dynamicConfig = getHeaderDynamicConfiguration();
671         List headerOrderList = (List)dynamicConfig.get( HEADER_CONFIG_ORDER );
672         if ( headerOrderList == null )
673         {
674             headerOrderList = new ArrayList();
675             dynamicConfig.put( HEADER_CONFIG_ORDER, headerOrderList );
676         }
677         return headerOrderList;
678     }
679     
680     /***
681      * Access modifiable header configuration settings
682      * 
683      * @return Map containing modifiable header configuration settings 
684      */
685     public Map getHeaderDynamicConfiguration()
686     {
687         if ( this.headerDynamicConfiguration == null )
688         {
689             this.headerDynamicConfiguration = (Map)requestContext.getAttribute( PortalReservedParameters.HEADER_CONFIGURATION_ATTRIBUTE );
690             if ( this.headerDynamicConfiguration == null )
691             {
692                 this.headerDynamicConfiguration = new HashMap();
693                 requestContext.setAttribute( PortalReservedParameters.HEADER_CONFIGURATION_ATTRIBUTE, this.headerDynamicConfiguration );
694             }
695         }
696         return this.headerDynamicConfiguration;
697     }
698     protected Map getHeaderSections()
699     {
700         if ( this.headerNamedResources == null )
701         {
702             this.headerNamedResources = (Map)requestContext.getAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ATTRIBUTE );
703             if ( this.headerNamedResources == null )
704             {
705                 this.headerNamedResources = new HashMap();
706                 requestContext.setAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ATTRIBUTE, this.headerNamedResources );
707             }
708         }
709         return this.headerNamedResources;
710     }
711     protected Map getHeaderSectionsAddedFragments()
712     {
713         if ( this.headerNamedResourcesAddedFragments == null )
714         {
715             this.headerNamedResourcesAddedFragments = (Map)requestContext.getAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ADDED_FRAGMENTS_ATTRIBUTE );
716             if ( this.headerNamedResourcesAddedFragments == null )
717             {
718                 this.headerNamedResourcesAddedFragments = new HashMap();
719                 requestContext.setAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_ADDED_FRAGMENTS_ATTRIBUTE, this.headerNamedResourcesAddedFragments );
720             }
721         }
722         return this.headerNamedResourcesAddedFragments;
723     }
724     protected Map getHeaderResourceRegistry()
725     {
726         if ( this.headerResourceRegistry == null )
727         {
728             this.headerResourceRegistry = (Map)requestContext.getAttribute( PortalReservedParameters.HEADER_NAMED_RESOURCE_REGISTRY_ATTRIBUTE );
729             if ( this.headerResourceRegistry == null )
730             {
731                 this.headerResourceRegistry = new HashMap();
732             }
733         }
734         return this.headerResourceRegistry;
735     }
736     
737     protected RequestContext getRequestContext()
738     {
739         return this.requestContext;
740     }    
741     protected BasePortalURL getBaseUrlAccess()
742     {
743         return this.baseUrlAccess;
744     }
745     
746     /***
747      * Is request for /desktop rather than /portal
748      * 
749      * @return true if request is for /desktop, false if request is for /portal
750      */
751     public boolean isDesktop()
752     {
753         return this.isDesktop;
754     }
755     
756     /***
757      * Access complete header configuration settings
758      * 
759      * @return unmodifiable Map containing complete header configuration settings
760      */
761     public Map getHeaderConfiguration()
762     {
763         return this.headerConfiguration;
764     }
765     
766     protected HashMap getNamedResourcesAlreadyOutput()
767     {
768         return this.namedResourcesAlreadyOutput;
769     }
770     protected void setNamedResourcesAlreadyOutput( HashMap newOne )
771     {
772         this.namedResourcesAlreadyOutput = newOne;
773     }
774 
775     
776     // get portal urls - a copy of each of these methods exists in JetspeedDesktopContextImpl.java
777     
778     /***
779      * Portal base url ( e.g. http://localhost:8080/jetspeed )
780      * 
781      * @return portal base url
782      */
783     public String getPortalBaseUrl()
784     {
785         if ( this.portalBaseUrl == null )
786         {
787             this.portalBaseUrl = HeaderResourceLib.getPortalBaseUrl( this.requestContext, this.baseUrlAccess );
788         }
789         return this.portalBaseUrl;
790     }
791     
792     /***
793      * Portal base url ( e.g. http://localhost:8080/jetspeed )
794      * 
795      * @return portal base url
796      */
797     public String getPortalBaseUrl( boolean encode )
798     {
799         String baseurl = getPortalBaseUrl();
800         if ( ! encode )
801         {
802             return baseurl;
803         }
804         else
805         {
806             return requestContext.getResponse().encodeURL( baseurl );
807         }
808     }
809         
810     /***
811      * Portal base url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/javascript/dojo/ )
812      * 
813      * @return portal base url with relativePath argument appended
814      */
815     public String getPortalResourceUrl( String relativePath )
816     {
817         return getPortalResourceUrl( relativePath, false );
818     }
819     
820     /***
821      * Portal base url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/javascript/dojo/ )
822      * 
823      * @return portal base url with relativePath argument appended
824      */
825     public String getPortalResourceUrl( String relativePath, boolean encode )
826     {
827         return HeaderResourceLib.getPortalResourceUrl( relativePath, getPortalBaseUrl(), encode, this.requestContext );
828     }
829     
830     /***
831      * Portal base servlet url ( e.g. http://localhost:8080/jetspeed/desktop/ )
832      * 
833      * @return portal base servlet url
834      */
835     public String getPortalUrl()
836     {
837         if ( this.portalUrl == null )
838         {
839             this.portalUrl = HeaderResourceLib.getPortalUrl( getPortalBaseUrl(), this.requestContext );
840         }
841         return this.portalUrl;
842     }
843     
844     /***
845      * Portal base servlet url ( e.g. http://localhost:8080/jetspeed/desktop/ )
846      * 
847      * @return portal base servlet url
848      */
849     public String getPortalUrl( boolean encode )
850     {
851         return getPortalUrl( null, encode );
852     }
853     
854     /***
855      * Portal base servlet url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/desktop/default-page.psml )
856      * 
857      * @return portal base servlet url with relativePath argument appended
858      */
859     public String getPortalUrl( String relativePath )
860     {
861         return getPortalUrl( relativePath, false );
862     }
863     
864     /***
865      * Portal base servlet url with relativePath argument appended ( e.g. http://localhost:8080/jetspeed/desktop/default-page.psml )
866      * 
867      * @return portal base servlet url with relativePath argument appended
868      */
869     public String getPortalUrl( String relativePath, boolean encode )
870     {
871         return HeaderResourceLib.getPortalResourceUrl( relativePath, getPortalUrl(), encode, this.requestContext );
872     }
873     
874 
875     //  jetspeed - special convenience methods
876     
877     protected String jetspeedGenerateBasetag()
878     {
879         StringBuffer basetagOut = new StringBuffer();
880         // <script type="text/javascript" src='http://localhost:8080/jetspeed/javascript/dojo/dojo.js'></script>
881         // src='$jetspeedDesktop.getPortalResourceUrl("/javascript/dojo/dojo.js")'
882         String fullPortalBaseUrl = HeaderResourceLib.getPortalBaseUrl( this.requestContext, this.baseUrlAccess, true );
883         String href = HeaderResourceLib.getPortalResourceUrl( "/", fullPortalBaseUrl, false, this.requestContext );
884         basetagOut.append( "<base href=\"" ).append( href ).append( "\">" );
885         return basetagOut.toString();
886     }
887     
888     // dojo - special convenience methods
889     
890     /***
891      * If no previous call using value of dojoRequire argument has been added to any getHeaderSections() content entry,
892      * add text argument to the getHeaderSections() content entry for dojo core require statements
893      * 
894      */
895     public void dojoAddCoreLibraryRequire( String dojoRequire )
896     {
897         dojoAddRequire( dojoRequire, HEADER_SECTION_DOJO_REQUIRES_CORE );
898     }
899     
900     /***
901      * Split dojoRequires argument using ';' delimiter and for each resulting dojoRequire value, if no previous call
902      * using dojoRequire value has been added to any getHeaderSections() content entry,
903      * add text argument to the getHeaderSections() content entry for dojo core require statements
904      * 
905      */
906     public void dojoAddCoreLibraryRequires( String dojoRequires )
907     {
908         dojoAddRequires( dojoRequires, HEADER_SECTION_DOJO_REQUIRES_CORE );
909     }
910     
911     /***
912      * If no previous call using value of dojoRequire argument has been added to any getHeaderSections() content entry,
913      * add text argument to the getHeaderSections() content entry for dojo library module require statements
914      * 
915      */
916     public void dojoAddModuleLibraryRequire( String dojoRequire )
917     {
918         dojoAddRequire( dojoRequire, HEADER_SECTION_DOJO_REQUIRES_MODULES );
919     }
920     
921     /***
922      * Split dojoRequires argument using ';' delimiter and for each resulting dojoRequire value, if no previous call
923      * using dojoRequire value has been added to any getHeaderSections() content entry,
924      * add text argument to the getHeaderSections() content entry for dojo library module require statements
925      * 
926      */
927     public void dojoAddModuleLibraryRequires( String dojoRequires )
928     {
929         dojoAddRequires( dojoRequires, HEADER_SECTION_DOJO_REQUIRES_MODULES );
930     }
931     
932     /***
933      * Assure that header section name for dojo body expand style is included
934      * 
935      */
936     public void dojoAddBodyExpandStyle( boolean omitWindowScrollbars )
937     {
938         if ( isHeaderSectionIncluded( HEADER_SECTION_DOJO_STYLE_BODYEXPAND ) || isHeaderSectionIncluded( HEADER_SECTION_DOJO_STYLE_BODYEXPAND_NOSCROLL ) )
939         {
940             // already included - first inclusion wins
941         }
942         else
943         {
944             if ( ! omitWindowScrollbars )
945             {
946                 orderHeaderSection( HEADER_SECTION_DOJO_STYLE_BODYEXPAND );
947             }
948             else
949             {
950                 orderHeaderSection( HEADER_SECTION_DOJO_STYLE_BODYEXPAND_NOSCROLL );
951             }
952         }
953     }
954     
955     /***
956      * Enable dojo by setting appropriate modifiable header configuration setting
957      * 
958      */
959     public void dojoEnable()
960     {
961         getHeaderDynamicConfiguration().put( HEADER_CONFIG_DOJO_ENABLE, "true" );
962     }
963     
964     protected void dojoDisable()
965     {
966         getHeaderDynamicConfiguration().put( HEADER_CONFIG_DOJO_ENABLE, "false" );
967     }
968     protected String dojoGetPath()
969     {
970         return (String)getHeaderDynamicConfiguration().get( HEADER_CONFIG_DOJO_PATH );
971     }
972     protected void dojoAddRequire( String dojoRequire, String addToHeaderName )
973     {
974         if ( dojoRequire != null && addToHeaderName != null && ! hasHeaderSectionFragment( dojoRequire, true ) )
975         {
976             String requireStatement = "    dojo.require(\"" + dojoRequire + "\");";
977             addHeaderSectionFragment( dojoRequire, addToHeaderName, requireStatement, true );
978         }
979     }
980     protected void dojoAddRequires( String dojoRequires, String addToHeaderName )
981     {
982         String[] reqStatements = StringUtils.split( dojoRequires, ';' );
983         int reqStatementsLen = ( reqStatements == null ) ? 0 : reqStatements.length;
984         if ( reqStatementsLen > 0 )
985         {   
986             for ( int i = 0 ; i < reqStatementsLen ; i++ )
987             {
988                 dojoAddRequire( reqStatements[i], addToHeaderName );
989             }
990         }
991     }
992     protected String dojoGeneratePreinit()
993     {
994         StringBuffer preinitOut = new StringBuffer();
995         //preinitOut.append( "    " ).append( "function de_jsessionid_url(url){var tEnds = url.indexOf(';jsessionid=');if (tEnds > 0) url = url.substring(0, tEnds);return url;}" ).append( EOL );
996         // presence of ;jsessionid in dojo baseScriptUri is bad news
997         preinitOut.append( "    " ).append( "djConfig.baseScriptUri = \"" ).append( getPortalResourceUrl( dojoGetPath(), false ) ).append( "\";" ).append( EOL );
998         if (this.requestContext.getRequest().getContextPath().length()==0)
999         {
1000             preinitOut.append( "    " ).append( "djConfig.jetspeed.rootContext = \"true\";" ).append( EOL );
1001         }
1002         preinitOut.append( "    " ).append( "djConfig.jetspeed.servletPath = \"" ).append( this.requestContext.getRequest().getServletPath() ).append( "\";" );
1003         return preinitOut.toString();
1004     }
1005     protected String dojoGenerateInit()
1006     {
1007         StringBuffer initOut = new StringBuffer();
1008         // <script type="text/javascript" src='http://localhost:8080/jetspeed/javascript/dojo/dojo.js'></script>
1009         // src='$jetspeedDesktop.getPortalResourceUrl("/javascript/dojo/dojo.js")'
1010         initOut.append( "<script type=\"text/javascript\" src=\"" ).append( getPortalResourceUrl( dojoGetPath(), false ) ).append( "dojo.js" ).append( "\"></script>" );
1011         return initOut.toString();
1012     }
1013     protected String dojoGenerateWriteincludes()
1014     {
1015         return "    dojo.hostenv.writeIncludes();";
1016     }
1017     protected String dojoGenerateBodyExpandStyle()
1018     {   // if not defined as getHeaderResourceRegistry(), generate default text
1019         Map headerRsrcRegistry = getHeaderResourceRegistry();
1020         String headerText = (String)headerRsrcRegistry.get( HEADER_SECTION_DOJO_STYLE_BODYEXPAND );
1021         if ( headerText == null )
1022         {
1023             headerText = "html, body { width: 100%; height: 100%; padding: 0 0 0 0; margin: 0 0 0 0; }";
1024         }
1025         return headerText;
1026     }
1027     protected String dojoGenerateBodyExpandNoScrollStyle()
1028     {   // if not defined as getHeaderResourceRegistry(), generate default text
1029         Map headerRsrcRegistry = getHeaderResourceRegistry();
1030         String headerText = (String)headerRsrcRegistry.get( HEADER_SECTION_DOJO_STYLE_BODYEXPAND_NOSCROLL );
1031         if ( headerText == null )
1032         {
1033             headerText = "html, body { width: 100%; height: 100%; overflow: hidden; padding: 0 0 0 0; margin: 0 0 0 0; }";
1034         }
1035         return headerText;
1036     }
1037 
1038     
1039     // older content implementation - using HeaderInfo set 
1040     
1041     /***
1042      * Gets HeaderInfo set from the request.
1043      * 
1044      * @return HeaderInfo set containing content for inclusion in html &lt;head&gt;
1045      */
1046     private Set getHeaderInfoSet()
1047     {
1048         Set headerInfoSet = (Set) requestContext.getAttribute(PortalReservedParameters.HEADER_RESOURCE_ATTRIBUTE);
1049         if (headerInfoSet == null)
1050         {
1051             headerInfoSet = new LinkedHashSet();
1052             requestContext.setAttribute(PortalReservedParameters.HEADER_RESOURCE_ATTRIBUTE, headerInfoSet);
1053         }
1054         return headerInfoSet;
1055     }
1056     
1057     /*
1058      * (non-Javadoc)
1059      * 
1060      * @see org.apache.jetspeed.headerresource.impl.HeaderResource#addHeaderInfo(java.lang.String)
1061      */
1062     public void addHeaderInfo(String text)
1063     {
1064         HeaderInfo headerInfo = new HeaderInfo(null, null, text);
1065         if (!containsHeaderInfo(headerInfo))
1066         {
1067             Set headerInfoSet = getHeaderInfoSet();
1068             headerInfoSet.add(headerInfo);
1069         }
1070     }
1071     
1072     /*
1073      * (non-Javadoc)
1074      * 
1075      * @see org.apache.jetspeed.headerresource.impl.HeaderResource#addHeaderInfo(java.lang.String,
1076      *      java.util.Map,java.lang.String)
1077      */
1078     public void addHeaderInfo(String elementName, Map attributes, String text)
1079     {
1080         HeaderInfo headerInfo = new HeaderInfo(elementName, attributes, text);
1081         if (!containsHeaderInfo(headerInfo))
1082         {
1083             Set headerInfoSet = getHeaderInfoSet();
1084             headerInfoSet.add(headerInfo);
1085         }
1086     }
1087 
1088     /***
1089      * Returns true if this set contains the specified HeaderInfo.
1090      * 
1091      * @param headerInfo
1092      * @return
1093      */
1094     private boolean containsHeaderInfo(HeaderInfo headerInfo)
1095     {
1096         Set headerInfoSet = getHeaderInfoSet();
1097         for (Iterator ite = headerInfoSet.iterator(); ite.hasNext();)
1098         {
1099             HeaderInfo hInfo = (HeaderInfo) ite.next();
1100             if (headerInfo.equals(hInfo))
1101             {
1102                 return true;
1103             }
1104         }
1105         return false;
1106     }
1107 
1108     /*
1109      * (non-Javadoc)
1110      * 
1111      * @see org.apache.jetspeed.headerresource.impl.HeaderResource#addJavaScript(java.lang.String,
1112      *      boolean)
1113      */
1114     public void addJavaScript(String path, boolean defer)
1115     {
1116         HashMap attrs = new HashMap();
1117         attrs.put("src", requestContext.getResponse().encodeURL( path ) );
1118         attrs.put("type", "text/javascript");
1119         if (defer)
1120         {
1121             attrs.put("defer", "true");
1122         }
1123         addHeaderInfo("script", attrs, "");
1124     }
1125 
1126     /*
1127      * (non-Javadoc)
1128      * 
1129      * @see org.apache.jetspeed.headerresource.impl.HeaderResource#addJavaScript(java.lang.String)
1130      */
1131     public void addJavaScript(String path)
1132     {
1133         addJavaScript(path, false);
1134     }
1135 
1136     /*
1137      * (non-Javadoc)
1138      * 
1139      * @see org.apache.jetspeed.headerresource.impl.HeaderResource#addStyleSheet(java.lang.String)
1140      */
1141     public void addStyleSheet(String path)
1142     {
1143         HashMap attrs = new HashMap();
1144         attrs.put("rel", "stylesheet");
1145         attrs.put("href", requestContext.getResponse().encodeURL( path ) );
1146         attrs.put("type", "text/css");
1147         addHeaderInfo("link", attrs, null);
1148     }
1149     
1150     /***
1151      * This class represents tag information for HeaderResouce component
1152      * 
1153      * @author <a href="mailto:shinsuke@yahoo.co.jp">Shinsuke Sugaya</a>
1154      */
1155     private class HeaderInfo
1156     {
1157         /***
1158          * Tag's name
1159          */
1160         private String elementName;
1161 
1162         /***
1163          * Tag's attributes
1164          */
1165         private Map attributes;
1166 
1167         /***
1168          * Tag's content
1169          */
1170         private String text;
1171 
1172         public HeaderInfo(String elementName)
1173         {
1174             this(elementName, new HashMap());
1175         }
1176 
1177         public HeaderInfo(String elementName, Map attr)
1178         {
1179             this(elementName, attr, null);
1180         }
1181 
1182         public HeaderInfo(String elementName, Map attr, String text)
1183         {
1184             setElementName(elementName);
1185             setAttributes(attr);
1186             setText(text);
1187         }
1188 
1189         public void addAttribute(String key, String value)
1190         {
1191             attributes.put(key, value);
1192         }
1193 
1194         public String toString()
1195         {
1196             StringBuffer buf = new StringBuffer();
1197             
1198             String elmtName = getElementName();
1199             if ( elmtName != null && elmtName.length() > 0 )
1200             {
1201                 buf.append("<");
1202                 buf.append(getElementName());
1203                 buf.append(" ");
1204 
1205                 Map attrMap = getAttributes();
1206                 if ( attrMap != null )
1207                 {
1208                     Set keySet = attrMap.keySet();
1209                     for (Iterator ite = keySet.iterator(); ite.hasNext();)
1210                     {
1211                         String key = (String) ite.next();
1212                         buf.append(key);
1213                         buf.append("=\"");
1214                         buf.append((String) attrMap.get(key));
1215                         buf.append("\" ");
1216                     }
1217                 }
1218                 if (getText() != null)
1219                 {
1220                     buf.append(">" + getText() + "</" + getElementName() + ">");
1221                 }
1222                 else
1223                 {
1224                     buf.append("/>");
1225                 }
1226             }
1227             else
1228             {
1229                 if (getText() != null)
1230                 {
1231                     buf.append( getText() );
1232                 }
1233             }
1234             return buf.toString();
1235         }
1236 
1237         public boolean equals(Object o)
1238         {
1239             if (o instanceof HeaderInfo)
1240             {
1241                 HeaderInfo headerInfo = (HeaderInfo) o;
1242                 if (compareString(headerInfo.getElementName(), getElementName())
1243                         && compareString(headerInfo.getText(), getText())
1244                         && compareAttributes(headerInfo.getAttributes(), getAttributes()))
1245                 {
1246                     return true;
1247                 }
1248             }
1249             return false;
1250         }
1251 
1252         private boolean compareString(String str0, String str1)
1253         {
1254             if (str0 == null)
1255             {
1256                 if (str1 == null)
1257                 {
1258                     return true;
1259                 }
1260 
1261             }
1262             else if ( str1 != null )
1263             {
1264                 if (str0.equals(str1))
1265                 {
1266                     return true;
1267                 }
1268             }
1269             return false;
1270         }
1271         
1272         private boolean compareAttributes(Map attr0, Map attr1)
1273         {
1274             if (attr0 == null)
1275             {
1276                 if (attr1 == null)
1277                 {
1278                     return true;
1279                 }
1280             }
1281             else if ( attr1 != null )
1282             {
1283                 if (attr0.equals(attr1))
1284                 {
1285                     return true;
1286                 }
1287             }
1288             return false;
1289         }
1290 
1291         /***
1292          * @return Returns the attributes.
1293          */
1294         public Map getAttributes()
1295         {
1296             return attributes;
1297         }
1298 
1299         /***
1300          * @param attributes The attributes to set.
1301          */
1302         public void setAttributes(Map attributes)
1303         {
1304             this.attributes = attributes;
1305         }
1306 
1307         /***
1308          * @return Returns the elementName.
1309          */
1310         public String getElementName()
1311         {
1312             return elementName;
1313         }
1314 
1315         /***
1316          * @param elementName The elementName to set.
1317          */
1318         public void setElementName(String elementName)
1319         {
1320             this.elementName = elementName;
1321         }
1322 
1323         /***
1324          * @return Returns the text.
1325          */
1326         public String getText()
1327         {
1328             return text;
1329         }
1330 
1331         /***
1332          * @param text The text to set.
1333          */
1334         public void setText(String text)
1335         {
1336             this.text = text;
1337         }
1338     }
1339 }