Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
AjaxShellDelegate |
|
| 2.5;2.5 |
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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | if (_debug) |
96 | { | |
97 | 0 | dojoConfig.put("isDebug", _debug); |
98 | } | |
99 | ||
100 | 0 | if (_debugAtAllCosts) |
101 | 0 | dojoConfig.put("debugAtAllCosts", _debugAtAllCosts); |
102 | 0 | if (_debugContainerId != null) |
103 | 0 | dojoConfig.put("debugContainerId", _debugContainerId); |
104 | ||
105 | 0 | IPage page = cycle.getPage(); |
106 | ||
107 | // The key to resolving everything out of the asset service | |
108 | ||
109 | 0 | if (_dojoPath!=null) |
110 | { | |
111 | 0 | dojoConfig.put("baseRelativePath", _dojoPath.buildURL()); |
112 | } | |
113 | ||
114 | 0 | if (page.hasFormComponents()) |
115 | { | |
116 | 0 | dojoConfig.put("preventBackButtonFix", _preventBackButtonFix); |
117 | } | |
118 | ||
119 | 0 | dojoConfig.put("parseWidgets", _parseWidgets); |
120 | 0 | if (_searchIds != null) |
121 | 0 | 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 | 0 | Locale locale = cycle.getPage().getLocale(); |
127 | ||
128 | 0 | String localeStr = locale.getLanguage().toLowerCase() |
129 | + ((locale.getCountry() != null && locale.getCountry().trim().length() > 0) | |
130 | ? "-" + locale.getCountry().toLowerCase() | |
131 | : ""); | |
132 | ||
133 | 0 | if (isLocaleSupported(localeStr)) |
134 | { | |
135 | 0 | dojoConfig.put("locale", localeStr); |
136 | } | |
137 | ||
138 | // Write the required script includes and dojo.requires | |
139 | ||
140 | 0 | StringBuffer str = new StringBuffer("<script type=\"text/javascript\">"); |
141 | 0 | 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 | 0 | if (_dojoSource!=null) |
148 | { | |
149 | 0 | str.append("<script type=\"text/javascript\" src=\"") |
150 | .append(_dojoSource.buildURL()).append("\"></script>"); | |
151 | } | |
152 | ||
153 | 0 | if (page.hasFormComponents() && _dojoFormSource!=null) |
154 | { | |
155 | 0 | str.append("<script type=\"text/javascript\" src=\"") |
156 | .append(_dojoFormSource.buildURL()).append("\"></script>"); | |
157 | } | |
158 | ||
159 | 0 | 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 | 0 | if (_debug) |
168 | { | |
169 | 0 | String logRequire = _consoleEnabled ? "dojo.require(\"dojo.debug.console\");" + SYSTEM_NEWLINE |
170 | : "dojo.require(\"dojo.logging.Logger\");" + SYSTEM_NEWLINE; | |
171 | ||
172 | 0 | str.append(SYSTEM_NEWLINE).append("<script type=\"text/javascript\">").append(SYSTEM_NEWLINE); |
173 | 0 | 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 | 0 | if (_tapestryPath!=null) |
182 | { | |
183 | 0 | String tapestryUrl = _tapestryPath.buildURL(); |
184 | 0 | if (tapestryUrl.endsWith("/")) |
185 | { | |
186 | 0 | tapestryUrl = tapestryUrl.substring(0, tapestryUrl.length() - 1); |
187 | } | |
188 | ||
189 | 0 | 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 | 0 | str.append("</script>").append(SYSTEM_NEWLINE); |
193 | } | |
194 | ||
195 | // include core tapestry.js package | |
196 | ||
197 | 0 | if (_tapestrySource!=null) |
198 | { | |
199 | 0 | str.append("<script type=\"text/javascript\" src=\"") |
200 | .append(_tapestrySource.buildURL()).append("\"></script>"); | |
201 | } | |
202 | ||
203 | // namespace registration | |
204 | ||
205 | 0 | str.append(SYSTEM_NEWLINE).append("<script type=\"text/javascript\">").append(SYSTEM_NEWLINE); |
206 | 0 | 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 | 0 | writer.printRaw(str.toString()); |
212 | 0 | writer.println(); |
213 | 0 | } |
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 | 0 | if (locale == null) |
227 | 0 | return false; |
228 | ||
229 | 0 | for (int i=0; i < SUPPORTED_LOCALES.length; i++) |
230 | { | |
231 | 0 | if (locale.equals(SUPPORTED_LOCALES[i])) |
232 | 0 | 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 | 0 | Defense.notNull("level", level); |
256 | ||
257 | 0 | _browserLogLevel = level; |
258 | 0 | } |
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 | 0 | _debug = debug; |
268 | 0 | } |
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 | 0 | _consoleEnabled = enabled; |
317 | 0 | } |
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 | 0 | _searchIds = searchIds; |
352 | 0 | } |
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 | 0 | _dojoSource = dojoSource; |
364 | 0 | } |
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 | 0 | _dojoPath = dojoPath; |
385 | 0 | } |
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 | 0 | _tapestrySource = tapestrySource; |
396 | 0 | } |
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 | 0 | _tapestryPath = tapestryPath; |
407 | 0 | } |
408 | } |