Coverage Report - org.apache.tapestry.dojo.AjaxShellDelegate
 
Classes in this File Line Coverage Branch Coverage Complexity
AjaxShellDelegate
73% 
100% 
1.933
 
 1  
 // Copyright 2004, 2005 The Apache Software Foundation
 2  
 //
 3  
 // Licensed under the Apache License, Version 2.0 (the "License");
 4  
 // you may not use this file except in compliance with the License.
 5  
 // You may obtain a copy of the License at
 6  
 //
 7  
 //     http://www.apache.org/licenses/LICENSE-2.0
 8  
 //
 9  
 // Unless required by applicable law or agreed to in writing, software
 10  
 // distributed under the License is distributed on an "AS IS" BASIS,
 11  
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
 // See the License for the specific language governing permissions and
 13  
 // limitations under the License.
 14  
 package org.apache.tapestry.dojo;
 15  
 
 16  
 import org.apache.hivemind.util.Defense;
 17  
 import org.apache.tapestry.*;
 18  
 import org.apache.tapestry.html.Shell;
 19  
 import org.apache.tapestry.json.JSONObject;
 20  
 
 21  
 import java.util.Locale;
 22  
 
 23  
 /**
 24  
  * The default rendering delegate responseible for include the dojo sources in
 25  
  * to the {@link Shell} component.
 26  
  */
 27  2
 public class AjaxShellDelegate implements IRender {
 28  
 
 29  
     /** Client side debug log level. */
 30  
     public static final String BROWSER_LOG_DEBUG="DEBUG";
 31  
     /** Client side info log level. */
 32  
     public static final String BROWSER_LOG_INFO="INFO";
 33  
     /** Client side warning log level. */
 34  
     public static final String BROWSER_LOG_WARNING="WARNING";
 35  
     /** Client side error log level. */
 36  
     public static final String BROWSER_LOG_ERROR="ERROR";
 37  
     /** Client side critical log level. */
 38  
     public static final String BROWSER_LOG_CRITICAL="CRITICAL";
 39  
 
 40  1
     private static final String SYSTEM_NEWLINE= (String)java.security.AccessController.doPrivileged(
 41  
       new sun.security.action.GetPropertyAction("line.separator"));
 42  
 
 43  
     private IAsset _dojoSource;
 44  
 
 45  
     private IAsset _dojoFormSource;
 46  
 
 47  
     private IAsset _dojoWidgetSource;
 48  
 
 49  
     private IAsset _dojoPath;
 50  
 
 51  
     private IAsset _tapestrySource;
 52  
 
 53  
     private IAsset _tapestryPath;
 54  
 
 55  
     private boolean _parseWidgets;
 56  
 
 57  2
     private String _browserLogLevel = BROWSER_LOG_WARNING;
 58  
 
 59  
     private boolean _debug;
 60  
 
 61  
     private String _debugContainerId;
 62  
 
 63  
     private boolean _consoleEnabled;
 64  
 
 65  
     private boolean _preventBackButtonFix;
 66  
 
 67  
     private boolean _debugAtAllCosts;
 68  
 
 69  
     /** Default list of pre-bundled dojo supported locales */
 70  2
     protected String[] SUPPORTED_LOCALES = { "en-us", "de-de", "de", "en-gb",
 71  
                                              "es-es", "es", "fr-fr", "fr", "zh-cn",
 72  
                                              "zh-tw", "zh" , "it-it", "it", "ja-jp",
 73  
                                              "ja", "ko-kr", "ko", "pt-br", "pt", "en", "xx"};
 74  
 
 75  
     /**
 76  
      * {@inheritDoc}
 77  
      */
 78  
     public void render(IMarkupWriter writer, IRequestCycle cycle)
 79  
     {
 80  
         // first configure dojo, has to happen before package include
 81  
 
 82  2
         JSONObject dojoConfig = new JSONObject();
 83  
 
 84  
         // Debugging configuration , debugAtAlCosts causes the individual 
 85  
         // .js files to included in the document head so that javascript errors
 86  
         // are able to resolve to the context of the file instead of just "dojo.js"
 87  
 
 88  2
         if (_debug)
 89  
         {
 90  1
             dojoConfig.put("isDebug", _debug);
 91  
         }
 92  
 
 93  2
         if (_debugAtAllCosts)
 94  0
             dojoConfig.put("debugAtAllCosts", _debugAtAllCosts);
 95  2
         if (_debugContainerId != null)
 96  0
             dojoConfig.put("debugContainerId", _debugContainerId);
 97  
 
 98  2
         IPage page = cycle.getPage();
 99  
 
 100  
         // The key to resolving everything out of the asset service
 101  
 
 102  2
         dojoConfig.put("baseRelativePath", _dojoPath.buildURL());
 103  
 
 104  2
         if (page.hasFormComponents())
 105  
         {
 106  0
             dojoConfig.put("preventBackButtonFix", _preventBackButtonFix);
 107  
         }
 108  2
         dojoConfig.put("parseWidgets", _parseWidgets);
 109  
 
 110  
         // Supports setting up locale in dojo environment to match the requested page locale.
 111  
         // (for things that use these settings, like DropdownDatePicker / date parsing / etc..
 112  
 
 113  2
         Locale locale = cycle.getPage().getLocale();
 114  
 
 115  2
         String localeStr = locale.getLanguage().toLowerCase()
 116  
                            + ((locale.getCountry() != null && locale.getCountry().trim().length() > 0)
 117  
                               ? "-" + locale.getCountry().toLowerCase()
 118  
                               : "");
 119  
 
 120  2
         if (isLocaleSupported(localeStr))
 121  
         {
 122  2
             dojoConfig.put("locale", localeStr);
 123  
         }
 124  
 
 125  
         // Write the required script includes and dojo.requires
 126  
 
 127  2
         StringBuffer str = new StringBuffer("<script type=\"text/javascript\">");
 128  2
         str.append("djConfig = ").append(dojoConfig.toString())
 129  
           .append(" </script>")
 130  
           .append(SYSTEM_NEWLINE).append(SYSTEM_NEWLINE);
 131  
 
 132  
         // include the core dojo.js package
 133  
 
 134  2
         str.append("<script type=\"text/javascript\" src=\"")
 135  
           .append(_dojoSource.buildURL()).append("\"></script>");
 136  
 
 137  2
         if (page.hasFormComponents())
 138  
         {
 139  0
             str.append("<script type=\"text/javascript\" src=\"")
 140  
               .append(_dojoFormSource.buildURL()).append("\"></script>");
 141  
         }
 142  
 
 143  2
         if (page.hasWidgets())
 144  
         {
 145  0
             str.append("<script type=\"text/javascript\" src=\"")
 146  
               .append(_dojoWidgetSource.buildURL()).append("\"></script>");
 147  
         }
 148  
 
 149  
         // configure basic dojo properties , logging includes
 150  
 
 151  2
         if (_debug)
 152  
         {
 153  1
             String logRequire = _consoleEnabled ? "dojo.require(\"dojo.debug.console\");" + SYSTEM_NEWLINE
 154  
                                 : "dojo.require(\"dojo.logging.Logger\");" + SYSTEM_NEWLINE;
 155  
 
 156  1
             str.append(SYSTEM_NEWLINE).append("<script type=\"text/javascript\">").append(SYSTEM_NEWLINE);
 157  1
             str.append(logRequire)
 158  
               .append("dojo.log.setLevel(dojo.log.getLevel(\"").append(_browserLogLevel)
 159  
               .append("\"));").append(SYSTEM_NEWLINE)
 160  
               .append("</script>");
 161  
         }
 162  
 
 163  
         // module path registration to tapestry javascript sources
 164  
 
 165  2
         String tapestryUrl = _tapestryPath.buildURL();
 166  2
         if (tapestryUrl.endsWith("/"))
 167  
         {
 168  0
             tapestryUrl = tapestryUrl.substring(0, tapestryUrl.length() - 1);
 169  
         }
 170  
 
 171  2
         str.append(SYSTEM_NEWLINE).append("<script type=\"text/javascript\">").append(SYSTEM_NEWLINE)
 172  
           .append("dojo.registerModulePath(\"tapestry\", \"")
 173  
           .append(tapestryUrl).append("\");").append(SYSTEM_NEWLINE);
 174  2
         str.append("</script>").append(SYSTEM_NEWLINE);
 175  
 
 176  
         // include core tapestry.js package
 177  
 
 178  2
         str.append("<script type=\"text/javascript\" src=\"")
 179  
           .append(_tapestrySource.buildURL()).append("\"></script>");
 180  
 
 181  
         // namespace registration
 182  
 
 183  2
         str.append(SYSTEM_NEWLINE).append("<script type=\"text/javascript\">").append(SYSTEM_NEWLINE);
 184  2
         str.append("dojo.require(\"tapestry.namespace\");").append(SYSTEM_NEWLINE)
 185  
           .append("tapestry.requestEncoding='")
 186  
           .append(cycle.getEngine().getOutputEncoding()).append("';")
 187  
           .append(SYSTEM_NEWLINE).append("</script>");
 188  
 
 189  2
         writer.printRaw(str.toString());
 190  2
         writer.println();
 191  2
     }
 192  
 
 193  
     /**
 194  
      * Checks if the provided locale string matches one of the predefined {@link #SUPPORTED_LOCALES}
 195  
      * in the dojo javascript library.
 196  
      *
 197  
      * @param locale
 198  
      *          The Dojo formatted locale string to check.
 199  
      *
 200  
      * @return True if locale is supported and ok to define in dojoConfig - false otherwise.
 201  
      */
 202  
     protected boolean isLocaleSupported(String locale)
 203  
     {
 204  2
         if (locale == null)
 205  0
             return false;
 206  
 
 207  5
         for (int i=0; i < SUPPORTED_LOCALES.length; i++)
 208  
         {
 209  5
             if (locale.equals(SUPPORTED_LOCALES[i]))
 210  2
                 return true;
 211  
         }
 212  
 
 213  0
         return false;
 214  
     }
 215  
 
 216  
     /**
 217  
      * Sets the dojo logging level. Similar to log4j style
 218  
      * log levels. 
 219  
      * @param level The string constant for the level, valid values
 220  
      *              are:
 221  
      *              <p>
 222  
      *              <ul>
 223  
      *              <li>{@link #BROWSER_LOG_DEBUG}</li>
 224  
      *              <li>{@link #BROWSER_LOG_INFO}</li>
 225  
      *              <li>{@link #BROWSER_LOG_WARNING}</li>
 226  
      *              <li>{@link #BROWSER_LOG_ERROR}</li>
 227  
      *              <li>{@link #BROWSER_LOG_CRITICAL}</li>
 228  
      *              </ul>
 229  
      *              </p>
 230  
      */
 231  
     public void setLogLevel(String level)
 232  
     {
 233  1
         Defense.notNull("level", level);
 234  
 
 235  1
         _browserLogLevel = level;
 236  1
     }
 237  
 
 238  
     /**
 239  
      * Allows for turning browser debugging on/off.
 240  
      *
 241  
      * @param debug If false, no logging output will be written.
 242  
      */
 243  
     public void setDebug(boolean debug)
 244  
     {
 245  1
         _debug = debug;
 246  1
     }
 247  
 
 248  
     /**
 249  
      * Turns off deep context level javascript debugging mode for dojo. This means
 250  
      * that exceptions/debug statements will show you line numbers from the actual 
 251  
      * javascript file that generated them instead of the normal default which is 
 252  
      * usually bootstrap.js .
 253  
      *
 254  
      * <p>The default value is false if not set.</p>
 255  
      *
 256  
      * <p>
 257  
      *  People should be wary of turning this on as it may cause problems
 258  
      *  under certain conditions, and you definitely don't ever want this 
 259  
      *  on in production. 
 260  
      * </p>
 261  
      *
 262  
      * @param value If true deep debugging will be turned on.
 263  
      */
 264  
     public void setDebugAtAllCosts(boolean value)
 265  
     {
 266  0
         _debugAtAllCosts = value;
 267  0
     }
 268  
 
 269  
     /**
 270  
      * Sets the html element node id of the element you would like all browser
 271  
      * debug content to go to.
 272  
      *
 273  
      * @param debugContainerId the debugContainerId to set
 274  
      */
 275  
     public void setDebugContainerId(String debugContainerId)
 276  
     {
 277  0
         _debugContainerId = debugContainerId;
 278  0
     }
 279  
 
 280  
     /**
 281  
      * Enables/disables the dojo.debug.console functionality which should redirect
 282  
      * most logging messages to your browsers javascript console. (if it supports 
 283  
      * one).
 284  
      *
 285  
      * <p>
 286  
      *  The debug console is disabled by default. Currently known supported 
 287  
      *  browsers are FireFox(having FireBug extension helps a great deal)/Opera/Safari.
 288  
      * </p>
 289  
      *
 290  
      * @param enabled Whether or not the enable debug console.
 291  
      */
 292  
     public void setConsoleEnabled(boolean enabled)
 293  
     {
 294  1
         _consoleEnabled = enabled;
 295  1
     }
 296  
 
 297  
     /**
 298  
      * Sets the dojo preventBackButtonFix djConfig configuration. This should
 299  
      * typically be avoided but is provided for flexibility.
 300  
      *
 301  
      * @param prevent
 302  
      *          Whether or not to prevent back button fix.
 303  
      */
 304  
     public void setPreventBackButtonFix(boolean prevent)
 305  
     {
 306  0
         _preventBackButtonFix = prevent;
 307  0
     }
 308  
 
 309  
     /**
 310  
      * Tells dojo whether or not to parse widgets by traversing the entire 
 311  
      * dom node of your document. It is highly reccomended that you keep this
 312  
      * at its default value of false.
 313  
      *
 314  
      * @param parseWidgets the parseWidgets to set
 315  
      */
 316  
     public void setParseWidgets(boolean parseWidgets)
 317  
     {
 318  0
         _parseWidgets = parseWidgets;
 319  0
     }
 320  
 
 321  
     /**
 322  
      * Sets a valid path to the base dojo javascript installation
 323  
      * directory.
 324  
      *
 325  
      * @param dojoSource
 326  
      *          Path to dojo source directory core "dojo.js" file.
 327  
      */
 328  
     public void setDojoSource(IAsset dojoSource)
 329  
     {
 330  2
         _dojoSource = dojoSource;
 331  2
     }
 332  
 
 333  
     public void setDojoFormSource(IAsset formSource)
 334  
     {
 335  0
         _dojoFormSource = formSource;
 336  0
     }
 337  
 
 338  
     public void setDojoWidgetSource(IAsset widgetSource)
 339  
     {
 340  0
         _dojoWidgetSource = widgetSource;
 341  0
     }
 342  
 
 343  
     /**
 344  
      * Sets the dojo baseRelativePath value.
 345  
      *
 346  
      * @param dojoPath
 347  
      *          The base path to dojo directory.
 348  
      */
 349  
     public void setDojoPath(IAsset dojoPath)
 350  
     {
 351  2
         _dojoPath = dojoPath;
 352  2
     }
 353  
 
 354  
     /**
 355  
      * Sets a valid base path to resolve tapestry core.js.
 356  
      *
 357  
      * @param tapestrySource
 358  
      *          Main tapestry core.js file.
 359  
      */
 360  
     public void setTapestrySource(IAsset tapestrySource)
 361  
     {
 362  2
         _tapestrySource = tapestrySource;
 363  2
     }
 364  
 
 365  
     /**
 366  
      * Sets the path to the tapestry javascript modules. (Needed for dojo to resolve the 
 367  
      * path to tapestry javascript, esp when overriding the default bundled dojo.)
 368  
      *
 369  
      * @param tapestryPath The path to tapestry.
 370  
      */
 371  
     public void setTapestryPath(IAsset tapestryPath)
 372  
     {
 373  2
         _tapestryPath = tapestryPath;
 374  2
     }
 375  
 }