1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.taglib.html;
22
23 import org.apache.struts.Globals;
24 import org.apache.struts.taglib.TagUtils;
25 import org.apache.struts.util.MessageResources;
26
27 import javax.servlet.jsp.JspException;
28 import javax.servlet.jsp.PageContext;
29 import javax.servlet.jsp.tagext.TagSupport;
30
31 import java.util.Locale;
32
33 /**
34 * Renders an HTML <html> element with appropriate language attributes if
35 * there is a current Locale available in the user's session.
36 *
37 * @version $Rev: 482895 $ $Date: 2005-08-21 19:08:45 -0400 (Sun, 21 Aug 2005)
38 * $
39 */
40 public class HtmlTag extends TagSupport {
41
42
43 /**
44 * The message resources for this package.
45 */
46 protected static MessageResources messages =
47 MessageResources.getMessageResources(Constants.Package
48 + ".LocalStrings");
49
50 /**
51 * Are we rendering an xhtml page?
52 */
53 protected boolean xhtml = false;
54
55 /**
56 * Are we rendering a lang attribute?
57 *
58 * @since Struts 1.2
59 */
60 protected boolean lang = false;
61
62 public boolean getXhtml() {
63 return this.xhtml;
64 }
65
66 public void setXhtml(boolean xhtml) {
67 this.xhtml = xhtml;
68 }
69
70 /**
71 * Returns true if the tag should render a lang attribute.
72 *
73 * @since Struts 1.2
74 */
75 public boolean getLang() {
76 return this.lang;
77 }
78
79 /**
80 * Sets whether the tag should render a lang attribute.
81 *
82 * @since Struts 1.2
83 */
84 public void setLang(boolean lang) {
85 this.lang = lang;
86 }
87
88 /**
89 * Process the start of this tag.
90 *
91 * @throws JspException if a JSP exception has occurred
92 */
93 public int doStartTag() throws JspException {
94 TagUtils.getInstance().write(this.pageContext,
95 this.renderHtmlStartElement());
96
97 return EVAL_BODY_INCLUDE;
98 }
99
100 /**
101 * Renders an <html> element with appropriate language attributes.
102 *
103 * @since Struts 1.2
104 */
105 protected String renderHtmlStartElement() {
106 StringBuffer sb = new StringBuffer("<html");
107
108 String language = null;
109 String country = "";
110
111 Locale currentLocale =
112 TagUtils.getInstance().getUserLocale(pageContext, Globals.LOCALE_KEY);
113
114 language = currentLocale.getLanguage();
115 country = currentLocale.getCountry();
116
117 boolean validLanguage = isValidRfc2616(language);
118 boolean validCountry = isValidRfc2616(country);
119
120 if (this.xhtml) {
121 this.pageContext.setAttribute(Globals.XHTML_KEY, "true",
122 PageContext.PAGE_SCOPE);
123
124 sb.append(" xmlns=\"http://www.w3.org/1999/xhtml\"");
125 }
126
127 if ((this.lang || this.xhtml) && validLanguage) {
128 sb.append(" lang=\"");
129 sb.append(language);
130
131 if (validCountry) {
132 sb.append("-");
133 sb.append(country);
134 }
135
136 sb.append("\"");
137 }
138
139 if (this.xhtml && validLanguage) {
140 sb.append(" xml:lang=\"");
141 sb.append(language);
142
143 if (validCountry) {
144 sb.append("-");
145 sb.append(country);
146 }
147
148 sb.append("\"");
149 }
150
151 sb.append(">");
152
153 return sb.toString();
154 }
155
156 /**
157 * Process the end of this tag.
158 *
159 * @throws JspException if a JSP exception has occurred
160 */
161 public int doEndTag() throws JspException {
162 TagUtils.getInstance().write(pageContext, "</html>");
163
164
165 return (EVAL_PAGE);
166 }
167
168 /**
169 * Release any acquired resources.
170 */
171 public void release() {
172 this.xhtml = false;
173 this.lang = false;
174 }
175
176 /**
177 * Check whether the value contains valid characters for the
178 * "Accept-Language" header according to RFC 2616 (section 14.4).
179 *
180 * @param value The value to check
181 * @return <code>true</code> if valid, otherwise <code>false</code>
182 */
183 private boolean isValidRfc2616(String value) {
184 if (value == null || value.length() == 0) {
185 return false;
186 }
187 for (int i = 0; i < value.length(); i++) {
188 char c = value.charAt(i);
189
190 if (!(Character.isLetter(c) || c == '-')) {
191 return false;
192 }
193 }
194 return true;
195 }
196 }