View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.custom.dojo;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.myfaces.renderkit.html.util.AddResource;
26  import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
27  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
28  
29  import javax.faces.component.UIComponent;
30  import javax.faces.context.FacesContext;
31  import javax.faces.context.ResponseWriter;
32  import javax.servlet.http.HttpServletRequest;
33  import java.io.IOException;
34  import java.lang.reflect.InvocationTargetException;
35  import java.lang.reflect.Method;
36  import java.util.*;
37  import java.util.Map.Entry;
38  
39  /**
40   * Utils class for the dojo infrastructure to ease the component building
41   * mechanisms note this class uses its own double entries filter due to the fact
42   * that we can mix and match header and body scripts as needed (we do not want
43   * to lose portal functionality do we?)
44   *
45   * @author Werner Punz (latest modification by $Author: skitching $)
46   * @version $Revision: 673833 $ $Date: 2006-09-08 20:56:28 +0000 (Fri, 08 Sep
47   *          2006) $
48   */
49  public final class DojoUtils {
50      private static final String MYFACES_DOJO_DEBUGCONSOLE_ID     = "myfaces_Dojo_Debugger";
51  
52      private static final String DEBUG_CONSOLE_TYPE               = "DebugConsole";
53  
54      private static final String LAYOUT_ALIGN_ATTR                = "layoutAlign";
55  
56      private static final String DISPLAY_CLOSE_ACTION_ATTR        = "displayCloseAction";
57  
58      private static final String RESIZABLE_ATTR                   = "resizable";
59  
60      private static final String HAS_SHADOW_ATTR                  = "hasShadow";
61  
62      private static final String CONSTRAIN_TO_CONTAINER_ATTR      = "constrainToContainer";
63  
64      private static final String ICON_SRC_ATTR                    = "iconSrc";
65  
66      private static final String TITLE_ATTR                       = "title";
67  
68      private static final String INCL_TYPE_REQ_KEY                = "DOJO_DEVELOPMENT_INCLUDE";
69  
70      private static final Log    log                              = LogFactory.getLog(DojoUtils.class);
71  
72      private static final String DOJO_PROVIDE                     = "dojo.provide:";
73  
74      private static final String DOJO_REQUIRE                     = "dojo.require:";
75  
76      private static final String DOJO_NAMESPACE                   = "dojo.namespace:";
77  
78      private static final String DJCONFIG_INITKEY                 = "/*djconfig init*/";
79  
80      private static final String BODY_SCRIPT_INFOS_ATTRIBUTE_NAME = "bodyScriptInfos";
81  
82      private static final String DOJO_FILE_UNCOMPRESSED           = "dojo.js.uncompressed.js";
83  
84      private static final String DOJO_FILE                        = "dojo.js";
85  
86      private static final String DJCONFIG_REQ_KEY                 = "MYFACES_DJCONFIG";
87  
88      private static final String DOJOEXTENSIONS_NAMESPACE         = "dojo.setModulePrefix('extensions', '../dojoextensions.ResourceLoader');";
89  
90      private DojoUtils() {
91          // nope
92      }
93  
94      /**
95       * creates a dojoed attribute map upon the given array of attribute names
96       *
97       * @param facesContext
98       *            standard faces context used internally
99       * @param attributeNames
100      *            string array of traversable attribute names
101      * @param component
102      *            the source component with the values set
103      * @return a map which resembles the attribute map for further processing
104      */
105     public static Map getAttributeMap(FacesContext facesContext, String[] attributeNames, UIComponent component) {
106         Log log = null;
107 
108         Class componentClass = component.getClass();
109         Map returnMap = new HashMap();
110         for (int cnt = 0; cnt < attributeNames.length; cnt++) {
111             try {
112                 String attributeName = attributeNames[cnt];
113                 //the dojo attributes deal with different ids than the rest
114                 if (attributeName.equals("id") || attributeName.equals("widgetId")) {
115                     String calculatedId = DojoUtils.calculateWidgetId(facesContext, component);
116                     returnMap.put("id", calculatedId);
117                 } else {
118                     String attributeCasedName = attributeName.substring(0, 1).toUpperCase() + attributeName.substring(1);
119                     String getForm = "get" + attributeCasedName; // to prevent multiple creating in finding
120                     String isForm = "is" + attributeCasedName; // to prevent multiple creating in finding
121                     Method m = null;
122                     // finding getter in hiearchy: try current class for "get" and "is" form, if NOT found, try superclass
123                     // doesn't use getMethod() to avoid walking whole hiearchy for wrong form in case of "is"
124                     // and getMethod() uses getSuperClass() anyway, so no performance hit this way + ability to invoke protected methods
125                     while ((componentClass != null) && (m == null)) {
126                         m = componentClass.getDeclaredMethod(getForm, null);
127                         if (m == null) {
128                             // try alternative method name for dealing with Booleans
129                          m = componentClass.getDeclaredMethod(isForm, null);
130                         }
131                         if (m == null) {
132                             // load superclass
133                             componentClass = componentClass.getSuperclass(); // null in case of componentClass == Object
134                         }
135                     }
136                     if (m != null) {
137                         Object execRetval = m.invoke(component, null);
138                         if (execRetval != null)
139                             returnMap.put(attributeName, execRetval);
140                     }
141                 }
142             } catch (Exception e) {
143                 if (log == null)
144                     log = LogFactory.getLog(DojoUtils.class);
145                 // this should not happen but can
146                 log.error("getAttributeMap", e);
147             }
148         }
149         return returnMap;
150     }
151 
152     /**
153      * adds a debug console to the output this is for helping to debug the dojo
154      * system a debug:true is required for this to work properly it will not be
155      * set by this method (due to the avoidance of unwanted automatisms causing
156      * sideefects)
157      *
158      * @param facesContext
159      * @param component
160      * @return
161      */
162     public static void addDebugConsole(FacesContext facesContext, UIComponent component) throws IOException {
163 
164         /* check whether we have a debugging flag already set */
165         if (isInlineScriptSet(facesContext, "/*DOJO DEBUGCONSOLE ON*/"))
166             return;
167 
168         AddResource addResource = AddResourceFactory.getInstance(facesContext);
169         addResource.addInlineScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, "/*DOJO DEBUGCONSOLE ON*/");
170 
171         ResponseWriter writer = facesContext.getResponseWriter();
172         // we for now have to break html until the dynamic creation
173         // isses are resolved, so hold on for this messy code now
174         // Since this is for debugging purposes only, we can live with it
175 
176         writer.startElement(HTML.DIV_ELEM, component);
177         writer.writeAttribute(HTML.ID_ATTR, MYFACES_DOJO_DEBUGCONSOLE_ID, null);
178         writer.writeAttribute(HTML.STYLE_ATTR, "width: 400px; height: 500px; left: 200px;", null);
179         writer.endElement(HTML.DIV_ELEM);
180 
181         Map attributeMap = new HashMap();
182         attributeMap.put(TITLE_ATTR, "MyFaces Dojo Debug console");
183         attributeMap.put(ICON_SRC_ATTR, "images/flatScreen.gif");
184         attributeMap.put(CONSTRAIN_TO_CONTAINER_ATTR, new Integer(1));
185         attributeMap.put(HAS_SHADOW_ATTR, new Boolean(true));
186         attributeMap.put(RESIZABLE_ATTR, new Boolean(true));
187         attributeMap.put(DISPLAY_CLOSE_ACTION_ATTR, new Boolean(true));
188         attributeMap.put(LAYOUT_ALIGN_ATTR, "client");
189         renderWidgetInitializationCode(writer, component, DEBUG_CONSOLE_TYPE, attributeMap, MYFACES_DOJO_DEBUGCONSOLE_ID, true);
190     }
191 
192     /**
193      * check if dojo is going to be used 
194      */
195     public static boolean isDojoInitialized(FacesContext facesContext)
196     {
197         return isInlineScriptCheck(facesContext, DJCONFIG_INITKEY);
198     }
199 
200     public static void addMainInclude(FacesContext facesContext, UIComponent component, String javascriptLocation, DojoConfig config) throws IOException {
201 
202         AddResource addResource = AddResourceFactory.getInstance(facesContext);
203 
204         /*
205          * var djConfig = { isDebug: false }; TODO add a saner handling of
206          * collecting all djconfig data and then merging it
207          */
208         if (!isInlineScriptSet(facesContext, DJCONFIG_INITKEY)) {
209             addResource.addInlineScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, DJCONFIG_INITKEY);
210             addResource.addInlineScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, config.toString());
211 
212             String dojofile = ((getExpanded(facesContext) != null) && getExpanded(facesContext).booleanValue()) ? DOJO_FILE_UNCOMPRESSED : DOJO_FILE;
213 
214             if (javascriptLocation != null) {
215                 addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, javascriptLocation + dojofile);
216             } else {
217                 /*
218                  * ResponseWriter writer = facesContext.getResponseWriter();
219                  * writer.startElement(HTML.SCRIPT_ELEM,component);
220                  *
221                  * MyFacesResourceHandler handler = new
222                  * MyFacesResourceHandler(DojoResourceLoader.class, dojofile);
223                  * String uri = handler.getResourceUri(facesContext); uri =
224                  * uri.replaceAll("dojo\\.js\\;jsessionid(.)*\\\"","dojo.js");
225                  * writer.writeAttribute(HTML.SRC_ATTR, uri, null);
226                  *
227                  * writer.endElement(HTML.SCRIPT_ELEM);
228                  * addResource.addJavaScriptAtPosition(facesContext,
229                  * AddResource.HEADER_BEGIN, DojoResourceLoader.class,
230                  * dojofile);
231                  */
232 
233                 addResource.addJavaScriptAtPositionPlain(facesContext, AddResource.HEADER_BEGIN, DojoResourceLoader.class, dojofile);
234             }
235             addResource.addInlineScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, DOJOEXTENSIONS_NAMESPACE);
236         }
237     }
238 
239     /**
240      * adds a new namespace location to the mix
241      *
242      * @param facesContext
243      *            the faces context which is used internally
244      * @param component
245      *            the affected component
246      * @param namespace
247      *            the namespace which has to be applied
248      * @param location
249      *            the script location
250      * @throws IOException
251      * @link http://blog.dojotoolkit.org/2006/01/11/putting-your-code-outside-of-the-dojo-source-tree
252      */
253     public static void addNamespace(FacesContext facesContext, UIComponent component, String namespace, String location) throws IOException {
254 
255         if (isInlineScriptSet(facesContext, DOJO_NAMESPACE + namespace))
256             return;
257 
258         String namespaceStr = createNamespaceScript(namespace, location);
259         writeInlineScript(facesContext, component, namespaceStr);
260     }
261 
262     /**
263      * adds a dojo provide to the current list of definitions within the header
264      *
265      * @param context
266      *            the faces context for accessing the resources internally
267      * @param provided
268      *            the package with the class provided by this implementation
269      * @see <a
270      *      href="http://dojotoolkit.org/docs/fast_widget_authoring.html">Dojo-Widget-Authoring</a>
271      *      for an example on this
272      */
273     public static void addProvide(FacesContext context, String provided) {
274 
275         if (isInlineScriptSet(context, DOJO_PROVIDE + provided))
276             return;
277 
278         AddResource addResource = AddResourceFactory.getInstance(context);
279         String providedBuilder = createDojoProvideScript(provided);
280 
281         addResource.addInlineScriptAtPosition(context, AddResource.HEADER_BEGIN, providedBuilder);
282     }
283 
284     /**
285      * adds a dojo provide
286      *
287      * @param facesContext
288      * @param component
289      * @param provided
290      * @throws IOException
291      */
292     public static void addProvide(FacesContext facesContext, UIComponent component, String provided) throws IOException {
293 
294         if (isInlineScriptSet(facesContext, DOJO_PROVIDE + provided))
295             return;
296 
297         String providedBuilder = createDojoProvideScript(provided);
298 
299         writeInlineScript(facesContext, component, providedBuilder);
300 
301     }
302 
303     /**
304      * convenience method for easier requires handling
305      * @param facesContext standard faces context
306      * @param component the component
307      * @param requires an array of requires which is rendered into single dojo.require statements
308      * @throws IOException
309      */
310     public static void addRequire(FacesContext facesContext, UIComponent component, String[] requires) throws IOException {
311         for (int cnt = 0; cnt < requires.length; cnt++)
312             addRequire(facesContext, component, requires[cnt]);
313     }
314 
315     /**
316      * adds a dojo require include to our mix of stuff used
317      *
318      * @param facesContext
319      * @param required
320      */
321     public static void addRequire(FacesContext facesContext, UIComponent component, String required) throws IOException {
322 
323         if (isInlineScriptSet(facesContext, DOJO_REQUIRE + required))
324             return;
325 
326         String requireAsScript = createDojoRequireString(required);
327         writeInlineScript(facesContext, component, requireAsScript);
328     }
329 
330     /**
331      * creates a debug statement for the debug console
332      *
333      * @param stmnt
334      *            the debug message displayed by the debug console
335      * @return javaScriptcode String
336      */
337     public static String createDebugStatement(String stmnt) {
338         return "dojo.debug(\"" + stmnt + "\");\n";
339     }
340 
341     /**
342      * creates a debug statement and a corresponding value for the debug console
343      *
344      * @param stmnt
345      *            the debug message displayed and given value by the debug
346      *            console
347      * @return javaScriptcode String
348      */
349     public static String createDebugStatement(String stmnt, String value) {
350         return "dojo.debug(\"" + stmnt + ":\");dojo.debug(" + value + ");\n";
351     }
352 
353     /**
354      * helper method which does the proper dojo provide script creation
355      *
356      * @param provided
357      *            the provided class name
358      * @return dojoProvide String
359      */
360     public static String createDojoProvideScript(String provided) {
361 
362         StringBuffer providedBuilder = new StringBuffer(32);
363         providedBuilder.append("dojo.provide('");
364         providedBuilder.append(provided.trim());
365         providedBuilder.append("');");
366 
367         return providedBuilder.toString();
368     }
369 
370     /**
371      * helper method for the proper dojo require script creation
372      *
373      * @param required
374      *            the creation package for the require functionality
375      * @return dojoRequire String
376      */
377     public static String createDojoRequireString(String required) {
378         StringBuffer requiredBuilder = new StringBuffer(32);
379         requiredBuilder.append("dojo.require('");
380         requiredBuilder.append(required.trim());
381         requiredBuilder.append("');");
382 
383         return requiredBuilder.toString();
384     }
385 
386     /**
387      * Request singleton getter method for the djConfig object
388      *
389      * @param context
390      * @return
391      */
392     public static DojoConfig getDjConfigInstance(FacesContext context) {
393 
394         // we wont have a need for a synchronized here, since
395         // we are in a single request cycle anyway
396         // but take care if you use the djconfig in multiple threads!
397         DojoConfig djConfig = (DojoConfig) ((HttpServletRequest) context.getExternalContext().getRequest()).getAttribute(DJCONFIG_REQ_KEY);
398 
399         if (djConfig == null) {
400             djConfig = new DojoConfig();
401             ((HttpServletRequest) context.getExternalContext().getRequest()).setAttribute(DJCONFIG_REQ_KEY, djConfig);
402         }
403 
404         return djConfig;
405     }
406 
407     /**
408      * getter for the expanded flat
409      *
410      * @param facesContext
411      * @return
412      */
413     public static Boolean getExpanded(FacesContext facesContext) {
414         // either the development attribute set or a special request key
415         HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
416         Boolean devStatus = (Boolean) request.getAttribute(INCL_TYPE_REQ_KEY);
417         DojoConfig config = getDjConfigInstance(facesContext);
418         if (devStatus == null)
419             devStatus = new Boolean(false);
420         devStatus = new Boolean(devStatus.booleanValue() || (config.getDevelopment() != null && config.getDevelopment().booleanValue()));
421 
422         return devStatus;
423     }
424 
425     /**
426      * Inline script set
427      *
428      * @param context
429      *            standard faces context
430      * @param inlineScript
431      *            key to the inline script
432      * @return true if the inline script already is set
433      */
434     public static boolean isInlineScriptSet(FacesContext context, String inlineScript) {
435 
436         // TODO move this non neutral code into the resource handler
437         HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
438         Set set = getBodyScriptInfos(request);
439 
440         if (!set.contains(inlineScript)) {
441             set.add(inlineScript);
442 
443             return false;
444         }
445 
446         return true;
447     }
448 
449     /**
450      * check if the script with the given inlineScript-name has been added
451      */
452     public static boolean isInlineScriptCheck(FacesContext context, String inlineScript)
453     {
454         // TODO move this non neutral code into the resource handler
455         HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
456         Set set = getBodyScriptInfos(request);
457 
458         return set.contains(inlineScript);
459     }
460 
461     /**
462      * please, instead of using standard dojo taglib mechanisms use this code
463      * for initialisation it will render a clean and proper javascript
464      * initialisation instead. There are issues with ADF and the dojo taglib
465      * mechanisms and also (Alex Russel wont like to hear this) the dojo taglib
466      * initialisation fails on W3C validations. returns the name of the
467      * javascript var for further processing
468      *
469      * @param facesContext
470      *            standard faces context
471      * @param component
472      *            standard component
473      * @param dojoType
474      *            the dojo type of this component
475      * @param paramMap
476      */
477     public static String renderWidgetInitializationCode(FacesContext facesContext, UIComponent component, String dojoType, Map paramMap) throws IOException {
478         ResponseWriter writer = facesContext.getResponseWriter();
479         String clientId = component.getClientId(facesContext);
480         return renderWidgetInitializationCode(writer, component, dojoType, paramMap, clientId, true);
481     }
482 
483     /**
484      * convenience method to render the widget init code automatically
485      * for a given component and a set of attribute names
486      *
487      * @param facesContext
488      * @param component
489      * @param dojoType
490      * @param attributeNames
491      * @return
492      * @throws IOException
493      */
494     public static String renderWidgetInitializationCode(FacesContext facesContext, UIComponent component, String dojoType, String[] attributeNames)
495             throws IOException {
496         Map paramMap = DojoUtils.getAttributeMap(facesContext, attributeNames, component);
497         return renderWidgetInitializationCode(facesContext, component, dojoType, paramMap);
498     }
499 
500     /**
501      * same for a given neutral id...
502      *
503      * @param dojoType
504      * @param paramMap
505      * @param clientId
506      *            the referencing id which the widget has to render to (note the
507      *            id is enforced the uicomponent does nothing in this case!!!!)
508      * @param refId
509      *            if true the refid is set in the dojo javascript init code if
510      *            false no ref is set the false often is needed for containers
511      *            which dynamically generated widgets with no referencing div
512      * @return a string with the name of the javascript variable
513      */
514     public static String renderWidgetInitializationCode(ResponseWriter writer, UIComponent component, String dojoType, Map paramMap, String clientId,
515             boolean refId) throws IOException {
516 
517         writer.startElement(HTML.SCRIPT_ELEM, component);
518         writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
519 
520         String javascriptVar = (String) paramMap.get("widgetVar");
521         if (StringUtils.isBlank(javascriptVar))
522             javascriptVar = calculateWidgetVarName(clientId);
523 
524         Iterator it = paramMap.entrySet().iterator();
525 
526         writer.write("var ");
527         writer.write(javascriptVar);
528         writer.write(" = ");
529 
530         writer.write("dojo.widget.createWidget(\"");
531         writer.write(dojoType);
532         writer.write("\",");
533 
534         writer.write("{");
535         boolean first = true;
536         while (it.hasNext()) {
537             Entry entry = (Entry) it.next();
538             Object value = entry.getValue();
539             if (value != null) {
540                 if (!first)
541                     writer.write(",");
542                 writer.write(entry.getKey().toString());
543                 writer.write(":");     // only real string values should be within
544                                     // ambersants, dojo req
545                 boolean isString = value instanceof String;
546                 if (isString)
547                 {
548                     if( value.equals("true")
549                         || value.equals("false") )
550                         isString = false;
551                 }
552                 if (isString)
553                     writer.write("'");
554                 writer.write(value.toString());
555                 if (isString)
556                     writer.write("'");
557                 first = false;
558             }
559 
560         }
561         writer.write("}");
562         if (refId) {
563             writer.write(",dojo.byId('");
564             writer.write(clientId);
565             writer.write("')");
566         }
567         writer.write(");");
568 
569         writer.endElement(HTML.SCRIPT_ELEM);
570         return javascriptVar;
571     }
572 
573     /**
574      * helper method to centralize the widget variable name calculation for our
575      * dojo javascript widget init code
576      *
577      * @param clientId
578      *            the client id upon which the var name has to be generated
579      * @return the javascript widget var name for the given client id
580      */
581     public static String calculateWidgetVarName(String clientId) {
582         return clientId.replaceAll("\\:", "_") + "_dojoControl";
583     }
584 
585     /**
586      *
587      * @return
588      */
589     public static String calculateWidgetId(FacesContext context, UIComponent widget) {
590         String widgetVarName = "";
591         if (widget instanceof DojoWidget) {
592             widgetVarName = ((DojoWidget) widget).getWidgetId();
593         }
594         if (StringUtils.isBlank(widgetVarName)) {
595             widgetVarName = calculateWidgetVarName(widget.getClientId(context));
596         }
597         return widgetVarName;
598     }
599 
600 
601     /**
602      *
603      * @return
604      */
605     public static String calculateWidgetVarName(FacesContext context, UIComponent widget) {
606         String widgetVarName = "";
607         if (widget instanceof DojoWidget) {
608             widgetVarName = ((DojoWidget) widget).getWidgetVar();
609         }
610         if (StringUtils.isBlank(widgetVarName)) {
611             widgetVarName = calculateWidgetVarName(widget.getClientId(context));
612         }
613         return widgetVarName;
614     }
615 
616     /**
617      * helper to merge in an external dojo config instance the merge algorithm
618      * is that an existing entry is overwritten if a new config entry is set
619      * make sure that this is not called too often due to the fact that we do
620      * heavy reflection in here
621      *
622      * @param context
623      * @param config
624      */
625     public static void mergeExternalDjConfig(FacesContext context, DojoConfig config) {
626 
627         // we now do the same as beanutils, but for dependency reasons we code
628         // it
629         DojoConfig configSingleton = getDjConfigInstance(context);
630         Class dcConfigClass = DojoConfig.class;
631         Method[] djConfigFieldArr = dcConfigClass.getMethods();
632 
633         for (int cnt = 0; cnt < djConfigFieldArr.length; cnt++) {
634 
635             try {
636                 Method configPropertyField = djConfigFieldArr[cnt];
637                 String methodCore = null;
638 
639                 if ((!configPropertyField.getName().startsWith("getClass") && configPropertyField.getName().startsWith("get"))
640                         || configPropertyField.getName().startsWith("is"))
641                     methodCore = (configPropertyField.getName().startsWith("get")) ? configPropertyField.getName().substring(3) : configPropertyField.getName()
642                             .substring(2);
643 
644                 if (methodCore != null) {
645                     Object val = configPropertyField.invoke(config, null);
646 
647                     if (val != null) {
648                         Class[] setterParams = new Class[1];
649                         setterParams[0] = val.getClass();
650 
651                         Method setMethod = dcConfigClass.getMethod("set" + methodCore, setterParams);
652 
653                         if (setMethod != null) {
654                             Object[] setterArgs = new Object[1];
655                             setterArgs[0] = val;
656                             setMethod.invoke(configSingleton, setterArgs);
657                         }
658                     }
659                 }
660             } catch (IllegalArgumentException e) {
661                 log.error(e);
662             } catch (SecurityException e) {
663                 log.error(e);
664             } catch (IllegalAccessException e) {
665                 log.error(e);
666             } catch (InvocationTargetException e) {
667                 log.error(e);
668             } catch (NoSuchMethodException e) {
669                 log.error(e);
670             }
671         }
672 
673     }
674 
675     /**
676      * if this flag is set to true somewhere before the rendering, the expanded
677      * version is loaded otherwise the nonexpanded version is loaded
678      *
679      * @param facesContext
680      *            context because we again have a full request singleton here
681      * @param expanded
682      *            if set to true the expanded version of the dojo scripts are
683      *            loaded otherwise the non expanded ones are loaded
684      */
685     public static void setExpanded(FacesContext facesContext, Boolean expanded) {
686         HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
687         request.setAttribute(INCL_TYPE_REQ_KEY, expanded);
688     }
689 
690     /**
691      * helper to write out debug statements this is only a convenience method to
692      * reduce the code bloat
693      *
694      * @param writer
695      * @param stmnt
696      * @return
697      * @throws IOException
698      */
699     public static void writeDebugStatement(ResponseWriter writer, String stmnt) throws IOException {
700         stmnt = createDebugStatement(stmnt);
701         writer.write(stmnt);
702     }
703 
704     /**
705      * dojo namespace definition method allows the definition of a new namespace
706      * within the parameters of the dojo namespacing system
707      *
708      * @param namespace
709      *            the dojo namespace
710      * @param location
711      *            the exaclt script location (can be a relative location)
712      *
713      * @return the namespace script which has to be printed / executed
714      */
715     private static String createNamespaceScript(String namespace, String location) {
716         StringBuffer namespaceBuilder = new StringBuffer(32);
717         namespaceBuilder.append("dojo.hostenv.setModulePrefix('");
718         namespaceBuilder.append(namespace);
719         namespaceBuilder.append("','");
720         namespaceBuilder.append(location);
721         namespaceBuilder.append("');");
722 
723         String namespaceStr = namespaceBuilder.toString();
724 
725         return namespaceStr;
726     }
727 
728     private static Set getBodyScriptInfos(HttpServletRequest request) {
729         Set set = (Set) request.getAttribute(BODY_SCRIPT_INFOS_ATTRIBUTE_NAME);
730 
731         if (set == null) {
732             set = new TreeSet();
733             request.setAttribute(BODY_SCRIPT_INFOS_ATTRIBUTE_NAME, set);
734         }
735 
736         return set;
737     }
738 
739     /**
740      * helper to write an inline javascript at the exact resource location of
741      * the call
742      *
743      * @param facesContext
744      * @param component
745      * @param script
746      * @throws IOException
747      */
748     private static void writeInlineScript(FacesContext facesContext, UIComponent component, String script) throws IOException {
749         ResponseWriter writer = facesContext.getResponseWriter();
750         writer.startElement(HTML.SCRIPT_ELEM, component);
751         writer.writeAttribute(HTML.TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
752         writer.write(script);
753         writer.endElement(HTML.SCRIPT_ELEM);
754     }
755 
756 }