| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.jasper.runtime; |
| |
| import java.beans.PropertyEditor; |
| import java.beans.PropertyEditorManager; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.lang.reflect.Method; |
| import java.util.Enumeration; |
| |
| import javax.servlet.RequestDispatcher; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.jsp.JspException; |
| import javax.servlet.jsp.JspWriter; |
| import javax.servlet.jsp.PageContext; |
| import javax.servlet.jsp.tagext.BodyContent; |
| import javax.servlet.jsp.tagext.BodyTag; |
| import javax.servlet.jsp.tagext.Tag; |
| |
| import org.apache.jasper.JasperException; |
| import org.apache.jasper.compiler.Localizer; |
| import org.apache.juli.logging.Log; |
| import org.apache.juli.logging.LogFactory; |
| import org.apache.tomcat.InstanceManager; |
| |
| /** |
| * Bunch of util methods that are used by code generated for useBean, |
| * getProperty and setProperty. |
| * |
| * The __begin, __end stuff is there so that the JSP engine can |
| * actually parse this file and inline them if people don't want |
| * runtime dependencies on this class. However, I'm not sure if that |
| * works so well right now. It got forgotten at some point. -akv |
| * |
| * @author Mandar Raje |
| * @author Shawn Bayern |
| */ |
| public class JspRuntimeLibrary { |
| |
| private static final Log log = LogFactory.getLog(JspRuntimeLibrary.class); |
| |
| /** |
| * Returns the value of the javax.servlet.error.exception request |
| * attribute value, if present, otherwise the value of the |
| * javax.servlet.jsp.jspException request attribute value. |
| * |
| * This method is called at the beginning of the generated servlet code |
| * for a JSP error page, when the "exception" implicit scripting language |
| * variable is initialized. |
| */ |
| public static Throwable getThrowable(ServletRequest request) { |
| Throwable error = (Throwable) request.getAttribute( |
| RequestDispatcher.ERROR_EXCEPTION); |
| if (error == null) { |
| error = (Throwable) request.getAttribute(PageContext.EXCEPTION); |
| if (error != null) { |
| /* |
| * The only place that sets JSP_EXCEPTION is |
| * PageContextImpl.handlePageException(). It really should set |
| * SERVLET_EXCEPTION, but that would interfere with the |
| * ErrorReportValve. Therefore, if JSP_EXCEPTION is set, we |
| * need to set SERVLET_EXCEPTION. |
| */ |
| request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, error); |
| } |
| } |
| |
| return error; |
| } |
| |
| public static boolean coerceToBoolean(String s) { |
| if (s == null || s.length() == 0) |
| return false; |
| else |
| return Boolean.parseBoolean(s); |
| } |
| |
| public static byte coerceToByte(String s) { |
| if (s == null || s.length() == 0) |
| return (byte) 0; |
| else |
| return Byte.parseByte(s); |
| } |
| |
| public static char coerceToChar(String s) { |
| if (s == null || s.length() == 0) { |
| return (char) 0; |
| } else { |
| return s.charAt(0); |
| } |
| } |
| |
| public static double coerceToDouble(String s) { |
| if (s == null || s.length() == 0) |
| return 0; |
| else |
| return Double.parseDouble(s); |
| } |
| |
| public static float coerceToFloat(String s) { |
| if (s == null || s.length() == 0) |
| return 0; |
| else |
| return Float.parseFloat(s); |
| } |
| |
| public static int coerceToInt(String s) { |
| if (s == null || s.length() == 0) |
| return 0; |
| else |
| return Integer.parseInt(s); |
| } |
| |
| public static short coerceToShort(String s) { |
| if (s == null || s.length() == 0) |
| return (short) 0; |
| else |
| return Short.parseShort(s); |
| } |
| |
| public static long coerceToLong(String s) { |
| if (s == null || s.length() == 0) |
| return 0; |
| else |
| return Long.parseLong(s); |
| } |
| |
| public static Object coerce(String s, Class<?> target) { |
| |
| boolean isNullOrEmpty = (s == null || s.length() == 0); |
| |
| if (target == Boolean.class) { |
| if (isNullOrEmpty) { |
| s = "false"; |
| } |
| return Boolean.valueOf(s); |
| } else if (target == Byte.class) { |
| if (isNullOrEmpty) |
| return Byte.valueOf((byte) 0); |
| else |
| return Byte.valueOf(s); |
| } else if (target == Character.class) { |
| if (isNullOrEmpty) |
| return Character.valueOf((char) 0); |
| else { |
| @SuppressWarnings("null") |
| Character result = Character.valueOf(s.charAt(0)); |
| return result; |
| } |
| } else if (target == Double.class) { |
| if (isNullOrEmpty) |
| return Double.valueOf(0); |
| else |
| return Double.valueOf(s); |
| } else if (target == Float.class) { |
| if (isNullOrEmpty) |
| return Float.valueOf(0); |
| else |
| return Float.valueOf(s); |
| } else if (target == Integer.class) { |
| if (isNullOrEmpty) |
| return Integer.valueOf(0); |
| else |
| return Integer.valueOf(s); |
| } else if (target == Short.class) { |
| if (isNullOrEmpty) |
| return Short.valueOf((short) 0); |
| else |
| return Short.valueOf(s); |
| } else if (target == Long.class) { |
| if (isNullOrEmpty) |
| return Long.valueOf(0); |
| else |
| return Long.valueOf(s); |
| } else { |
| return null; |
| } |
| } |
| |
| // __begin convertMethod |
| public static Object convert(String propertyName, String s, Class<?> t, |
| Class<?> propertyEditorClass) |
| throws JasperException |
| { |
| try { |
| if (s == null) { |
| if (t.equals(Boolean.class) || t.equals(Boolean.TYPE)) |
| s = "false"; |
| else |
| return null; |
| } |
| if (propertyEditorClass != null) { |
| return getValueFromBeanInfoPropertyEditor( |
| t, propertyName, s, propertyEditorClass); |
| } else if ( t.equals(Boolean.class) || t.equals(Boolean.TYPE) ) { |
| if (s.equalsIgnoreCase("on") || s.equalsIgnoreCase("true")) |
| s = "true"; |
| else |
| s = "false"; |
| return Boolean.valueOf(s); |
| } else if ( t.equals(Byte.class) || t.equals(Byte.TYPE) ) { |
| return Byte.valueOf(s); |
| } else if (t.equals(Character.class) || t.equals(Character.TYPE)) { |
| return s.length() > 0 ? Character.valueOf(s.charAt(0)) : null; |
| } else if ( t.equals(Short.class) || t.equals(Short.TYPE) ) { |
| return Short.valueOf(s); |
| } else if ( t.equals(Integer.class) || t.equals(Integer.TYPE) ) { |
| return Integer.valueOf(s); |
| } else if ( t.equals(Float.class) || t.equals(Float.TYPE) ) { |
| return Float.valueOf(s); |
| } else if ( t.equals(Long.class) || t.equals(Long.TYPE) ) { |
| return Long.valueOf(s); |
| } else if ( t.equals(Double.class) || t.equals(Double.TYPE) ) { |
| return Double.valueOf(s); |
| } else if ( t.equals(String.class) ) { |
| return s; |
| } else if ( t.equals(java.io.File.class) ) { |
| return new java.io.File(s); |
| } else if (t.getName().equals("java.lang.Object")) { |
| return new Object[] {s}; |
| } else { |
| return getValueFromPropertyEditorManager( |
| t, propertyName, s); |
| } |
| } catch (Exception ex) { |
| throw new JasperException(ex); |
| } |
| } |
| // __end convertMethod |
| |
| // __begin introspectMethod |
| public static void introspect(Object bean, ServletRequest request) |
| throws JasperException |
| { |
| Enumeration<String> e = request.getParameterNames(); |
| while ( e.hasMoreElements() ) { |
| String name = e.nextElement(); |
| String value = request.getParameter(name); |
| introspecthelper(bean, name, value, request, name, true); |
| } |
| } |
| // __end introspectMethod |
| |
| // __begin introspecthelperMethod |
| public static void introspecthelper(Object bean, String prop, |
| String value, ServletRequest request, |
| String param, boolean ignoreMethodNF) |
| throws JasperException { |
| Method method = null; |
| Class<?> type = null; |
| Class<?> propertyEditorClass = null; |
| try { |
| java.beans.BeanInfo info |
| = java.beans.Introspector.getBeanInfo(bean.getClass()); |
| if ( info != null ) { |
| java.beans.PropertyDescriptor pd[] |
| = info.getPropertyDescriptors(); |
| for (int i = 0 ; i < pd.length ; i++) { |
| if ( pd[i].getName().equals(prop) ) { |
| method = pd[i].getWriteMethod(); |
| type = pd[i].getPropertyType(); |
| propertyEditorClass = pd[i].getPropertyEditorClass(); |
| break; |
| } |
| } |
| } |
| if (method != null && type != null) { |
| if (type.isArray()) { |
| if (request == null) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.setproperty.noindexset")); |
| } |
| Class<?> t = type.getComponentType(); |
| String[] values = request.getParameterValues(param); |
| //XXX Please check. |
| if(values == null) return; |
| if(t.equals(String.class)) { |
| method.invoke(bean, new Object[] { values }); |
| } else { |
| createTypedArray (prop, bean, method, values, t, |
| propertyEditorClass); |
| } |
| } else { |
| if(value == null || (param != null && value.equals(""))) return; |
| Object oval = convert(prop, value, type, propertyEditorClass); |
| if ( oval != null ) |
| method.invoke(bean, new Object[] { oval }); |
| } |
| } |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| if (!ignoreMethodNF && (method == null)) { |
| if (type == null) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.noproperty", |
| prop, |
| bean.getClass().getName())); |
| } else { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nomethod.setproperty", |
| prop, |
| type.getName(), |
| bean.getClass().getName())); |
| } |
| } |
| } |
| // __end introspecthelperMethod |
| |
| //------------------------------------------------------------------- |
| // functions to convert builtin Java data types to string. |
| //------------------------------------------------------------------- |
| // __begin toStringMethod |
| public static String toString(Object o) { |
| return String.valueOf(o); |
| } |
| |
| public static String toString(byte b) { |
| return Byte.toString(b); |
| } |
| |
| public static String toString(boolean b) { |
| return Boolean.toString(b); |
| } |
| |
| public static String toString(short s) { |
| return Short.toString(s); |
| } |
| |
| public static String toString(int i) { |
| return Integer.toString(i); |
| } |
| |
| public static String toString(float f) { |
| return Float.toString(f); |
| } |
| |
| public static String toString(long l) { |
| return Long.toString(l); |
| } |
| |
| public static String toString(double d) { |
| return Double.toString(d); |
| } |
| |
| public static String toString(char c) { |
| return Character.toString(c); |
| } |
| // __end toStringMethod |
| |
| |
| /** |
| * Create a typed array. |
| * This is a special case where params are passed through |
| * the request and the property is indexed. |
| */ |
| public static void createTypedArray(String propertyName, |
| Object bean, |
| Method method, |
| String[] values, |
| Class<?> t, |
| Class<?> propertyEditorClass) |
| throws JasperException { |
| |
| try { |
| if (propertyEditorClass != null) { |
| Object[] tmpval = new Integer[values.length]; |
| for (int i=0; i<values.length; i++) { |
| tmpval[i] = getValueFromBeanInfoPropertyEditor( |
| t, propertyName, values[i], propertyEditorClass); |
| } |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Integer.class)) { |
| Integer []tmpval = new Integer[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Integer.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Byte.class)) { |
| Byte[] tmpval = new Byte[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Byte.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Boolean.class)) { |
| Boolean[] tmpval = new Boolean[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Boolean.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Short.class)) { |
| Short[] tmpval = new Short[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Short.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Long.class)) { |
| Long[] tmpval = new Long[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Long.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Double.class)) { |
| Double[] tmpval = new Double[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Double.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Float.class)) { |
| Float[] tmpval = new Float[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Float.valueOf(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(Character.class)) { |
| Character[] tmpval = new Character[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Character.valueOf(values[i].charAt(0)); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(int.class)) { |
| int []tmpval = new int[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Integer.parseInt (values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(byte.class)) { |
| byte[] tmpval = new byte[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Byte.parseByte (values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(boolean.class)) { |
| boolean[] tmpval = new boolean[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Boolean.parseBoolean(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(short.class)) { |
| short[] tmpval = new short[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Short.parseShort (values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(long.class)) { |
| long[] tmpval = new long[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Long.parseLong (values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(double.class)) { |
| double[] tmpval = new double[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Double.parseDouble(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(float.class)) { |
| float[] tmpval = new float[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = Float.parseFloat(values[i]); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else if (t.equals(char.class)) { |
| char[] tmpval = new char[values.length]; |
| for (int i = 0 ; i < values.length; i++) |
| tmpval[i] = values[i].charAt(0); |
| method.invoke (bean, new Object[] {tmpval}); |
| } else { |
| Object[] tmpval = new Integer[values.length]; |
| for (int i=0; i<values.length; i++) { |
| tmpval[i] = |
| getValueFromPropertyEditorManager( |
| t, propertyName, values[i]); |
| } |
| method.invoke (bean, new Object[] {tmpval}); |
| } |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException ("error in invoking method", ex); |
| } |
| } |
| |
| /** |
| * Escape special shell characters. |
| * @param unescString The string to shell-escape |
| * @return The escaped shell string. |
| */ |
| public static String escapeQueryString(String unescString) { |
| if (unescString == null) { |
| return null; |
| } |
| |
| StringBuilder escStringBuilder = new StringBuilder(); |
| String shellSpChars = "&;`'\"|*?~<>^()[]{}$\\\n"; |
| |
| for (int index = 0; index < unescString.length(); index++) { |
| char nextChar = unescString.charAt(index); |
| |
| if (shellSpChars.indexOf(nextChar) != -1) { |
| escStringBuilder.append('\\'); |
| } |
| |
| escStringBuilder.append(nextChar); |
| } |
| return escStringBuilder.toString(); |
| } |
| |
| // __begin lookupReadMethodMethod |
| public static Object handleGetProperty(Object o, String prop) |
| throws JasperException { |
| if (o == null) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nullbean")); |
| } |
| Object value = null; |
| try { |
| Method method = getReadMethod(o.getClass(), prop); |
| value = method.invoke(o, (Object[]) null); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException (ex); |
| } |
| return value; |
| } |
| // __end lookupReadMethodMethod |
| |
| // handles <jsp:setProperty> with EL expression for 'value' attribute |
| public static void handleSetPropertyExpression(Object bean, |
| String prop, String expression, PageContext pageContext, |
| ProtectedFunctionMapper functionMapper ) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { |
| PageContextImpl.proprietaryEvaluate( |
| expression, |
| method.getParameterTypes()[0], |
| pageContext, |
| functionMapper) |
| }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| Object value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { value }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| int value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Integer.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| short value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Short.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| long value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Long.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| double value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Double.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| float value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Float.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| char value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Character.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| byte value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Byte.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static void handleSetProperty(Object bean, String prop, |
| boolean value) |
| throws JasperException |
| { |
| try { |
| Method method = getWriteMethod(bean.getClass(), prop); |
| method.invoke(bean, new Object[] { Boolean.valueOf(value) }); |
| } catch (Exception ex) { |
| Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); |
| ExceptionUtils.handleThrowable(thr); |
| throw new JasperException(ex); |
| } |
| } |
| |
| public static Method getWriteMethod(Class<?> beanClass, String prop) |
| throws JasperException { |
| Method method = null; |
| Class<?> type = null; |
| try { |
| java.beans.BeanInfo info |
| = java.beans.Introspector.getBeanInfo(beanClass); |
| if ( info != null ) { |
| java.beans.PropertyDescriptor pd[] |
| = info.getPropertyDescriptors(); |
| for (int i = 0 ; i < pd.length ; i++) { |
| if ( pd[i].getName().equals(prop) ) { |
| method = pd[i].getWriteMethod(); |
| type = pd[i].getPropertyType(); |
| break; |
| } |
| } |
| } else { |
| // just in case introspection silently fails. |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nobeaninfo", |
| beanClass.getName())); |
| } |
| } catch (Exception ex) { |
| throw new JasperException (ex); |
| } |
| if (method == null) { |
| if (type == null) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.noproperty", |
| prop, |
| beanClass.getName())); |
| } else { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nomethod.setproperty", |
| prop, |
| type.getName(), |
| beanClass.getName())); |
| } |
| } |
| return method; |
| } |
| |
| public static Method getReadMethod(Class<?> beanClass, String prop) |
| throws JasperException { |
| |
| Method method = null; |
| Class<?> type = null; |
| try { |
| java.beans.BeanInfo info |
| = java.beans.Introspector.getBeanInfo(beanClass); |
| if ( info != null ) { |
| java.beans.PropertyDescriptor pd[] |
| = info.getPropertyDescriptors(); |
| for (int i = 0 ; i < pd.length ; i++) { |
| if ( pd[i].getName().equals(prop) ) { |
| method = pd[i].getReadMethod(); |
| type = pd[i].getPropertyType(); |
| break; |
| } |
| } |
| } else { |
| // just in case introspection silently fails. |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nobeaninfo", |
| beanClass.getName())); |
| } |
| } catch (Exception ex) { |
| throw new JasperException (ex); |
| } |
| if (method == null) { |
| if (type == null) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.noproperty", prop, |
| beanClass.getName())); |
| } else { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.nomethod", prop, |
| beanClass.getName())); |
| } |
| } |
| |
| return method; |
| } |
| |
| //********************************************************************* |
| // PropertyEditor Support |
| |
| public static Object getValueFromBeanInfoPropertyEditor( |
| Class<?> attrClass, String attrName, String attrValue, |
| Class<?> propertyEditorClass) |
| throws JasperException |
| { |
| try { |
| PropertyEditor pe = |
| (PropertyEditor)propertyEditorClass.newInstance(); |
| pe.setAsText(attrValue); |
| return pe.getValue(); |
| } catch (Exception ex) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.property.conversion", |
| attrValue, attrClass.getName(), attrName, |
| ex.getMessage())); |
| } |
| } |
| |
| public static Object getValueFromPropertyEditorManager( |
| Class<?> attrClass, String attrName, String attrValue) |
| throws JasperException |
| { |
| try { |
| PropertyEditor propEditor = |
| PropertyEditorManager.findEditor(attrClass); |
| if (propEditor != null) { |
| propEditor.setAsText(attrValue); |
| return propEditor.getValue(); |
| } else { |
| throw new IllegalArgumentException( |
| Localizer.getMessage("jsp.error.beans.propertyeditor.notregistered")); |
| } |
| } catch (IllegalArgumentException ex) { |
| throw new JasperException( |
| Localizer.getMessage("jsp.error.beans.property.conversion", |
| attrValue, attrClass.getName(), attrName, |
| ex.getMessage())); |
| } |
| } |
| |
| |
| // ************************************************************************ |
| // General Purpose Runtime Methods |
| // ************************************************************************ |
| |
| |
| /** |
| * Convert a possibly relative resource path into a context-relative |
| * resource path that starts with a '/'. |
| * |
| * @param request The servlet request we are processing |
| * @param relativePath The possibly relative resource path |
| */ |
| public static String getContextRelativePath(ServletRequest request, |
| String relativePath) { |
| |
| if (relativePath.startsWith("/")) |
| return (relativePath); |
| if (!(request instanceof HttpServletRequest)) |
| return (relativePath); |
| HttpServletRequest hrequest = (HttpServletRequest) request; |
| String uri = (String) request.getAttribute( |
| RequestDispatcher.INCLUDE_SERVLET_PATH); |
| if (uri != null) { |
| String pathInfo = (String) |
| request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); |
| if (pathInfo == null) { |
| if (uri.lastIndexOf('/') >= 0) |
| uri = uri.substring(0, uri.lastIndexOf('/')); |
| } |
| } |
| else { |
| uri = hrequest.getServletPath(); |
| if (uri.lastIndexOf('/') >= 0) |
| uri = uri.substring(0, uri.lastIndexOf('/')); |
| } |
| return uri + '/' + relativePath; |
| |
| } |
| |
| |
| /** |
| * Perform a RequestDispatcher.include() operation, with optional flushing |
| * of the response beforehand. |
| * |
| * @param request The servlet request we are processing |
| * @param response The servlet response we are processing |
| * @param relativePath The relative path of the resource to be included |
| * @param out The Writer to whom we are currently writing |
| * @param flush Should we flush before the include is processed? |
| * |
| * @exception IOException if thrown by the included servlet |
| * @exception ServletException if thrown by the included servlet |
| */ |
| public static void include(ServletRequest request, |
| ServletResponse response, |
| String relativePath, |
| JspWriter out, |
| boolean flush) |
| throws IOException, ServletException { |
| |
| if (flush && !(out instanceof BodyContent)) |
| out.flush(); |
| |
| // FIXME - It is tempting to use request.getRequestDispatcher() to |
| // resolve a relative path directly, but Catalina currently does not |
| // take into account whether the caller is inside a RequestDispatcher |
| // include or not. Whether Catalina *should* take that into account |
| // is a spec issue currently under review. In the mean time, |
| // replicate Jasper's previous behavior |
| |
| String resourcePath = getContextRelativePath(request, relativePath); |
| RequestDispatcher rd = request.getRequestDispatcher(resourcePath); |
| |
| rd.include(request, |
| new ServletResponseWrapperInclude(response, out)); |
| |
| } |
| |
| /** |
| * URL encodes a string, based on the supplied character encoding. |
| * This performs the same function as java.next.URLEncode.encode |
| * in J2SDK1.4, and should be removed if the only platform supported |
| * is 1.4 or higher. |
| * @param s The String to be URL encoded. |
| * @param enc The character encoding |
| * @return The URL encoded String |
| */ |
| public static String URLEncode(String s, String enc) { |
| |
| if (s == null) { |
| return "null"; |
| } |
| |
| if (enc == null) { |
| enc = "ISO-8859-1"; // The default request encoding |
| } |
| |
| StringBuilder out = new StringBuilder(s.length()); |
| ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
| OutputStreamWriter writer = null; |
| try { |
| writer = new OutputStreamWriter(buf, enc); |
| } catch (java.io.UnsupportedEncodingException ex) { |
| // Use the default encoding? |
| writer = new OutputStreamWriter(buf); |
| } |
| |
| for (int i = 0; i < s.length(); i++) { |
| int c = s.charAt(i); |
| if (c == ' ') { |
| out.append('+'); |
| } else if (isSafeChar(c)) { |
| out.append((char)c); |
| } else { |
| // convert to external encoding before hex conversion |
| try { |
| writer.write(c); |
| writer.flush(); |
| } catch(IOException e) { |
| buf.reset(); |
| continue; |
| } |
| byte[] ba = buf.toByteArray(); |
| for (int j = 0; j < ba.length; j++) { |
| out.append('%'); |
| // Converting each byte in the buffer |
| out.append(Character.forDigit((ba[j]>>4) & 0xf, 16)); |
| out.append(Character.forDigit(ba[j] & 0xf, 16)); |
| } |
| buf.reset(); |
| } |
| } |
| return out.toString(); |
| } |
| |
| private static boolean isSafeChar(int c) { |
| if (c >= 'a' && c <= 'z') { |
| return true; |
| } |
| if (c >= 'A' && c <= 'Z') { |
| return true; |
| } |
| if (c >= '0' && c <= '9') { |
| return true; |
| } |
| if (c == '-' || c == '_' || c == '.' || c == '!' || |
| c == '~' || c == '*' || c == '\'' || c == '(' || c == ')') { |
| return true; |
| } |
| return false; |
| } |
| |
| |
| public static JspWriter startBufferedBody(PageContext pageContext, BodyTag tag) |
| throws JspException { |
| BodyContent out = pageContext.pushBody(); |
| tag.setBodyContent(out); |
| tag.doInitBody(); |
| return out; |
| } |
| |
| |
| public static void releaseTag(Tag tag, InstanceManager instanceManager, boolean reused) { |
| // Caller ensures pool is non-null if reuse is true |
| if (!reused) { |
| releaseTag(tag, instanceManager); |
| } |
| } |
| |
| |
| protected static void releaseTag(Tag tag, InstanceManager instanceManager) { |
| try { |
| tag.release(); |
| } catch (Throwable t) { |
| ExceptionUtils.handleThrowable(t); |
| log.warn("Error processing release on tag instance of " |
| + tag.getClass().getName(), t); |
| } |
| try { |
| instanceManager.destroyInstance(tag); |
| } catch (Exception e) { |
| Throwable t = ExceptionUtils.unwrapInvocationTargetException(e); |
| ExceptionUtils.handleThrowable(t); |
| log.warn("Error processing preDestroy on tag instance of " |
| + tag.getClass().getName(), t); |
| } |
| |
| } |
| } |