0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.jasper.runtime;
0019:
0020: import java.beans.PropertyEditor;
0021: import java.beans.PropertyEditorManager;
0022: import java.io.ByteArrayOutputStream;
0023: import java.io.IOException;
0024: import java.io.OutputStreamWriter;
0025: import java.lang.reflect.Method;
0026: import java.security.AccessController;
0027: import java.security.PrivilegedActionException;
0028: import java.security.PrivilegedExceptionAction;
0029: import java.util.Enumeration;
0030:
0031: import javax.servlet.RequestDispatcher;
0032: import javax.servlet.ServletException;
0033: import javax.servlet.ServletRequest;
0034: import javax.servlet.ServletResponse;
0035: import javax.servlet.http.HttpServletRequest;
0036: import javax.servlet.jsp.JspWriter;
0037: import javax.servlet.jsp.PageContext;
0038: import javax.servlet.jsp.tagext.BodyContent;
0039:
0040: import org.apache.jasper.Constants;
0041: import org.apache.jasper.JasperException;
0042: import org.apache.jasper.compiler.Localizer;
0043:
0044: /**
0045: * Bunch of util methods that are used by code generated for useBean,
0046: * getProperty and setProperty.
0047: *
0048: * The __begin, __end stuff is there so that the JSP engine can
0049: * actually parse this file and inline them if people don't want
0050: * runtime dependencies on this class. However, I'm not sure if that
0051: * works so well right now. It got forgotten at some point. -akv
0052: *
0053: * @author Mandar Raje
0054: * @author Shawn Bayern
0055: */
0056: public class JspRuntimeLibrary {
0057:
0058: private static final String SERVLET_EXCEPTION = "javax.servlet.error.exception";
0059: private static final String JSP_EXCEPTION = "javax.servlet.jsp.jspException";
0060:
0061: protected static class PrivilegedIntrospectHelper implements
0062: PrivilegedExceptionAction {
0063:
0064: private Object bean;
0065: private String prop;
0066: private String value;
0067: private ServletRequest request;
0068: private String param;
0069: private boolean ignoreMethodNF;
0070:
0071: PrivilegedIntrospectHelper(Object bean, String prop,
0072: String value, ServletRequest request, String param,
0073: boolean ignoreMethodNF) {
0074: this .bean = bean;
0075: this .prop = prop;
0076: this .value = value;
0077: this .request = request;
0078: this .param = param;
0079: this .ignoreMethodNF = ignoreMethodNF;
0080: }
0081:
0082: public Object run() throws JasperException {
0083: internalIntrospecthelper(bean, prop, value, request, param,
0084: ignoreMethodNF);
0085: return null;
0086: }
0087: }
0088:
0089: /**
0090: * Returns the value of the javax.servlet.error.exception request
0091: * attribute value, if present, otherwise the value of the
0092: * javax.servlet.jsp.jspException request attribute value.
0093: *
0094: * This method is called at the beginning of the generated servlet code
0095: * for a JSP error page, when the "exception" implicit scripting language
0096: * variable is initialized.
0097: */
0098: public static Throwable getThrowable(ServletRequest request) {
0099: Throwable error = (Throwable) request
0100: .getAttribute(SERVLET_EXCEPTION);
0101: if (error == null) {
0102: error = (Throwable) request.getAttribute(JSP_EXCEPTION);
0103: if (error != null) {
0104: /*
0105: * The only place that sets JSP_EXCEPTION is
0106: * PageContextImpl.handlePageException(). It really should set
0107: * SERVLET_EXCEPTION, but that would interfere with the
0108: * ErrorReportValve. Therefore, if JSP_EXCEPTION is set, we
0109: * need to set SERVLET_EXCEPTION.
0110: */
0111: request.setAttribute(SERVLET_EXCEPTION, error);
0112: }
0113: }
0114:
0115: return error;
0116: }
0117:
0118: public static boolean coerceToBoolean(String s) {
0119: if (s == null || s.length() == 0)
0120: return false;
0121: else
0122: return Boolean.valueOf(s).booleanValue();
0123: }
0124:
0125: public static byte coerceToByte(String s) {
0126: if (s == null || s.length() == 0)
0127: return (byte) 0;
0128: else
0129: return Byte.valueOf(s).byteValue();
0130: }
0131:
0132: public static char coerceToChar(String s) {
0133: if (s == null || s.length() == 0) {
0134: return (char) 0;
0135: } else {
0136: // this trick avoids escaping issues
0137: return (char) (int) s.charAt(0);
0138: }
0139: }
0140:
0141: public static double coerceToDouble(String s) {
0142: if (s == null || s.length() == 0)
0143: return (double) 0;
0144: else
0145: return Double.valueOf(s).doubleValue();
0146: }
0147:
0148: public static float coerceToFloat(String s) {
0149: if (s == null || s.length() == 0)
0150: return (float) 0;
0151: else
0152: return Float.valueOf(s).floatValue();
0153: }
0154:
0155: public static int coerceToInt(String s) {
0156: if (s == null || s.length() == 0)
0157: return 0;
0158: else
0159: return Integer.valueOf(s).intValue();
0160: }
0161:
0162: public static short coerceToShort(String s) {
0163: if (s == null || s.length() == 0)
0164: return (short) 0;
0165: else
0166: return Short.valueOf(s).shortValue();
0167: }
0168:
0169: public static long coerceToLong(String s) {
0170: if (s == null || s.length() == 0)
0171: return (long) 0;
0172: else
0173: return Long.valueOf(s).longValue();
0174: }
0175:
0176: public static Object coerce(String s, Class target) {
0177:
0178: boolean isNullOrEmpty = (s == null || s.length() == 0);
0179:
0180: if (target == Boolean.class) {
0181: if (isNullOrEmpty) {
0182: s = "false";
0183: }
0184: return new Boolean(s);
0185: } else if (target == Byte.class) {
0186: if (isNullOrEmpty)
0187: return new Byte((byte) 0);
0188: else
0189: return new Byte(s);
0190: } else if (target == Character.class) {
0191: if (isNullOrEmpty)
0192: return new Character((char) 0);
0193: else
0194: return new Character(s.charAt(0));
0195: } else if (target == Double.class) {
0196: if (isNullOrEmpty)
0197: return new Double(0);
0198: else
0199: return new Double(s);
0200: } else if (target == Float.class) {
0201: if (isNullOrEmpty)
0202: return new Float(0);
0203: else
0204: return new Float(s);
0205: } else if (target == Integer.class) {
0206: if (isNullOrEmpty)
0207: return new Integer(0);
0208: else
0209: return new Integer(s);
0210: } else if (target == Short.class) {
0211: if (isNullOrEmpty)
0212: return new Short((short) 0);
0213: else
0214: return new Short(s);
0215: } else if (target == Long.class) {
0216: if (isNullOrEmpty)
0217: return new Long(0);
0218: else
0219: return new Long(s);
0220: } else {
0221: return null;
0222: }
0223: }
0224:
0225: // __begin convertMethod
0226: public static Object convert(String propertyName, String s,
0227: Class t, Class propertyEditorClass) throws JasperException {
0228: try {
0229: if (s == null) {
0230: if (t.equals(Boolean.class) || t.equals(Boolean.TYPE))
0231: s = "false";
0232: else
0233: return null;
0234: }
0235: if (propertyEditorClass != null) {
0236: return getValueFromBeanInfoPropertyEditor(t,
0237: propertyName, s, propertyEditorClass);
0238: } else if (t.equals(Boolean.class)
0239: || t.equals(Boolean.TYPE)) {
0240: if (s.equalsIgnoreCase("on")
0241: || s.equalsIgnoreCase("true"))
0242: s = "true";
0243: else
0244: s = "false";
0245: return new Boolean(s);
0246: } else if (t.equals(Byte.class) || t.equals(Byte.TYPE)) {
0247: return new Byte(s);
0248: } else if (t.equals(Character.class)
0249: || t.equals(Character.TYPE)) {
0250: return s.length() > 0 ? new Character(s.charAt(0))
0251: : null;
0252: } else if (t.equals(Short.class) || t.equals(Short.TYPE)) {
0253: return new Short(s);
0254: } else if (t.equals(Integer.class)
0255: || t.equals(Integer.TYPE)) {
0256: return new Integer(s);
0257: } else if (t.equals(Float.class) || t.equals(Float.TYPE)) {
0258: return new Float(s);
0259: } else if (t.equals(Long.class) || t.equals(Long.TYPE)) {
0260: return new Long(s);
0261: } else if (t.equals(Double.class) || t.equals(Double.TYPE)) {
0262: return new Double(s);
0263: } else if (t.equals(String.class)) {
0264: return s;
0265: } else if (t.equals(java.io.File.class)) {
0266: return new java.io.File(s);
0267: } else if (t.getName().equals("java.lang.Object")) {
0268: return new Object[] { s };
0269: } else {
0270: return getValueFromPropertyEditorManager(t,
0271: propertyName, s);
0272: }
0273: } catch (Exception ex) {
0274: throw new JasperException(ex);
0275: }
0276: }
0277:
0278: // __end convertMethod
0279:
0280: // __begin introspectMethod
0281: public static void introspect(Object bean, ServletRequest request)
0282: throws JasperException {
0283: Enumeration e = request.getParameterNames();
0284: while (e.hasMoreElements()) {
0285: String name = (String) e.nextElement();
0286: String value = request.getParameter(name);
0287: introspecthelper(bean, name, value, request, name, true);
0288: }
0289: }
0290:
0291: // __end introspectMethod
0292:
0293: // __begin introspecthelperMethod
0294: public static void introspecthelper(Object bean, String prop,
0295: String value, ServletRequest request, String param,
0296: boolean ignoreMethodNF) throws JasperException {
0297: if (Constants.IS_SECURITY_ENABLED) {
0298: try {
0299: PrivilegedIntrospectHelper dp = new PrivilegedIntrospectHelper(
0300: bean, prop, value, request, param,
0301: ignoreMethodNF);
0302: AccessController.doPrivileged(dp);
0303: } catch (PrivilegedActionException pe) {
0304: Exception e = pe.getException();
0305: throw (JasperException) e;
0306: }
0307: } else {
0308: internalIntrospecthelper(bean, prop, value, request, param,
0309: ignoreMethodNF);
0310: }
0311: }
0312:
0313: private static void internalIntrospecthelper(Object bean,
0314: String prop, String value, ServletRequest request,
0315: String param, boolean ignoreMethodNF)
0316: throws JasperException {
0317: Method method = null;
0318: Class type = null;
0319: Class propertyEditorClass = null;
0320: try {
0321: java.beans.BeanInfo info = java.beans.Introspector
0322: .getBeanInfo(bean.getClass());
0323: if (info != null) {
0324: java.beans.PropertyDescriptor pd[] = info
0325: .getPropertyDescriptors();
0326: for (int i = 0; i < pd.length; i++) {
0327: if (pd[i].getName().equals(prop)) {
0328: method = pd[i].getWriteMethod();
0329: type = pd[i].getPropertyType();
0330: propertyEditorClass = pd[i]
0331: .getPropertyEditorClass();
0332: break;
0333: }
0334: }
0335: }
0336: if (method != null) {
0337: if (type.isArray()) {
0338: if (request == null) {
0339: throw new JasperException(
0340: Localizer
0341: .getMessage("jsp.error.beans.setproperty.noindexset"));
0342: }
0343: Class t = type.getComponentType();
0344: String[] values = request.getParameterValues(param);
0345: //XXX Please check.
0346: if (values == null)
0347: return;
0348: if (t.equals(String.class)) {
0349: method.invoke(bean, new Object[] { values });
0350: } else {
0351: Object tmpval = null;
0352: createTypedArray(prop, bean, method, values, t,
0353: propertyEditorClass);
0354: }
0355: } else {
0356: if (value == null
0357: || (param != null && value.equals("")))
0358: return;
0359: Object oval = convert(prop, value, type,
0360: propertyEditorClass);
0361: if (oval != null)
0362: method.invoke(bean, new Object[] { oval });
0363: }
0364: }
0365: } catch (Exception ex) {
0366: throw new JasperException(ex);
0367: }
0368: if (!ignoreMethodNF && (method == null)) {
0369: if (type == null) {
0370: throw new JasperException(Localizer.getMessage(
0371: "jsp.error.beans.noproperty", prop, bean
0372: .getClass().getName()));
0373: } else {
0374: throw new JasperException(Localizer.getMessage(
0375: "jsp.error.beans.nomethod.setproperty", prop,
0376: type.getName(), bean.getClass().getName()));
0377: }
0378: }
0379: }
0380:
0381: // __end introspecthelperMethod
0382:
0383: //-------------------------------------------------------------------
0384: // functions to convert builtin Java data types to string.
0385: //-------------------------------------------------------------------
0386: // __begin toStringMethod
0387: public static String toString(Object o) {
0388: return String.valueOf(o);
0389: }
0390:
0391: public static String toString(byte b) {
0392: return new Byte(b).toString();
0393: }
0394:
0395: public static String toString(boolean b) {
0396: return new Boolean(b).toString();
0397: }
0398:
0399: public static String toString(short s) {
0400: return new Short(s).toString();
0401: }
0402:
0403: public static String toString(int i) {
0404: return new Integer(i).toString();
0405: }
0406:
0407: public static String toString(float f) {
0408: return new Float(f).toString();
0409: }
0410:
0411: public static String toString(long l) {
0412: return new Long(l).toString();
0413: }
0414:
0415: public static String toString(double d) {
0416: return new Double(d).toString();
0417: }
0418:
0419: public static String toString(char c) {
0420: return new Character(c).toString();
0421: }
0422:
0423: // __end toStringMethod
0424:
0425: /**
0426: * Create a typed array.
0427: * This is a special case where params are passed through
0428: * the request and the property is indexed.
0429: */
0430: public static void createTypedArray(String propertyName,
0431: Object bean, Method method, String[] values, Class t,
0432: Class propertyEditorClass) throws JasperException {
0433:
0434: try {
0435: if (propertyEditorClass != null) {
0436: Object[] tmpval = new Integer[values.length];
0437: for (int i = 0; i < values.length; i++) {
0438: tmpval[i] = getValueFromBeanInfoPropertyEditor(t,
0439: propertyName, values[i],
0440: propertyEditorClass);
0441: }
0442: method.invoke(bean, new Object[] { tmpval });
0443: } else if (t.equals(Integer.class)) {
0444: Integer[] tmpval = new Integer[values.length];
0445: for (int i = 0; i < values.length; i++)
0446: tmpval[i] = new Integer(values[i]);
0447: method.invoke(bean, new Object[] { tmpval });
0448: } else if (t.equals(Byte.class)) {
0449: Byte[] tmpval = new Byte[values.length];
0450: for (int i = 0; i < values.length; i++)
0451: tmpval[i] = new Byte(values[i]);
0452: method.invoke(bean, new Object[] { tmpval });
0453: } else if (t.equals(Boolean.class)) {
0454: Boolean[] tmpval = new Boolean[values.length];
0455: for (int i = 0; i < values.length; i++)
0456: tmpval[i] = new Boolean(values[i]);
0457: method.invoke(bean, new Object[] { tmpval });
0458: } else if (t.equals(Short.class)) {
0459: Short[] tmpval = new Short[values.length];
0460: for (int i = 0; i < values.length; i++)
0461: tmpval[i] = new Short(values[i]);
0462: method.invoke(bean, new Object[] { tmpval });
0463: } else if (t.equals(Long.class)) {
0464: Long[] tmpval = new Long[values.length];
0465: for (int i = 0; i < values.length; i++)
0466: tmpval[i] = new Long(values[i]);
0467: method.invoke(bean, new Object[] { tmpval });
0468: } else if (t.equals(Double.class)) {
0469: Double[] tmpval = new Double[values.length];
0470: for (int i = 0; i < values.length; i++)
0471: tmpval[i] = new Double(values[i]);
0472: method.invoke(bean, new Object[] { tmpval });
0473: } else if (t.equals(Float.class)) {
0474: Float[] tmpval = new Float[values.length];
0475: for (int i = 0; i < values.length; i++)
0476: tmpval[i] = new Float(values[i]);
0477: method.invoke(bean, new Object[] { tmpval });
0478: } else if (t.equals(Character.class)) {
0479: Character[] tmpval = new Character[values.length];
0480: for (int i = 0; i < values.length; i++)
0481: tmpval[i] = new Character(values[i].charAt(0));
0482: method.invoke(bean, new Object[] { tmpval });
0483: } else if (t.equals(int.class)) {
0484: int[] tmpval = new int[values.length];
0485: for (int i = 0; i < values.length; i++)
0486: tmpval[i] = Integer.parseInt(values[i]);
0487: method.invoke(bean, new Object[] { tmpval });
0488: } else if (t.equals(byte.class)) {
0489: byte[] tmpval = new byte[values.length];
0490: for (int i = 0; i < values.length; i++)
0491: tmpval[i] = Byte.parseByte(values[i]);
0492: method.invoke(bean, new Object[] { tmpval });
0493: } else if (t.equals(boolean.class)) {
0494: boolean[] tmpval = new boolean[values.length];
0495: for (int i = 0; i < values.length; i++)
0496: tmpval[i] = (Boolean.valueOf(values[i]))
0497: .booleanValue();
0498: method.invoke(bean, new Object[] { tmpval });
0499: } else if (t.equals(short.class)) {
0500: short[] tmpval = new short[values.length];
0501: for (int i = 0; i < values.length; i++)
0502: tmpval[i] = Short.parseShort(values[i]);
0503: method.invoke(bean, new Object[] { tmpval });
0504: } else if (t.equals(long.class)) {
0505: long[] tmpval = new long[values.length];
0506: for (int i = 0; i < values.length; i++)
0507: tmpval[i] = Long.parseLong(values[i]);
0508: method.invoke(bean, new Object[] { tmpval });
0509: } else if (t.equals(double.class)) {
0510: double[] tmpval = new double[values.length];
0511: for (int i = 0; i < values.length; i++)
0512: tmpval[i] = Double.valueOf(values[i]).doubleValue();
0513: method.invoke(bean, new Object[] { tmpval });
0514: } else if (t.equals(float.class)) {
0515: float[] tmpval = new float[values.length];
0516: for (int i = 0; i < values.length; i++)
0517: tmpval[i] = Float.valueOf(values[i]).floatValue();
0518: method.invoke(bean, new Object[] { tmpval });
0519: } else if (t.equals(char.class)) {
0520: char[] tmpval = new char[values.length];
0521: for (int i = 0; i < values.length; i++)
0522: tmpval[i] = values[i].charAt(0);
0523: method.invoke(bean, new Object[] { tmpval });
0524: } else {
0525: Object[] tmpval = new Integer[values.length];
0526: for (int i = 0; i < values.length; i++) {
0527: tmpval[i] = getValueFromPropertyEditorManager(t,
0528: propertyName, values[i]);
0529: }
0530: method.invoke(bean, new Object[] { tmpval });
0531: }
0532: } catch (Exception ex) {
0533: throw new JasperException("error in invoking method", ex);
0534: }
0535: }
0536:
0537: /**
0538: * Escape special shell characters.
0539: * @param unescString The string to shell-escape
0540: * @return The escaped shell string.
0541: */
0542:
0543: public static String escapeQueryString(String unescString) {
0544: if (unescString == null)
0545: return null;
0546:
0547: String escString = "";
0548: String shellSpChars = "&;`'\"|*?~<>^()[]{}$\\\n";
0549:
0550: for (int index = 0; index < unescString.length(); index++) {
0551: char nextChar = unescString.charAt(index);
0552:
0553: if (shellSpChars.indexOf(nextChar) != -1)
0554: escString += "\\";
0555:
0556: escString += nextChar;
0557: }
0558: return escString;
0559: }
0560:
0561: /**
0562: * Decode an URL formatted string.
0563: * @param encoded The string to decode.
0564: * @return The decoded string.
0565: */
0566:
0567: public static String decode(String encoded) {
0568: // speedily leave if we're not needed
0569: if (encoded == null)
0570: return null;
0571: if (encoded.indexOf('%') == -1 && encoded.indexOf('+') == -1)
0572: return encoded;
0573:
0574: //allocate the buffer - use byte[] to avoid calls to new.
0575: byte holdbuffer[] = new byte[encoded.length()];
0576:
0577: char holdchar;
0578: int bufcount = 0;
0579:
0580: for (int count = 0; count < encoded.length(); count++) {
0581: char cur = encoded.charAt(count);
0582: if (cur == '%') {
0583: holdbuffer[bufcount++] = (byte) Integer.parseInt(
0584: encoded.substring(count + 1, count + 3), 16);
0585: if (count + 2 >= encoded.length())
0586: count = encoded.length();
0587: else
0588: count += 2;
0589: } else if (cur == '+') {
0590: holdbuffer[bufcount++] = (byte) ' ';
0591: } else {
0592: holdbuffer[bufcount++] = (byte) cur;
0593: }
0594: }
0595: // REVISIT -- remedy for Deprecated warning.
0596: //return new String(holdbuffer,0,0,bufcount);
0597: return new String(holdbuffer, 0, bufcount);
0598: }
0599:
0600: // __begin lookupReadMethodMethod
0601: public static Object handleGetProperty(Object o, String prop)
0602: throws JasperException {
0603: if (o == null) {
0604: throw new JasperException(Localizer
0605: .getMessage("jsp.error.beans.nullbean"));
0606: }
0607: Object value = null;
0608: try {
0609: Method method = getReadMethod(o.getClass(), prop);
0610: value = method.invoke(o, (Object[]) null);
0611: } catch (Exception ex) {
0612: throw new JasperException(ex);
0613: }
0614: return value;
0615: }
0616:
0617: // __end lookupReadMethodMethod
0618:
0619: // handles <jsp:setProperty> with EL expression for 'value' attribute
0620: /** Use proprietaryEvaluate
0621: public static void handleSetPropertyExpression(Object bean,
0622: String prop, String expression, PageContext pageContext,
0623: VariableResolver variableResolver, FunctionMapper functionMapper )
0624: throws JasperException
0625: {
0626: try {
0627: Method method = getWriteMethod(bean.getClass(), prop);
0628: method.invoke(bean, new Object[] {
0629: pageContext.getExpressionEvaluator().evaluate(
0630: expression,
0631: method.getParameterTypes()[0],
0632: variableResolver,
0633: functionMapper,
0634: null )
0635: });
0636: } catch (Exception ex) {
0637: throw new JasperException(ex);
0638: }
0639: }
0640: **/
0641: public static void handleSetPropertyExpression(Object bean,
0642: String prop, String expression, PageContext pageContext,
0643: ProtectedFunctionMapper functionMapper)
0644: throws JasperException {
0645: try {
0646: Method method = getWriteMethod(bean.getClass(), prop);
0647: method.invoke(bean, new Object[] { PageContextImpl
0648: .proprietaryEvaluate(expression, method
0649: .getParameterTypes()[0], pageContext,
0650: functionMapper, false) });
0651: } catch (Exception ex) {
0652: throw new JasperException(ex);
0653: }
0654: }
0655:
0656: public static void handleSetProperty(Object bean, String prop,
0657: Object value) throws JasperException {
0658: try {
0659: Method method = getWriteMethod(bean.getClass(), prop);
0660: method.invoke(bean, new Object[] { value });
0661: } catch (Exception ex) {
0662: throw new JasperException(ex);
0663: }
0664: }
0665:
0666: public static void handleSetProperty(Object bean, String prop,
0667: int value) throws JasperException {
0668: try {
0669: Method method = getWriteMethod(bean.getClass(), prop);
0670: method.invoke(bean, new Object[] { new Integer(value) });
0671: } catch (Exception ex) {
0672: throw new JasperException(ex);
0673: }
0674: }
0675:
0676: public static void handleSetProperty(Object bean, String prop,
0677: short value) throws JasperException {
0678: try {
0679: Method method = getWriteMethod(bean.getClass(), prop);
0680: method.invoke(bean, new Object[] { new Short(value) });
0681: } catch (Exception ex) {
0682: throw new JasperException(ex);
0683: }
0684: }
0685:
0686: public static void handleSetProperty(Object bean, String prop,
0687: long value) throws JasperException {
0688: try {
0689: Method method = getWriteMethod(bean.getClass(), prop);
0690: method.invoke(bean, new Object[] { new Long(value) });
0691: } catch (Exception ex) {
0692: throw new JasperException(ex);
0693: }
0694: }
0695:
0696: public static void handleSetProperty(Object bean, String prop,
0697: double value) throws JasperException {
0698: try {
0699: Method method = getWriteMethod(bean.getClass(), prop);
0700: method.invoke(bean, new Object[] { new Double(value) });
0701: } catch (Exception ex) {
0702: throw new JasperException(ex);
0703: }
0704: }
0705:
0706: public static void handleSetProperty(Object bean, String prop,
0707: float value) throws JasperException {
0708: try {
0709: Method method = getWriteMethod(bean.getClass(), prop);
0710: method.invoke(bean, new Object[] { new Float(value) });
0711: } catch (Exception ex) {
0712: throw new JasperException(ex);
0713: }
0714: }
0715:
0716: public static void handleSetProperty(Object bean, String prop,
0717: char value) throws JasperException {
0718: try {
0719: Method method = getWriteMethod(bean.getClass(), prop);
0720: method.invoke(bean, new Object[] { new Character(value) });
0721: } catch (Exception ex) {
0722: throw new JasperException(ex);
0723: }
0724: }
0725:
0726: public static void handleSetProperty(Object bean, String prop,
0727: byte value) throws JasperException {
0728: try {
0729: Method method = getWriteMethod(bean.getClass(), prop);
0730: method.invoke(bean, new Object[] { new Byte(value) });
0731: } catch (Exception ex) {
0732: throw new JasperException(ex);
0733: }
0734: }
0735:
0736: public static void handleSetProperty(Object bean, String prop,
0737: boolean value) throws JasperException {
0738: try {
0739: Method method = getWriteMethod(bean.getClass(), prop);
0740: method.invoke(bean, new Object[] { new Boolean(value) });
0741: } catch (Exception ex) {
0742: throw new JasperException(ex);
0743: }
0744: }
0745:
0746: public static Method getWriteMethod(Class beanClass, String prop)
0747: throws JasperException {
0748: Method method = null;
0749: Class type = null;
0750: try {
0751: java.beans.BeanInfo info = java.beans.Introspector
0752: .getBeanInfo(beanClass);
0753: if (info != null) {
0754: java.beans.PropertyDescriptor pd[] = info
0755: .getPropertyDescriptors();
0756: for (int i = 0; i < pd.length; i++) {
0757: if (pd[i].getName().equals(prop)) {
0758: method = pd[i].getWriteMethod();
0759: type = pd[i].getPropertyType();
0760: break;
0761: }
0762: }
0763: } else {
0764: // just in case introspection silently fails.
0765: throw new JasperException(Localizer.getMessage(
0766: "jsp.error.beans.nobeaninfo", beanClass
0767: .getName()));
0768: }
0769: } catch (Exception ex) {
0770: throw new JasperException(ex);
0771: }
0772: if (method == null) {
0773: if (type == null) {
0774: throw new JasperException(Localizer.getMessage(
0775: "jsp.error.beans.noproperty", prop, beanClass
0776: .getName()));
0777: } else {
0778: throw new JasperException(Localizer.getMessage(
0779: "jsp.error.beans.nomethod.setproperty", prop,
0780: type.getName(), beanClass.getName()));
0781: }
0782: }
0783: return method;
0784: }
0785:
0786: public static Method getReadMethod(Class beanClass, String prop)
0787: throws JasperException {
0788:
0789: Method method = null;
0790: Class type = null;
0791: try {
0792: java.beans.BeanInfo info = java.beans.Introspector
0793: .getBeanInfo(beanClass);
0794: if (info != null) {
0795: java.beans.PropertyDescriptor pd[] = info
0796: .getPropertyDescriptors();
0797: for (int i = 0; i < pd.length; i++) {
0798: if (pd[i].getName().equals(prop)) {
0799: method = pd[i].getReadMethod();
0800: type = pd[i].getPropertyType();
0801: break;
0802: }
0803: }
0804: } else {
0805: // just in case introspection silently fails.
0806: throw new JasperException(Localizer.getMessage(
0807: "jsp.error.beans.nobeaninfo", beanClass
0808: .getName()));
0809: }
0810: } catch (Exception ex) {
0811: throw new JasperException(ex);
0812: }
0813: if (method == null) {
0814: if (type == null) {
0815: throw new JasperException(Localizer.getMessage(
0816: "jsp.error.beans.noproperty", prop, beanClass
0817: .getName()));
0818: } else {
0819: throw new JasperException(Localizer.getMessage(
0820: "jsp.error.beans.nomethod", prop, beanClass
0821: .getName()));
0822: }
0823: }
0824:
0825: return method;
0826: }
0827:
0828: //*********************************************************************
0829: // PropertyEditor Support
0830:
0831: public static Object getValueFromBeanInfoPropertyEditor(
0832: Class attrClass, String attrName, String attrValue,
0833: Class propertyEditorClass) throws JasperException {
0834: try {
0835: PropertyEditor pe = (PropertyEditor) propertyEditorClass
0836: .newInstance();
0837: pe.setAsText(attrValue);
0838: return pe.getValue();
0839: } catch (Exception ex) {
0840: throw new JasperException(Localizer.getMessage(
0841: "jsp.error.beans.property.conversion", attrValue,
0842: attrClass.getName(), attrName, ex.getMessage()));
0843: }
0844: }
0845:
0846: public static Object getValueFromPropertyEditorManager(
0847: Class attrClass, String attrName, String attrValue)
0848: throws JasperException {
0849: try {
0850: PropertyEditor propEditor = PropertyEditorManager
0851: .findEditor(attrClass);
0852: if (propEditor != null) {
0853: propEditor.setAsText(attrValue);
0854: return propEditor.getValue();
0855: } else {
0856: throw new IllegalArgumentException(
0857: Localizer
0858: .getMessage("jsp.error.beans.propertyeditor.notregistered"));
0859: }
0860: } catch (IllegalArgumentException ex) {
0861: throw new JasperException(Localizer.getMessage(
0862: "jsp.error.beans.property.conversion", attrValue,
0863: attrClass.getName(), attrName, ex.getMessage()));
0864: }
0865: }
0866:
0867: // ************************************************************************
0868: // General Purpose Runtime Methods
0869: // ************************************************************************
0870:
0871: /**
0872: * Convert a possibly relative resource path into a context-relative
0873: * resource path that starts with a '/'.
0874: *
0875: * @param request The servlet request we are processing
0876: * @param relativePath The possibly relative resource path
0877: */
0878: public static String getContextRelativePath(ServletRequest request,
0879: String relativePath) {
0880:
0881: if (relativePath.startsWith("/"))
0882: return (relativePath);
0883: if (!(request instanceof HttpServletRequest))
0884: return (relativePath);
0885: HttpServletRequest hrequest = (HttpServletRequest) request;
0886: String uri = (String) request
0887: .getAttribute("javax.servlet.include.servlet_path");
0888: if (uri != null) {
0889: String pathInfo = (String) request
0890: .getAttribute("javax.servlet.include.path_info");
0891: if (pathInfo == null) {
0892: if (uri.lastIndexOf('/') >= 0)
0893: uri = uri.substring(0, uri.lastIndexOf('/'));
0894: }
0895: } else {
0896: uri = hrequest.getServletPath();
0897: if (uri.lastIndexOf('/') >= 0)
0898: uri = uri.substring(0, uri.lastIndexOf('/'));
0899: }
0900: return uri + '/' + relativePath;
0901:
0902: }
0903:
0904: /**
0905: * Perform a RequestDispatcher.include() operation, with optional flushing
0906: * of the response beforehand.
0907: *
0908: * @param request The servlet request we are processing
0909: * @param response The servlet response we are processing
0910: * @param relativePath The relative path of the resource to be included
0911: * @param out The Writer to whom we are currently writing
0912: * @param flush Should we flush before the include is processed?
0913: *
0914: * @exception IOException if thrown by the included servlet
0915: * @exception ServletException if thrown by the included servlet
0916: */
0917: public static void include(ServletRequest request,
0918: ServletResponse response, String relativePath,
0919: JspWriter out, boolean flush) throws IOException,
0920: ServletException {
0921:
0922: if (flush && !(out instanceof BodyContent))
0923: out.flush();
0924:
0925: // FIXME - It is tempting to use request.getRequestDispatcher() to
0926: // resolve a relative path directly, but Catalina currently does not
0927: // take into account whether the caller is inside a RequestDispatcher
0928: // include or not. Whether Catalina *should* take that into account
0929: // is a spec issue currently under review. In the mean time,
0930: // replicate Jasper's previous behavior
0931:
0932: String resourcePath = getContextRelativePath(request,
0933: relativePath);
0934: RequestDispatcher rd = request
0935: .getRequestDispatcher(resourcePath);
0936:
0937: rd.include(request, new ServletResponseWrapperInclude(response,
0938: out));
0939:
0940: }
0941:
0942: /**
0943: * URL encodes a string, based on the supplied character encoding.
0944: * This performs the same function as java.next.URLEncode.encode
0945: * in J2SDK1.4, and should be removed if the only platform supported
0946: * is 1.4 or higher.
0947: * @param s The String to be URL encoded.
0948: * @param enc The character encoding
0949: * @return The URL encoded String
0950: */
0951: public static String URLEncode(String s, String enc) {
0952:
0953: if (s == null) {
0954: return "null";
0955: }
0956:
0957: if (enc == null) {
0958: enc = "ISO-8859-1"; // The default request encoding
0959: }
0960:
0961: StringBuffer out = new StringBuffer(s.length());
0962: ByteArrayOutputStream buf = new ByteArrayOutputStream();
0963: OutputStreamWriter writer = null;
0964: try {
0965: writer = new OutputStreamWriter(buf, enc);
0966: } catch (java.io.UnsupportedEncodingException ex) {
0967: // Use the default encoding?
0968: writer = new OutputStreamWriter(buf);
0969: }
0970:
0971: for (int i = 0; i < s.length(); i++) {
0972: int c = s.charAt(i);
0973: if (c == ' ') {
0974: out.append('+');
0975: } else if (isSafeChar(c)) {
0976: out.append((char) c);
0977: } else {
0978: // convert to external encoding before hex conversion
0979: try {
0980: writer.write(c);
0981: writer.flush();
0982: } catch (IOException e) {
0983: buf.reset();
0984: continue;
0985: }
0986: byte[] ba = buf.toByteArray();
0987: for (int j = 0; j < ba.length; j++) {
0988: out.append('%');
0989: // Converting each byte in the buffer
0990: out.append(Character.forDigit((ba[j] >> 4) & 0xf,
0991: 16));
0992: out.append(Character.forDigit(ba[j] & 0xf, 16));
0993: }
0994: buf.reset();
0995: }
0996: }
0997: return out.toString();
0998: }
0999:
1000: private static boolean isSafeChar(int c) {
1001: if (c >= 'a' && c <= 'z') {
1002: return true;
1003: }
1004: if (c >= 'A' && c <= 'Z') {
1005: return true;
1006: }
1007: if (c >= '0' && c <= '9') {
1008: return true;
1009: }
1010: if (c == '-' || c == '_' || c == '.' || c == '!' || c == '~'
1011: || c == '*' || c == '\'' || c == '(' || c == ')') {
1012: return true;
1013: }
1014: return false;
1015: }
1016:
1017: }
|