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