1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.runtime;
19
20 import org.apache.struts2.jasper.JasperException;
21 import org.apache.struts2.jasper.compiler.Localizer;
22
23 import javax.servlet.RequestDispatcher;
24 import javax.servlet.ServletException;
25 import javax.servlet.ServletRequest;
26 import javax.servlet.ServletResponse;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.jsp.JspWriter;
29 import javax.servlet.jsp.PageContext;
30 import javax.servlet.jsp.tagext.BodyContent;
31 import java.beans.PropertyEditor;
32 import java.beans.PropertyEditorManager;
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.OutputStreamWriter;
36 import java.lang.reflect.Method;
37 import java.security.AccessController;
38 import java.security.PrivilegedActionException;
39 import java.security.PrivilegedExceptionAction;
40 import java.util.Enumeration;
41
42 /***
43 * Bunch of util methods that are used by code generated for useBean,
44 * getProperty and setProperty.
45 * <p/>
46 * The __begin, __end stuff is there so that the JSP engine can
47 * actually parse this file and inline them if people don't want
48 * runtime dependencies on this class. However, I'm not sure if that
49 * works so well right now. It got forgotten at some point. -akv
50 *
51 * @author Mandar Raje
52 * @author Shawn Bayern
53 */
54 public class JspRuntimeLibrary {
55
56 private static final String SERVLET_EXCEPTION
57 = "javax.servlet.error.exception";
58 private static final String JSP_EXCEPTION
59 = "javax.servlet.jsp.jspException";
60
61 protected static class PrivilegedIntrospectHelper
62 implements PrivilegedExceptionAction {
63
64 private Object bean;
65 private String prop;
66 private String value;
67 private ServletRequest request;
68 private String param;
69 private boolean ignoreMethodNF;
70
71 PrivilegedIntrospectHelper(Object bean, String prop,
72 String value, ServletRequest request,
73 String param, boolean ignoreMethodNF) {
74 this.bean = bean;
75 this.prop = prop;
76 this.value = value;
77 this.request = request;
78 this.param = param;
79 this.ignoreMethodNF = ignoreMethodNF;
80 }
81
82 public Object run() throws JasperException {
83 internalIntrospecthelper(
84 bean, prop, value, request, param, ignoreMethodNF);
85 return null;
86 }
87 }
88
89 /***
90 * Returns the value of the javax.servlet.error.exception request
91 * attribute value, if present, otherwise the value of the
92 * javax.servlet.jsp.jspException request attribute value.
93 * <p/>
94 * This method is called at the beginning of the generated servlet code
95 * for a JSP error page, when the "exception" implicit scripting language
96 * variable is initialized.
97 */
98 public static Throwable getThrowable(ServletRequest request) {
99 Throwable error = (Throwable) request.getAttribute(SERVLET_EXCEPTION);
100 if (error == null) {
101 error = (Throwable) request.getAttribute(JSP_EXCEPTION);
102 if (error != null) {
103
104
105
106
107
108
109
110 request.setAttribute(SERVLET_EXCEPTION, error);
111 }
112 }
113
114 return error;
115 }
116
117 public static boolean coerceToBoolean(String s) {
118 if (s == null || s.length() == 0)
119 return false;
120 else
121 return Boolean.valueOf(s).booleanValue();
122 }
123
124 public static byte coerceToByte(String s) {
125 if (s == null || s.length() == 0)
126 return (byte) 0;
127 else
128 return Byte.valueOf(s).byteValue();
129 }
130
131 public static char coerceToChar(String s) {
132 if (s == null || s.length() == 0) {
133 return (char) 0;
134 } else {
135
136 return (char) (int) s.charAt(0);
137 }
138 }
139
140 public static double coerceToDouble(String s) {
141 if (s == null || s.length() == 0)
142 return (double) 0;
143 else
144 return Double.valueOf(s).doubleValue();
145 }
146
147 public static float coerceToFloat(String s) {
148 if (s == null || s.length() == 0)
149 return (float) 0;
150 else
151 return Float.valueOf(s).floatValue();
152 }
153
154 public static int coerceToInt(String s) {
155 if (s == null || s.length() == 0)
156 return 0;
157 else
158 return Integer.valueOf(s).intValue();
159 }
160
161 public static short coerceToShort(String s) {
162 if (s == null || s.length() == 0)
163 return (short) 0;
164 else
165 return Short.valueOf(s).shortValue();
166 }
167
168 public static long coerceToLong(String s) {
169 if (s == null || s.length() == 0)
170 return (long) 0;
171 else
172 return Long.valueOf(s).longValue();
173 }
174
175 public static Object coerce(String s, Class target) {
176
177 boolean isNullOrEmpty = (s == null || s.length() == 0);
178
179 if (target == Boolean.class) {
180 if (isNullOrEmpty) {
181 s = "false";
182 }
183 return new Boolean(s);
184 } else if (target == Byte.class) {
185 if (isNullOrEmpty)
186 return new Byte((byte) 0);
187 else
188 return new Byte(s);
189 } else if (target == Character.class) {
190 if (isNullOrEmpty)
191 return new Character((char) 0);
192 else
193 return new Character(s.charAt(0));
194 } else if (target == Double.class) {
195 if (isNullOrEmpty)
196 return new Double(0);
197 else
198 return new Double(s);
199 } else if (target == Float.class) {
200 if (isNullOrEmpty)
201 return new Float(0);
202 else
203 return new Float(s);
204 } else if (target == Integer.class) {
205 if (isNullOrEmpty)
206 return new Integer(0);
207 else
208 return new Integer(s);
209 } else if (target == Short.class) {
210 if (isNullOrEmpty)
211 return new Short((short) 0);
212 else
213 return new Short(s);
214 } else if (target == Long.class) {
215 if (isNullOrEmpty)
216 return new Long(0);
217 else
218 return new Long(s);
219 } else {
220 return null;
221 }
222 }
223
224
225 public static Object convert(String propertyName, String s, Class t,
226 Class propertyEditorClass)
227 throws JasperException {
228 try {
229 if (s == null) {
230 if (t.equals(Boolean.class) || t.equals(Boolean.TYPE))
231 s = "false";
232 else
233 return null;
234 }
235 if (propertyEditorClass != null) {
236 return getValueFromBeanInfoPropertyEditor(
237 t, propertyName, s, propertyEditorClass);
238 } else if (t.equals(Boolean.class) || t.equals(Boolean.TYPE)) {
239 if (s.equalsIgnoreCase("on") || s.equalsIgnoreCase("true"))
240 s = "true";
241 else
242 s = "false";
243 return new Boolean(s);
244 } else if (t.equals(Byte.class) || t.equals(Byte.TYPE)) {
245 return new Byte(s);
246 } else if (t.equals(Character.class) || t.equals(Character.TYPE)) {
247 return s.length() > 0 ? new Character(s.charAt(0)) : null;
248 } else if (t.equals(Short.class) || t.equals(Short.TYPE)) {
249 return new Short(s);
250 } else if (t.equals(Integer.class) || t.equals(Integer.TYPE)) {
251 return new Integer(s);
252 } else if (t.equals(Float.class) || t.equals(Float.TYPE)) {
253 return new Float(s);
254 } else if (t.equals(Long.class) || t.equals(Long.TYPE)) {
255 return new Long(s);
256 } else if (t.equals(Double.class) || t.equals(Double.TYPE)) {
257 return new Double(s);
258 } else if (t.equals(String.class)) {
259 return s;
260 } else if (t.equals(java.io.File.class)) {
261 return new java.io.File(s);
262 } else if (t.getName().equals("java.lang.Object")) {
263 return new Object[]{s};
264 } else {
265 return getValueFromPropertyEditorManager(
266 t, propertyName, s);
267 }
268 } catch (Exception ex) {
269 throw new JasperException(ex);
270 }
271 }
272
273
274
275
276 public static void introspect(Object bean, ServletRequest request)
277 throws JasperException {
278 Enumeration e = request.getParameterNames();
279 while (e.hasMoreElements()) {
280 String name = (String) e.nextElement();
281 String value = request.getParameter(name);
282 introspecthelper(bean, name, value, request, name, true);
283 }
284 }
285
286
287
288
289 public static void introspecthelper(Object bean, String prop,
290 String value, ServletRequest request,
291 String param, boolean ignoreMethodNF)
292 throws JasperException {
293 if (System.getSecurityManager() != null) {
294 try {
295 PrivilegedIntrospectHelper dp =
296 new PrivilegedIntrospectHelper(
297 bean, prop, value, request, param, ignoreMethodNF);
298 AccessController.doPrivileged(dp);
299 } catch (PrivilegedActionException pe) {
300 Exception e = pe.getException();
301 throw (JasperException) e;
302 }
303 } else {
304 internalIntrospecthelper(
305 bean, prop, value, request, param, ignoreMethodNF);
306 }
307 }
308
309 private static void internalIntrospecthelper(Object bean, String prop,
310 String value, ServletRequest request,
311 String param, boolean ignoreMethodNF)
312 throws JasperException {
313 Method method = null;
314 Class type = null;
315 Class propertyEditorClass = null;
316 try {
317 java.beans.BeanInfo info
318 = java.beans.Introspector.getBeanInfo(bean.getClass());
319 if (info != null) {
320 java.beans.PropertyDescriptor pd[]
321 = info.getPropertyDescriptors();
322 for (int i = 0; i < pd.length; i++) {
323 if (pd[i].getName().equals(prop)) {
324 method = pd[i].getWriteMethod();
325 type = pd[i].getPropertyType();
326 propertyEditorClass = pd[i].getPropertyEditorClass();
327 break;
328 }
329 }
330 }
331 if (method != null) {
332 if (type.isArray()) {
333 if (request == null) {
334 throw new JasperException(
335 Localizer.getMessage("jsp.error.beans.setproperty.noindexset"));
336 }
337 Class t = type.getComponentType();
338 String[] values = request.getParameterValues(param);
339
340 if (values == null) return;
341 if (t.equals(String.class)) {
342 method.invoke(bean, new Object[]{values});
343 } else {
344 createTypedArray(prop, bean, method, values, t,
345 propertyEditorClass);
346 }
347 } else {
348 if (value == null || (param != null && value.equals(""))) return;
349 Object oval = convert(prop, value, type, propertyEditorClass);
350 if (oval != null)
351 method.invoke(bean, new Object[]{oval});
352 }
353 }
354 } catch (Exception ex) {
355 throw new JasperException(ex);
356 }
357 if (!ignoreMethodNF && (method == null)) {
358 if (type == null) {
359 throw new JasperException(
360 Localizer.getMessage("jsp.error.beans.noproperty",
361 prop,
362 bean.getClass().getName()));
363 } else {
364 throw new JasperException(
365 Localizer.getMessage("jsp.error.beans.nomethod.setproperty",
366 prop,
367 type.getName(),
368 bean.getClass().getName()));
369 }
370 }
371 }
372
373
374
375
376
377
378
379 public static String toString(Object o) {
380 return String.valueOf(o);
381 }
382
383 public static String toString(byte b) {
384 return new Byte(b).toString();
385 }
386
387 public static String toString(boolean b) {
388 return new Boolean(b).toString();
389 }
390
391 public static String toString(short s) {
392 return new Short(s).toString();
393 }
394
395 public static String toString(int i) {
396 return new Integer(i).toString();
397 }
398
399 public static String toString(float f) {
400 return new Float(f).toString();
401 }
402
403 public static String toString(long l) {
404 return new Long(l).toString();
405 }
406
407 public static String toString(double d) {
408 return new Double(d).toString();
409 }
410
411 public static String toString(char c) {
412 return new Character(c).toString();
413 }
414
415
416
417 /***
418 * Create a typed array.
419 * This is a special case where params are passed through
420 * the request and the property is indexed.
421 */
422 public static void createTypedArray(String propertyName,
423 Object bean,
424 Method method,
425 String[] values,
426 Class t,
427 Class propertyEditorClass)
428 throws JasperException {
429
430 try {
431 if (propertyEditorClass != null) {
432 Object[] tmpval = new Integer[values.length];
433 for (int i = 0; i < values.length; i++) {
434 tmpval[i] = getValueFromBeanInfoPropertyEditor(
435 t, propertyName, values[i], propertyEditorClass);
436 }
437 method.invoke(bean, new Object[]{tmpval});
438 } else if (t.equals(Integer.class)) {
439 Integer[] tmpval = new Integer[values.length];
440 for (int i = 0; i < values.length; i++)
441 tmpval[i] = new Integer(values[i]);
442 method.invoke(bean, new Object[]{tmpval});
443 } else if (t.equals(Byte.class)) {
444 Byte[] tmpval = new Byte[values.length];
445 for (int i = 0; i < values.length; i++)
446 tmpval[i] = new Byte(values[i]);
447 method.invoke(bean, new Object[]{tmpval});
448 } else if (t.equals(Boolean.class)) {
449 Boolean[] tmpval = new Boolean[values.length];
450 for (int i = 0; i < values.length; i++)
451 tmpval[i] = new Boolean(values[i]);
452 method.invoke(bean, new Object[]{tmpval});
453 } else if (t.equals(Short.class)) {
454 Short[] tmpval = new Short[values.length];
455 for (int i = 0; i < values.length; i++)
456 tmpval[i] = new Short(values[i]);
457 method.invoke(bean, new Object[]{tmpval});
458 } else if (t.equals(Long.class)) {
459 Long[] tmpval = new Long[values.length];
460 for (int i = 0; i < values.length; i++)
461 tmpval[i] = new Long(values[i]);
462 method.invoke(bean, new Object[]{tmpval});
463 } else if (t.equals(Double.class)) {
464 Double[] tmpval = new Double[values.length];
465 for (int i = 0; i < values.length; i++)
466 tmpval[i] = new Double(values[i]);
467 method.invoke(bean, new Object[]{tmpval});
468 } else if (t.equals(Float.class)) {
469 Float[] tmpval = new Float[values.length];
470 for (int i = 0; i < values.length; i++)
471 tmpval[i] = new Float(values[i]);
472 method.invoke(bean, new Object[]{tmpval});
473 } else if (t.equals(Character.class)) {
474 Character[] tmpval = new Character[values.length];
475 for (int i = 0; i < values.length; i++)
476 tmpval[i] = new Character(values[i].charAt(0));
477 method.invoke(bean, new Object[]{tmpval});
478 } else if (t.equals(int.class)) {
479 int[] tmpval = new int[values.length];
480 for (int i = 0; i < values.length; i++)
481 tmpval[i] = Integer.parseInt(values[i]);
482 method.invoke(bean, new Object[]{tmpval});
483 } else if (t.equals(byte.class)) {
484 byte[] tmpval = new byte[values.length];
485 for (int i = 0; i < values.length; i++)
486 tmpval[i] = Byte.parseByte(values[i]);
487 method.invoke(bean, new Object[]{tmpval});
488 } else if (t.equals(boolean.class)) {
489 boolean[] tmpval = new boolean[values.length];
490 for (int i = 0; i < values.length; i++)
491 tmpval[i] = (Boolean.valueOf(values[i])).booleanValue();
492 method.invoke(bean, new Object[]{tmpval});
493 } else if (t.equals(short.class)) {
494 short[] tmpval = new short[values.length];
495 for (int i = 0; i < values.length; i++)
496 tmpval[i] = Short.parseShort(values[i]);
497 method.invoke(bean, new Object[]{tmpval});
498 } else if (t.equals(long.class)) {
499 long[] tmpval = new long[values.length];
500 for (int i = 0; i < values.length; i++)
501 tmpval[i] = Long.parseLong(values[i]);
502 method.invoke(bean, new Object[]{tmpval});
503 } else if (t.equals(double.class)) {
504 double[] tmpval = new double[values.length];
505 for (int i = 0; i < values.length; i++)
506 tmpval[i] = Double.valueOf(values[i]).doubleValue();
507 method.invoke(bean, new Object[]{tmpval});
508 } else if (t.equals(float.class)) {
509 float[] tmpval = new float[values.length];
510 for (int i = 0; i < values.length; i++)
511 tmpval[i] = Float.valueOf(values[i]).floatValue();
512 method.invoke(bean, new Object[]{tmpval});
513 } else if (t.equals(char.class)) {
514 char[] tmpval = new char[values.length];
515 for (int i = 0; i < values.length; i++)
516 tmpval[i] = values[i].charAt(0);
517 method.invoke(bean, new Object[]{tmpval});
518 } else {
519 Object[] tmpval = new Integer[values.length];
520 for (int i = 0; i < values.length; i++) {
521 tmpval[i] =
522 getValueFromPropertyEditorManager(
523 t, propertyName, values[i]);
524 }
525 method.invoke(bean, new Object[]{tmpval});
526 }
527 } catch (Exception ex) {
528 throw new JasperException("error in invoking method", ex);
529 }
530 }
531
532 /***
533 * Escape special shell characters.
534 *
535 * @param unescString The string to shell-escape
536 * @return The escaped shell string.
537 */
538
539 public static String escapeQueryString(String unescString) {
540 if (unescString == null)
541 return null;
542
543 String escString = "";
544 String shellSpChars = "&;`'\"|*?~<>^()[]{}$//\n";
545
546 for (int index = 0; index < unescString.length(); index++) {
547 char nextChar = unescString.charAt(index);
548
549 if (shellSpChars.indexOf(nextChar) != -1)
550 escString += "//";
551
552 escString += nextChar;
553 }
554 return escString;
555 }
556
557 /***
558 * Decode an URL formatted string.
559 *
560 * @param encoded The string to decode.
561 * @return The decoded string.
562 */
563
564 public static String decode(String encoded) {
565
566 if (encoded == null) return null;
567 if (encoded.indexOf('%') == -1 && encoded.indexOf('+') == -1)
568 return encoded;
569
570
571 byte holdbuffer[] = new byte[encoded.length()];
572
573 int bufcount = 0;
574
575 for (int count = 0; count < encoded.length(); count++) {
576 char cur = encoded.charAt(count);
577 if (cur == '%') {
578 holdbuffer[bufcount++] =
579 (byte) Integer.parseInt(encoded.substring(count + 1, count + 3), 16);
580 if (count + 2 >= encoded.length())
581 count = encoded.length();
582 else
583 count += 2;
584 } else if (cur == '+') {
585 holdbuffer[bufcount++] = (byte) ' ';
586 } else {
587 holdbuffer[bufcount++] = (byte) cur;
588 }
589 }
590
591
592 return new String(holdbuffer, 0, bufcount);
593 }
594
595
596 public static Object handleGetProperty(Object o, String prop)
597 throws JasperException {
598 if (o == null) {
599 throw new JasperException(
600 Localizer.getMessage("jsp.error.beans.nullbean"));
601 }
602 Object value = null;
603 try {
604 Method method = getReadMethod(o.getClass(), prop);
605 value = method.invoke(o, null);
606 } catch (Exception ex) {
607 throw new JasperException(ex);
608 }
609 return value;
610 }
611
612
613
614
615 /***
616 * Use proprietaryEvaluate
617 * public static void handleSetPropertyExpression(Object bean,
618 * String prop, String expression, PageContext pageContext,
619 * VariableResolver variableResolver, FunctionMapper functionMapper )
620 * throws JasperException
621 * {
622 * try {
623 * Method method = getWriteMethod(bean.getClass(), prop);
624 * method.invoke(bean, new Object[] {
625 * pageContext.getExpressionEvaluator().evaluate(
626 * expression,
627 * method.getParameterTypes()[0],
628 * variableResolver,
629 * functionMapper,
630 * null )
631 * });
632 * } catch (Exception ex) {
633 * throw new JasperException(ex);
634 * }
635 * }
636 */
637 public static void handleSetPropertyExpression(Object bean,
638 String prop, String expression, PageContext pageContext,
639 ProtectedFunctionMapper functionMapper)
640 throws JasperException {
641 try {
642 Method method = getWriteMethod(bean.getClass(), prop);
643 method.invoke(bean, new Object[]{
644 PageContextImpl.proprietaryEvaluate(
645 expression,
646 method.getParameterTypes()[0],
647 pageContext,
648 functionMapper,
649 false)
650 });
651 } catch (Exception ex) {
652 throw new JasperException(ex);
653 }
654 }
655
656 public static void handleSetProperty(Object bean, String prop,
657 Object value)
658 throws JasperException {
659 try {
660 Method method = getWriteMethod(bean.getClass(), prop);
661 method.invoke(bean, new Object[]{value});
662 } catch (Exception ex) {
663 throw new JasperException(ex);
664 }
665 }
666
667 public static void handleSetProperty(Object bean, String prop,
668 int value)
669 throws JasperException {
670 try {
671 Method method = getWriteMethod(bean.getClass(), prop);
672 method.invoke(bean, new Object[]{new Integer(value)});
673 } catch (Exception ex) {
674 throw new JasperException(ex);
675 }
676 }
677
678 public static void handleSetProperty(Object bean, String prop,
679 short value)
680 throws JasperException {
681 try {
682 Method method = getWriteMethod(bean.getClass(), prop);
683 method.invoke(bean, new Object[]{new Short(value)});
684 } catch (Exception ex) {
685 throw new JasperException(ex);
686 }
687 }
688
689 public static void handleSetProperty(Object bean, String prop,
690 long value)
691 throws JasperException {
692 try {
693 Method method = getWriteMethod(bean.getClass(), prop);
694 method.invoke(bean, new Object[]{new Long(value)});
695 } catch (Exception ex) {
696 throw new JasperException(ex);
697 }
698 }
699
700 public static void handleSetProperty(Object bean, String prop,
701 double value)
702 throws JasperException {
703 try {
704 Method method = getWriteMethod(bean.getClass(), prop);
705 method.invoke(bean, new Object[]{new Double(value)});
706 } catch (Exception ex) {
707 throw new JasperException(ex);
708 }
709 }
710
711 public static void handleSetProperty(Object bean, String prop,
712 float value)
713 throws JasperException {
714 try {
715 Method method = getWriteMethod(bean.getClass(), prop);
716 method.invoke(bean, new Object[]{new Float(value)});
717 } catch (Exception ex) {
718 throw new JasperException(ex);
719 }
720 }
721
722 public static void handleSetProperty(Object bean, String prop,
723 char value)
724 throws JasperException {
725 try {
726 Method method = getWriteMethod(bean.getClass(), prop);
727 method.invoke(bean, new Object[]{new Character(value)});
728 } catch (Exception ex) {
729 throw new JasperException(ex);
730 }
731 }
732
733 public static void handleSetProperty(Object bean, String prop,
734 byte value)
735 throws JasperException {
736 try {
737 Method method = getWriteMethod(bean.getClass(), prop);
738 method.invoke(bean, new Object[]{new Byte(value)});
739 } catch (Exception ex) {
740 throw new JasperException(ex);
741 }
742 }
743
744 public static void handleSetProperty(Object bean, String prop,
745 boolean value)
746 throws JasperException {
747 try {
748 Method method = getWriteMethod(bean.getClass(), prop);
749 method.invoke(bean, new Object[]{new Boolean(value)});
750 } catch (Exception ex) {
751 throw new JasperException(ex);
752 }
753 }
754
755 public static Method getWriteMethod(Class beanClass, String prop)
756 throws JasperException {
757 Method method = null;
758 Class type = null;
759 try {
760 java.beans.BeanInfo info
761 = java.beans.Introspector.getBeanInfo(beanClass);
762 if (info != null) {
763 java.beans.PropertyDescriptor pd[]
764 = info.getPropertyDescriptors();
765 for (int i = 0; i < pd.length; i++) {
766 if (pd[i].getName().equals(prop)) {
767 method = pd[i].getWriteMethod();
768 type = pd[i].getPropertyType();
769 break;
770 }
771 }
772 } else {
773
774 throw new JasperException(
775 Localizer.getMessage("jsp.error.beans.nobeaninfo",
776 beanClass.getName()));
777 }
778 } catch (Exception ex) {
779 throw new JasperException(ex);
780 }
781 if (method == null) {
782 if (type == null) {
783 throw new JasperException(
784 Localizer.getMessage("jsp.error.beans.noproperty",
785 prop,
786 beanClass.getName()));
787 } else {
788 throw new JasperException(
789 Localizer.getMessage("jsp.error.beans.nomethod.setproperty",
790 prop,
791 type.getName(),
792 beanClass.getName()));
793 }
794 }
795 return method;
796 }
797
798 public static Method getReadMethod(Class beanClass, String prop)
799 throws JasperException {
800
801 Method method = null;
802 Class type = null;
803 try {
804 java.beans.BeanInfo info
805 = java.beans.Introspector.getBeanInfo(beanClass);
806 if (info != null) {
807 java.beans.PropertyDescriptor pd[]
808 = info.getPropertyDescriptors();
809 for (int i = 0; i < pd.length; i++) {
810 if (pd[i].getName().equals(prop)) {
811 method = pd[i].getReadMethod();
812 type = pd[i].getPropertyType();
813 break;
814 }
815 }
816 } else {
817
818 throw new JasperException(
819 Localizer.getMessage("jsp.error.beans.nobeaninfo",
820 beanClass.getName()));
821 }
822 } catch (Exception ex) {
823 throw new JasperException(ex);
824 }
825 if (method == null) {
826 if (type == null) {
827 throw new JasperException(
828 Localizer.getMessage("jsp.error.beans.noproperty", prop,
829 beanClass.getName()));
830 } else {
831 throw new JasperException(
832 Localizer.getMessage("jsp.error.beans.nomethod", prop,
833 beanClass.getName()));
834 }
835 }
836
837 return method;
838 }
839
840 //**********************************************************************
841 // PropertyEditor Support
842
843 public static Object getValueFromBeanInfoPropertyEditor(
844 Class attrClass, String attrName, String attrValue,
845 Class propertyEditorClass)
846 throws JasperException {
847 try {
848 PropertyEditor pe = (PropertyEditor) propertyEditorClass.newInstance();
849 pe.setAsText(attrValue);
850 return pe.getValue();
851 } catch (Exception ex) {
852 throw new JasperException(
853 Localizer.getMessage("jsp.error.beans.property.conversion",
854 attrValue, attrClass.getName(), attrName,
855 ex.getMessage()));
856 }
857 }
858
859 public static Object getValueFromPropertyEditorManager(
860 Class attrClass, String attrName, String attrValue)
861 throws JasperException {
862 try {
863 PropertyEditor propEditor =
864 PropertyEditorManager.findEditor(attrClass);
865 if (propEditor != null) {
866 propEditor.setAsText(attrValue);
867 return propEditor.getValue();
868 } else {
869 throw new IllegalArgumentException(
870 Localizer.getMessage("jsp.error.beans.propertyeditor.notregistered"));
871 }
872 } catch (IllegalArgumentException ex) {
873 throw new JasperException(
874 Localizer.getMessage("jsp.error.beans.property.conversion",
875 attrValue, attrClass.getName(), attrName,
876 ex.getMessage()));
877 }
878 }
879
880
881 // ************************************************************************
882 // General Purpose Runtime Methods
883 // ************************************************************************
884
885
886 /**
887 * Convert a possibly relative resource path into a context-relative
888 * resource path that starts with a '/'.
889 *
890 * @param request The servlet request we are processing
891 * @param relativePath The possibly relative resource path
892 */
893 public static String getContextRelativePath(ServletRequest request,
894 String relativePath) {
895
896 if (relativePath.startsWith("/"))
897 return (relativePath);
898 if (!(request instanceof HttpServletRequest))
899 return (relativePath);
900 HttpServletRequest hrequest = (HttpServletRequest) request;
901 String uri = (String)
902 request.getAttribute("javax.servlet.include.servlet_path");
903 if (uri != null) {
904 String pathInfo = (String)
905 request.getAttribute("javax.servlet.include.path_info");
906 if (pathInfo == null) {
907 if (uri.lastIndexOf('/') >= 0)
908 uri = uri.substring(0, uri.lastIndexOf('/'));
909 }
910 } else {
911 uri = hrequest.getServletPath();
912 if (uri.lastIndexOf('/') >= 0)
913 uri = uri.substring(0, uri.lastIndexOf('/'));
914 }
915 return uri + '/' + relativePath;
916
917 }
918
919
920 /***
921 * Perform a RequestDispatcher.include() operation, with optional flushing
922 * of the response beforehand.
923 *
924 * @param request The servlet request we are processing
925 * @param response The servlet response we are processing
926 * @param relativePath The relative path of the resource to be included
927 * @param out The Writer to whom we are currently writing
928 * @param flush Should we flush before the include is processed?
929 * @throws IOException if thrown by the included servlet
930 * @throws ServletException if thrown by the included servlet
931 */
932 public static void include(ServletRequest request,
933 ServletResponse response,
934 String relativePath,
935 JspWriter out,
936 boolean flush)
937 throws IOException, ServletException {
938
939 if (flush && !(out instanceof BodyContent))
940 out.flush();
941
942
943
944
945
946
947
948
949 String resourcePath = getContextRelativePath(request, relativePath);
950 RequestDispatcher rd = request.getRequestDispatcher(resourcePath);
951
952 rd.include(request,
953 new ServletResponseWrapperInclude(response, out));
954
955 }
956
957 /***
958 * URL encodes a string, based on the supplied character encoding.
959 * This performs the same function as java.next.URLEncode.encode
960 * in J2SDK1.4, and should be removed if the only platform supported
961 * is 1.4 or higher.
962 *
963 * @param s The String to be URL encoded.
964 * @param enc The character encoding
965 * @return The URL encoded String
966 */
967 public static String URLEncode(String s, String enc) {
968
969 if (s == null) {
970 return "null";
971 }
972
973 if (enc == null) {
974 enc = "ISO-8859-1";
975 }
976
977 StringBuffer out = new StringBuffer(s.length());
978 ByteArrayOutputStream buf = new ByteArrayOutputStream();
979 OutputStreamWriter writer = null;
980 try {
981 writer = new OutputStreamWriter(buf, enc);
982 } catch (java.io.UnsupportedEncodingException ex) {
983
984 writer = new OutputStreamWriter(buf);
985 }
986
987 for (int i = 0; i < s.length(); i++) {
988 int c = s.charAt(i);
989 if (c == ' ') {
990 out.append('+');
991 } else if (isSafeChar(c)) {
992 out.append((char) c);
993 } else {
994
995 try {
996 writer.write(c);
997 writer.flush();
998 } catch (IOException e) {
999 buf.reset();
1000 continue;
1001 }
1002 byte[] ba = buf.toByteArray();
1003 for (int j = 0; j < ba.length; j++) {
1004 out.append('%');
1005
1006 out.append(Character.forDigit((ba[j] >> 4) & 0xf, 16));
1007 out.append(Character.forDigit(ba[j] & 0xf, 16));
1008 }
1009 buf.reset();
1010 }
1011 }
1012 return out.toString();
1013 }
1014
1015 private static boolean isSafeChar(int c) {
1016 if (c >= 'a' && c <= 'z') {
1017 return true;
1018 }
1019 if (c >= 'A' && c <= 'Z') {
1020 return true;
1021 }
1022 if (c >= '0' && c <= '9') {
1023 return true;
1024 }
1025 if (c == '-' || c == '_' || c == '.' || c == '!' ||
1026 c == '~' || c == '*' || c == '\'' || c == '(' || c == ')') {
1027 return true;
1028 }
1029 return false;
1030 }
1031
1032 }