1 package org.apache.turbine.util.template;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.ArrayList;
23
24 import org.apache.commons.configuration.Configuration;
25
26 import org.apache.commons.lang.StringUtils;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31 import org.apache.turbine.Turbine;
32 import org.apache.turbine.TurbineConstants;
33 import org.apache.turbine.services.pull.ApplicationTool;
34 import org.apache.turbine.util.RunData;
35
36 /***
37 * Template context tool that can be used to set various attributes of a
38 * HTML page. This tool does not automatically make the changes in the HTML
39 * page for you. You must use this tool in your layout template to retrieve
40 * the attributes.
41 * <p>
42 * The set/add methods are can be used from a screen template, action, screen
43 * class, layour template, or anywhere else. The get methods should be used in
44 * your layout template(s) to construct the appropriate HTML tags.
45 *<p>
46 * Example usage of this tool to build the HEAD and BODY tags in your layout
47 * templates:
48 * <p>
49 * <code>
50 * ## Set defaults for all pages using this layout. Anything set here can<br>
51 * ## be overridden in the screen template.<br>
52 * $page.setTitle("My default page title");<br>
53 * $page.setHttpEquiv("Content-Style-Type","text/css")<br>
54 * $page.addStyleSheet($content.getURI("myStyleSheet.css"))<br>
55 * $page.addScript($content.getURI("globalJavascriptCode.js"))<br>
56 * <br>
57 * ## build the HTML, HEAD, and BODY tags dynamically<br>
58 * <html><br>
59 * <head><br>
60 * #if( $page.Title != "" )<br>
61 * <title>$page.Title</title><br>
62 * #end<br>
63 * #foreach($metaTag in $page.MetaTags.keySet())<br>
64 * <meta name="$metaTag" content="$page.MetaTags.get($metaTag)"><br>
65 * #end<br>
66 * #foreach($httpEquiv in $page.HttpEquivs.keySet())<br>
67 * <meta http-equiv="$httpEquiv" content="$page.HttpEquivs.get($httpEquiv)"><br>
68 * #end<br>
69 * #foreach( $styleSheet in $page.StyleSheets )<br>
70 * <link rel="stylesheet" href="$styleSheet.Url"<br>
71 * #if($styleSheet.Type != "" ) type="$styleSheet.Type" #end<br>
72 * #if($styleSheet.Media != "") media="$styleSheet.Media" #end<br>
73 * #if($styleSheet.Title != "") title="$styleSheet.Title" #end<br>
74 * ><br>
75 * #end<br>
76 * #foreach( $script in $page.Scripts )<br>
77 * <script type="text/javascript" src="$script" language="JavaScript"></script><br>
78 * #end<br>
79 * </head><br>
80 *<br>
81 * ## Construct the body tag. Iterate through the body attributes to build the opening tag<br>
82 * <body<br>
83 * #foreach( $attributeName in $page.BodyAttributes.keySet() )<br>
84 * $attributeName = "$page.BodyAttributes.get($attributeName)"<br>
85 * #end<br>
86 * >
87 * </code>
88 * <p>
89 * Example usages of this tool in your screen templates:<br>
90 * <code>$page.addScript($content.getURI("myJavascript.js")<br>
91 * $page.setTitle("My page title")<br>
92 * $page.setHttpEquiv("refresh","5; URL=http://localhost/nextpage.html")</code>
93 *
94 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
95 * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
96 * @version $Id: HtmlPageAttributes.java 264148 2005-08-29 14:21:04Z henning $
97 */
98 public class HtmlPageAttributes
99 implements ApplicationTool
100 {
101 /*** Logging */
102 private static Log log = LogFactory.getLog(HtmlPageAttributes.class);
103
104 /*** The title */
105 private String title;
106
107 /*** Body Attributes */
108 private Map bodyAttributes = new HashMap();
109
110 /*** Script references */
111 private List scripts = new ArrayList();
112
113 /*** Stylesheet references */
114 private List styleSheets = new ArrayList();
115
116 /*** Inline styles */
117 private List styles = new ArrayList();
118
119 /*** Meta tags for the HEAD */
120 private Map metaTags = new HashMap();
121
122 /*** http-equiv tags */
123 private Map httpEquivs = new HashMap();
124
125 /*** Doctype */
126 private String doctype = null;
127
128 /***
129 * Default constructor. The init method must be called before use
130 */
131 public HtmlPageAttributes()
132 {
133 }
134
135 /***
136 * Construct a new instance with the given RunData object.
137 *
138 * @param data a RunData instance
139 */
140 public HtmlPageAttributes(RunData data)
141 {
142 init(data);
143 }
144
145 /***
146 * Initialise this instance with the given RunData object.
147 * (ApplicationTool method)
148 *
149 * @param data Assumed to be a RunData instance
150 */
151 public void init(Object data)
152 {
153 this.title = null;
154 this.bodyAttributes.clear();
155 this.scripts.clear();
156 this.styleSheets.clear();
157 this.styles.clear();
158 this.metaTags.clear();
159 this.httpEquivs.clear();
160 }
161
162 /***
163 * Refresh method - does nothing
164 */
165 public void refresh()
166 {
167
168 }
169
170 /***
171 * Set the title in the page. This returns an empty String so
172 * that the template doesn't complain about getting a null return
173 * value. Subsequent calls to this method will replace the current
174 * title.
175 *
176 * @param title A String with the title.
177 * @return a <code>HtmlPageAttributes</code> (self).
178 */
179 public HtmlPageAttributes setTitle(String title)
180 {
181 this.title = title;
182 return this;
183 }
184
185 /***
186 * Get the title in the page. This returns an empty String if
187 * empty so that the template doesn't complain about getting a null
188 * return value.
189 *
190 * @return A String with the title.
191 */
192 public String getTitle()
193 {
194 if (StringUtils.isEmpty(this.title))
195 {
196 return "";
197 }
198 return title;
199 }
200
201 /***
202 * Adds an attribute to the BODY tag.
203 *
204 * @param name A String.
205 * @param value A String.
206 * @return a <code>HtmlPageAttributes</code> (self).
207 * @deprecated Use addBodyAttribute instead.
208 */
209 public HtmlPageAttributes addAttribute(String name, String value)
210 {
211 log.info("Use of the addAttribute(name,value) method is deprecated. Please use " +
212 "addBodyAttribute(name,value) instead.");
213 return addBodyAttribute(name, value);
214 }
215
216 /***
217 * Adds an attribute to the BODY tag.
218 *
219 * @param name A String.
220 * @param value A String.
221 * @return a <code>HtmlPageAttributes</code> (self).
222 */
223 public HtmlPageAttributes addBodyAttribute(String name, String value)
224 {
225 this.bodyAttributes.put(name, value);
226 return this;
227 }
228
229 /***
230 * Returns the map of body attributes
231 *
232 * @return the map
233 */
234 public Map getBodyAttributes()
235 {
236 return this.bodyAttributes;
237 }
238
239 /***
240 * Adds a script reference
241 *
242 * @param scriptURL
243 * @return a <code>HtmlPageAttributes</code> (self).
244 */
245 public HtmlPageAttributes addScript(String scriptURL)
246 {
247 this.scripts.add(scriptURL);
248 return this;
249 }
250
251 /***
252 * Adds a script reference
253 *
254 * @param scriptURL
255 * @return a <code>HtmlPageAttributes</code> (self).
256 * @deprecated Use addScript instead
257 */
258 public HtmlPageAttributes setScript(String scriptURL)
259 {
260 log.info("Use of the setScript(scriptURL) method is deprecated. Please use " +
261 "addScript(scriptURL) instead.");
262 return addScript(scriptURL);
263 }
264
265 /***
266 * Returns a collection of script URLs
267 *
268 * @return list of String objects constainings URLs of javascript files
269 * to include
270 */
271 public List getScripts()
272 {
273 return this.scripts;
274 }
275
276 /***
277 * Adds a style sheet reference
278 *
279 * @param styleSheetURL URL of the style sheet
280 * @return a <code>HtmlPageAttributes</code> (self).
281 */
282 public HtmlPageAttributes addStyleSheet(String styleSheetURL)
283 {
284 addStyleSheet(styleSheetURL, "screen", null, "text/css");
285 return this;
286 }
287
288 /***
289 * Adds a style sheet reference
290 *
291 * @param styleSheetURL URL of the style sheet
292 * @param media name of the media
293 * @param title title of the stylesheet
294 * @param type content type
295 * @return a <code>HtmlPageAttributes</code> (self).
296 */
297 public HtmlPageAttributes addStyleSheet(String styleSheetURL,
298 String media, String title, String type)
299 {
300 StyleSheet ss = new StyleSheet(styleSheetURL);
301 ss.setMedia(media);
302 ss.setTitle(title);
303 ss.setType(type);
304 this.styleSheets.add(ss);
305 return this;
306 }
307
308 /***
309 * Adds a style sheet reference
310 *
311 * @param styleSheetURL
312 * @return a <code>HtmlPageAttributes</code> (self).
313 * @deprecated use addStyleSheet instead
314 */
315 public HtmlPageAttributes setStyleSheet(String styleSheetURL)
316 {
317 log.info("Use of the setStyleSheet(styleSheetURL) method is deprecated. Please use " +
318 "addStyleSheet(styleSheetURL) instead.");
319 return addStyleSheet(styleSheetURL);
320 }
321
322 /***
323 * Adds a style sheet reference
324 *
325 * @param styleSheetURL
326 * @param media name of the media
327 * @return a <code>HtmlPageAttributes</code> (self).
328 * @deprecated use addStyleSheet instead
329 */
330 public HtmlPageAttributes setStyleSheet(String styleSheetURL, String media)
331 {
332 log.info("Use of the setStyleSheet(styleSheetURL,media) method is deprecated. " +
333 "Please use addStyleSheet(styleSheetURL,media) instead.");
334 return addStyleSheet(styleSheetURL, media, null, "text/css");
335 }
336
337 /***
338 * Returns a collection of script URLs
339 *
340 * @return list StyleSheet objects (inner class)
341 */
342 public List getStyleSheets()
343 {
344 return this.styleSheets;
345 }
346
347 /***
348 * Adds a STYLE element to the HEAD of the page with the provided content.
349 *
350 * @param styleText The contents of the <code>style</code> tag.
351 * @return a <code>HtmlPageAttributes</code> (self).
352 * @deprecated use addStyle instead
353 */
354 public HtmlPageAttributes setStyle(String styleText)
355 {
356 log.info("Use of the setStyle(styleText) method is deprecated. Please use " +
357 "addStyle(styleText) instead.");
358 return addStyle(styleText);
359 }
360
361 /***
362 * Adds a STYLE element to the HEAD of the page with the provided content.
363 *
364 * @param styleText The contents of the <code>style</code> tag.
365 * @return a <code>HtmlPageAttributes</code> (self).
366 */
367 public HtmlPageAttributes addStyle(String styleText)
368 {
369 this.styles.add(styleText);
370 return this;
371 }
372
373 /***
374 * Returns a collection of styles
375 *
376 * @return list of String objects containing the contents of style tags
377 */
378 public List getStyles()
379 {
380 return this.styles;
381 }
382
383 /***
384 * Set a keywords META tag in the HEAD of the page.
385 *
386 * @param keywords A String.
387 * @return a <code>HtmlPageAttributes</code> (self).
388 */
389 public HtmlPageAttributes setKeywords(String keywords)
390 {
391 this.metaTags.put("keywords", keywords);
392 return this;
393 }
394
395 /***
396 * Sets a HttpEquiv META tag in the HEAD of the page, usage:
397 * <br><code>setHttpEquiv("refresh", "5; URL=http://localhost/nextpage.html")</code>
398 * <br><code>setHttpEquiv("Expires", "Tue, 20 Aug 1996 14:25:27 GMT")</code>
399 *
400 * @param httpEquiv The value to use for the http-equiv attribute.
401 * @param content The text for the content attribute of the meta tag.
402 * @return a <code>HtmlPageAttributes</code> (self).
403 */
404 public HtmlPageAttributes setHttpEquiv(String httpEquiv, String content)
405 {
406 this.httpEquivs.put(httpEquiv, content);
407 return this;
408 }
409
410 /***
411 * Add a description META tag to the HEAD of the page.
412 *
413 * @param description A String.
414 * @return a <code>HtmlPageAttributes</code> (self).
415 */
416 public HtmlPageAttributes setDescription(String description)
417 {
418 this.metaTags.put("description", description);
419 return this;
420 }
421
422 /***
423 * Set the background image for the BODY tag.
424 *
425 * @param url A String.
426 * @return a <code>HtmlPageAttributes</code> (self).
427 */
428 public HtmlPageAttributes setBackground(String url)
429 {
430 this.bodyAttributes.put("background", url);
431 return this;
432 }
433
434 /***
435 * Set the background color for the BODY tag. You can use either
436 * color names or color values (e.g. "white" or "#ffffff" or
437 * "ffffff").
438 *
439 * @param color A String.
440 * @return a <code>HtmlPageAttributes</code> (self).
441 */
442 public HtmlPageAttributes setBgColor(String color)
443 {
444 this.bodyAttributes.put("BGCOLOR", color);
445 return this;
446 }
447
448 /***
449 * Set the text color for the BODY tag. You can use either color
450 * names or color values (e.g. "white" or "#ffffff" or "ffffff").
451 *
452 * @param color A String.
453 * @return a <code>HtmlPageAttributes</code> (self).
454 */
455 public HtmlPageAttributes setTextColor(String color)
456 {
457 this.bodyAttributes.put("TEXT", color);
458 return this;
459 }
460
461 /***
462 * Set the link color for the BODY tag. You can use either color
463 * names or color values (e.g. "white" or "#ffffff" or "ffffff").
464 *
465 * @param color A String.
466 * @return a <code>HtmlPageAttributes</code> (self).
467 */
468 public HtmlPageAttributes setLinkColor(String color)
469 {
470 this.bodyAttributes.put("LINK", color);
471 return this;
472 }
473
474 /***
475 * Set the visited link color for the BODY tag.
476 *
477 * @param color A String.
478 * @return a <code>HtmlPageAttributes</code> (self).
479 */
480 public HtmlPageAttributes setVlinkColor(String color)
481 {
482 this.bodyAttributes.put("VLINK", color);
483 return this;
484 }
485
486 /***
487 * Set the active link color for the BODY tag.
488 *
489 * @param color A String.
490 * @return a <code>HtmlPageAttributes</code> (self).
491 */
492 public HtmlPageAttributes setAlinkColor(String color)
493 {
494 this.bodyAttributes.put("ALINK", color);
495 return this;
496 }
497
498 /***
499 * Gets the map of http equiv tags
500 *
501 * @return Map of http equiv names to the contents
502 */
503 public Map getHttpEquivs()
504 {
505 return this.httpEquivs;
506 }
507
508 /***
509 * Gets the map of meta tags
510 *
511 * @return Map of http equiv names to the contents
512 */
513 public Map getMetaTags()
514 {
515 return this.metaTags;
516 }
517
518 /***
519 * A dummy toString method that returns an empty string.
520 *
521 * @return An empty String ("").
522 */
523 public String toString()
524 {
525 return "";
526 }
527
528 /***
529 * Helper class to hold data about a stylesheet
530 */
531 public class StyleSheet
532 {
533 private String url;
534 private String title;
535 private String media;
536 private String type;
537
538 /***
539 * Constructor requiring the URL to be set
540 *
541 * @param url URL of the external style sheet
542 */
543 public StyleSheet(String url)
544 {
545 setUrl(url);
546 }
547
548 /***
549 * Gets the content type of the style sheet
550 *
551 * @return content type
552 */
553 public String getType()
554 {
555 return (StringUtils.isEmpty(type) ? "" : type);
556 }
557
558 /***
559 * Sets the content type of the style sheet
560 *
561 * @param type content type
562 */
563 public void setType(String type)
564 {
565 this.type = type;
566 }
567
568 /***
569 * @return String representation of the URL
570 */
571 public String getUrl()
572 {
573 return url;
574 }
575
576 /***
577 * Sets the URL of the external style sheet
578 *
579 * @param url The URL of the stylesheet
580 */
581 private void setUrl(String url)
582 {
583 this.url = url;
584 }
585
586 /***
587 * Gets the title of the style sheet
588 *
589 * @return title
590 */
591 public String getTitle()
592 {
593 return (StringUtils.isEmpty(title) ? "" : title);
594 }
595
596 /***
597 * Sets the title of the stylesheet
598 *
599 * @param title
600 */
601 public void setTitle(String title)
602 {
603 this.title = title;
604 }
605
606 /***
607 * Gets the media for which the stylesheet should be applied.
608 *
609 * @return name of the media
610 */
611 public String getMedia()
612 {
613 return (StringUtils.isEmpty(media) ? "" : media);
614 }
615
616 /***
617 * Sets the media for which the stylesheet should be applied.
618 *
619 * @param media name of the media
620 */
621 public void setMedia(String media)
622 {
623 this.media = media;
624 }
625
626 }
627
628 /***
629 * Retrieve the default Doctype as configured by the
630 * TurbineResources.peoperties
631 * default.doctype.root.element, default.doctype.identifier and
632 * default.doctype.url properties (defaults are "HTML",
633 * "-//W3C//DTD HTML 4.01 Transitional//EN" and
634 * "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd" respectively).
635 *
636 * @return the DOCTYPE tag constructed from the properties in
637 * TurbineResources.properties.
638 */
639 public String getDefaultDoctype()
640 {
641 Configuration conf = Turbine.getConfiguration();
642 if (doctype == null)
643 {
644 String tag = conf.getString(
645 TurbineConstants.DEFAULT_HTML_DOCTYPE_ROOT_ELEMENT_KEY,
646 TurbineConstants.DEFAULT_HTML_DOCTYPE_ROOT_ELEMENT_DEFAULT);
647
648 if (StringUtils.isEmpty(tag))
649 {
650 doctype = "";
651 }
652 else
653 {
654 String identifier = conf.getString(
655 TurbineConstants.DEFAULT_HTML_DOCTYPE_IDENTIFIER_KEY,
656 TurbineConstants.DEFAULT_HTML_DOCTYPE_IDENTIFIER_DEFAULT);
657
658 String uri = conf.getString(
659 TurbineConstants.DEFAULT_HTML_DOCTYPE_URI_KEY,
660 TurbineConstants.DEFAULT_HTML_DOCTYPE_URI_DEFAULT);
661
662 doctype = buildDoctype(tag, identifier, uri);
663 }
664 }
665 return doctype;
666 }
667
668 /***
669 * Build the doctype element.
670 *
671 * @param tag the tag whose DTD is being declared.
672 * @param identifier the identifier for the doctype declaration.
673 * @param uri the uri for the doctype declaration.
674 * @return the doctype.
675 */
676 private String buildDoctype(String tag, String identifier, String uri)
677 {
678 StringBuffer doctypeBuf = new StringBuffer("<!DOCTYPE ");
679 doctypeBuf.append(tag);
680
681 if (StringUtils.isNotEmpty(identifier))
682 {
683 doctypeBuf.append(" PUBLIC \"");
684 doctypeBuf.append(identifier);
685 doctypeBuf.append("\" \"");
686 }
687 else
688 {
689 doctypeBuf.append(" SYSTEM \"");
690 }
691
692 doctypeBuf.append(uri);
693 doctypeBuf.append("\">");
694
695 return doctypeBuf.toString();
696 }
697
698 }