1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.struts2.jasper.tagplugins.jstl;
20
21 import javax.servlet.ServletOutputStream;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24 import javax.servlet.http.HttpServletResponseWrapper;
25 import javax.servlet.jsp.JspException;
26 import javax.servlet.jsp.JspTagException;
27 import javax.servlet.jsp.PageContext;
28 import java.io.*;
29 import java.util.Locale;
30
31 /***
32 * Util contains some often used consts, static methods and embedded class
33 * to support the JSTL tag plugin.
34 */
35
36 public class Util {
37
38 public static final String VALID_SCHEME_CHAR =
39 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-";
40
41 public static final String DEFAULT_ENCODING =
42 "ISO-8859-1";
43
44 public static final int HIGHEST_SPECIAL = '>';
45
46 public static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][];
47
48 static {
49 specialCharactersRepresentation['&'] = "&".toCharArray();
50 specialCharactersRepresentation['<'] = "<".toCharArray();
51 specialCharactersRepresentation['>'] = ">".toCharArray();
52 specialCharactersRepresentation['"'] = """.toCharArray();
53 specialCharactersRepresentation['\''] = "'".toCharArray();
54 }
55
56 /***
57 * Converts the given string description of a scope to the corresponding
58 * PageContext constant.
59 * <p/>
60 * The validity of the given scope has already been checked by the
61 * appropriate TLV.
62 *
63 * @param scope String description of scope
64 * @return PageContext constant corresponding to given scope description
65 * <p/>
66 * taken from org.apache.taglibs.standard.tag.common.core.Util
67 */
68 public static int getScope(String scope) {
69 int ret = PageContext.PAGE_SCOPE;
70
71 if ("request".equalsIgnoreCase(scope)) {
72 ret = PageContext.REQUEST_SCOPE;
73 } else if ("session".equalsIgnoreCase(scope)) {
74 ret = PageContext.SESSION_SCOPE;
75 } else if ("application".equalsIgnoreCase(scope)) {
76 ret = PageContext.APPLICATION_SCOPE;
77 }
78
79 return ret;
80 }
81
82 /***
83 * Returns <tt>true</tt> if our current URL is absolute,
84 * <tt>false</tt> otherwise.
85 * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
86 */
87 public static boolean isAbsoluteUrl(String url) {
88 if (url == null) {
89 return false;
90 }
91
92 int colonPos = url.indexOf(":");
93 if (colonPos == -1) {
94 return false;
95 }
96
97 for (int i = 0; i < colonPos; i++) {
98 if (VALID_SCHEME_CHAR.indexOf(url.charAt(i)) == -1) {
99 return false;
100 }
101 }
102
103 return true;
104 }
105
106 /***
107 * Get the value associated with a content-type attribute.
108 * Syntax defined in RFC 2045, section 5.1.
109 * taken from org.apache.taglibs.standard.tag.common.core.Util
110 */
111 public static String getContentTypeAttribute(String input, String name) {
112 int begin;
113 int end;
114 int index = input.toUpperCase().indexOf(name.toUpperCase());
115 if (index == -1) return null;
116 index = index + name.length();
117 index = input.indexOf('=', index);
118 if (index == -1) return null;
119 index += 1;
120 input = input.substring(index).trim();
121
122 if (input.charAt(0) == '"') {
123
124 begin = 1;
125 end = input.indexOf('"', begin);
126 if (end == -1) return null;
127 } else {
128 begin = 0;
129 end = input.indexOf(';');
130 if (end == -1) end = input.indexOf(' ');
131 if (end == -1) end = input.length();
132 }
133 return input.substring(begin, end).trim();
134 }
135
136 /***
137 * Strips a servlet session ID from <tt>url</tt>. The session ID
138 * is encoded as a URL "path parameter" beginning with "jsessionid=".
139 * We thus remove anything we find between ";jsessionid=" (inclusive)
140 * and either EOS or a subsequent ';' (exclusive).
141 * <p/>
142 * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
143 */
144 public static String stripSession(String url) {
145 StringBuffer u = new StringBuffer(url);
146 int sessionStart;
147 while ((sessionStart = u.toString().indexOf(";jsessionid=")) != -1) {
148 int sessionEnd = u.toString().indexOf(";", sessionStart + 1);
149 if (sessionEnd == -1)
150 sessionEnd = u.toString().indexOf("?", sessionStart + 1);
151 if (sessionEnd == -1)
152 sessionEnd = u.length();
153 u.delete(sessionStart, sessionEnd);
154 }
155 return u.toString();
156 }
157
158
159 /***
160 * Performs the following substring replacements
161 * (to facilitate output to XML/HTML pages):
162 * <p/>
163 * & -> &
164 * < -> <
165 * > -> >
166 * " -> "
167 * ' -> '
168 * <p/>
169 * See also OutSupport.writeEscapedXml().
170 * <p/>
171 * taken from org.apache.taglibs.standard.tag.common.core.Util
172 */
173 public static String escapeXml(String buffer) {
174 int start = 0;
175 int length = buffer.length();
176 char[] arrayBuffer = buffer.toCharArray();
177 StringBuffer escapedBuffer = null;
178
179 for (int i = 0; i < length; i++) {
180 char c = arrayBuffer[i];
181 if (c <= HIGHEST_SPECIAL) {
182 char[] escaped = specialCharactersRepresentation[c];
183 if (escaped != null) {
184
185 if (start == 0) {
186 escapedBuffer = new StringBuffer(length + 5);
187 }
188
189 if (start < i) {
190 escapedBuffer.append(arrayBuffer, start, i - start);
191 }
192 start = i + 1;
193
194 escapedBuffer.append(escaped);
195 }
196 }
197 }
198
199 if (start == 0) {
200 return buffer;
201 }
202
203 if (start < length) {
204 escapedBuffer.append(arrayBuffer, start, length - start);
205 }
206 return escapedBuffer.toString();
207 }
208
209 /***
210 * Utility methods
211 * taken from org.apache.taglibs.standard.tag.common.core.UrlSupport
212 */
213 public static String resolveUrl(
214 String url, String context, PageContext pageContext)
215 throws JspException {
216
217 if (isAbsoluteUrl(url))
218 return url;
219
220
221 HttpServletRequest request =
222 (HttpServletRequest) pageContext.getRequest();
223 if (context == null) {
224 if (url.startsWith("/"))
225 return (request.getContextPath() + url);
226 else
227 return url;
228 } else {
229 if (!context.startsWith("/") || !url.startsWith("/")) {
230 throw new JspTagException(
231 "In URL tags, when the \"context\" attribute is specified, values of both \"context\" and \"url\" must start with \"/\".");
232 }
233 if (context.equals("/")) {
234
235
236
237 return url;
238 } else {
239 return (context + url);
240 }
241 }
242 }
243
244 /***
245 * Wraps responses to allow us to retrieve results as Strings.
246 * mainly taken from org.apache.taglibs.standard.tag.common.core.importSupport
247 */
248 public static class ImportResponseWrapper extends HttpServletResponseWrapper {
249
250 private StringWriter sw = new StringWriter();
251 private ByteArrayOutputStream bos = new ByteArrayOutputStream();
252 private ServletOutputStream sos = new ServletOutputStream() {
253 public void write(int b) throws IOException {
254 bos.write(b);
255 }
256 };
257 private boolean isWriterUsed;
258 private boolean isStreamUsed;
259 private int status = 200;
260 private String charEncoding;
261
262 public ImportResponseWrapper(HttpServletResponse arg0) {
263 super(arg0);
264
265 }
266
267 public PrintWriter getWriter() {
268 if (isStreamUsed)
269 throw new IllegalStateException("Unexpected internal error during <import>: " +
270 "Target servlet called getWriter(), then getOutputStream()");
271 isWriterUsed = true;
272 return new PrintWriter(sw);
273 }
274
275 public ServletOutputStream getOutputStream() {
276 if (isWriterUsed)
277 throw new IllegalStateException("Unexpected internal error during <import>: " +
278 "Target servlet called getOutputStream(), then getWriter()");
279 isStreamUsed = true;
280 return sos;
281 }
282
283 /***
284 * Has no effect.
285 */
286 public void setContentType(String x) {
287
288 }
289
290 /***
291 * Has no effect.
292 */
293 public void setLocale(Locale x) {
294
295 }
296
297 public void setStatus(int status) {
298 this.status = status;
299 }
300
301 public int getStatus() {
302 return status;
303 }
304
305 public String getCharEncoding() {
306 return this.charEncoding;
307 }
308
309 public void setCharEncoding(String ce) {
310 this.charEncoding = ce;
311 }
312
313 public String getString() throws UnsupportedEncodingException {
314 if (isWriterUsed)
315 return sw.toString();
316 else if (isStreamUsed) {
317 if (this.charEncoding != null && !this.charEncoding.equals(""))
318 return bos.toString(charEncoding);
319 else
320 return bos.toString("ISO-8859-1");
321 } else
322 return "";
323 }
324 }
325
326 }