/*
 * 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.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
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.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyContent;

import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Localizer;

/**
 * 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 String SERVLET_EXCEPTION
        = "javax.servlet.error.exception";
    private static final String JSP_EXCEPTION
        = "javax.servlet.jsp.jspException";

    protected static class PrivilegedIntrospectHelper
        implements PrivilegedExceptionAction {

        private Object bean;
        private String prop;
        private String value;
        private ServletRequest request;
        private String param;
        private boolean ignoreMethodNF;

        PrivilegedIntrospectHelper(Object bean, String prop,
                                   String value, ServletRequest request,
                                   String param, boolean ignoreMethodNF)
        {
            this.bean = bean;
            this.prop = prop;
            this.value = value;
            this.request = request;
            this.param = param;
            this.ignoreMethodNF = ignoreMethodNF;
        }
         
        public Object run() throws JasperException {
            internalIntrospecthelper(
                bean,prop,value,request,param,ignoreMethodNF);
            return null;
        }
    }

    /**
     * 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(SERVLET_EXCEPTION);
        if (error == null) {
            error = (Throwable) request.getAttribute(JSP_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(SERVLET_EXCEPTION, error);
            }
        }

        return error;
    }

    public static boolean coerceToBoolean(String s) {
        if (s == null || s.length() == 0)
            return false;
        else
            return Boolean.valueOf(s).booleanValue();
    }

    public static byte coerceToByte(String s) {
        if (s == null || s.length() == 0)
            return (byte) 0;
        else
            return Byte.valueOf(s).byteValue();
    }

    public static char coerceToChar(String s) {
        if (s == null || s.length() == 0) {
            return (char) 0;
        } else {
            // this trick avoids escaping issues
            return (char)(int) s.charAt(0);
        }
    }

    public static double coerceToDouble(String s) {
        if (s == null || s.length() == 0)
            return (double) 0;
        else
            return Double.valueOf(s).doubleValue();
    }

    public static float coerceToFloat(String s) {
        if (s == null || s.length() == 0)
            return (float) 0;
        else
            return Float.valueOf(s).floatValue();
    }

    public static int coerceToInt(String s) {
        if (s == null || s.length() == 0)
            return 0;
        else
            return Integer.valueOf(s).intValue();
    }

    public static short coerceToShort(String s) {
        if (s == null || s.length() == 0)
            return (short) 0;
        else
            return Short.valueOf(s).shortValue();
    }

    public static long coerceToLong(String s) {
        if (s == null || s.length() == 0)
            return (long) 0;
        else
            return Long.valueOf(s).longValue();
    }

    public static Object coerce(String s, Class target) {

        boolean isNullOrEmpty = (s == null || s.length() == 0);

        if (target == Boolean.class) {
            if (isNullOrEmpty) {
                s = "false";
            }
            return new Boolean(s);
        } else if (target == Byte.class) {
            if (isNullOrEmpty)
                return new Byte((byte) 0);
            else
                return new Byte(s);
        } else if (target == Character.class) {
            if (isNullOrEmpty)
                return new Character((char) 0);
            else 
                return new Character(s.charAt(0));
        } else if (target == Double.class) {
            if (isNullOrEmpty)
                return new Double(0);
            else
                return new Double(s);
        } else if (target == Float.class) {
            if (isNullOrEmpty)
                return new Float(0);
            else
                return new Float(s);
        } else if (target == Integer.class) {
            if (isNullOrEmpty)
                return new Integer(0);
            else
                return new Integer(s);
        } else if (target == Short.class) {
            if (isNullOrEmpty)
                return new Short((short) 0);
            else
                return new Short(s);
        } else if (target == Long.class) {
            if (isNullOrEmpty)
                return new Long(0);
            else
                return new Long(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 new Boolean(s);
            } else if ( t.equals(Byte.class) || t.equals(Byte.TYPE) ) {
                return new Byte(s);
            } else if (t.equals(Character.class) || t.equals(Character.TYPE)) {
                return s.length() > 0 ? new Character(s.charAt(0)) : null;
            } else if ( t.equals(Short.class) || t.equals(Short.TYPE) ) {
                return new Short(s);
            } else if ( t.equals(Integer.class) || t.equals(Integer.TYPE) ) {
                return new Integer(s);
            } else if ( t.equals(Float.class) || t.equals(Float.TYPE) ) {
                return new Float(s);
            } else if ( t.equals(Long.class) || t.equals(Long.TYPE) ) {
                return new Long(s);
            } else if ( t.equals(Double.class) || t.equals(Double.TYPE) ) {
                return new Double(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 e = request.getParameterNames();
        while ( e.hasMoreElements() ) {
            String name  = (String) 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
    {
        if( System.getSecurityManager() != null ) {
            try {
                PrivilegedIntrospectHelper dp =
                    new PrivilegedIntrospectHelper(
                        bean,prop,value,request,param,ignoreMethodNF);
                AccessController.doPrivileged(dp);
            } catch( PrivilegedActionException pe) {
                Exception e = pe.getException();
                throw (JasperException)e;
            }
        } else {
            internalIntrospecthelper(
                bean,prop,value,request,param,ignoreMethodNF);
        }
    }

    private static void internalIntrospecthelper(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 ) {
                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) {
            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 new Byte(b).toString();
    }

    public static String toString(boolean b) {
        return new Boolean(b).toString();
    }

    public static String toString(short s) {
        return new Short(s).toString();
    }

    public static String toString(int i) {
        return new Integer(i).toString();
    }

    public static String toString(float f) {
        return new Float(f).toString();
    }

    public static String toString(long l) {
        return new Long(l).toString();
    }

    public static String toString(double d) {
        return new Double(d).toString();
    }

    public static String toString(char c) {
        return new Character(c).toString();
    }
    // __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] =  new Integer (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] = new Byte (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] = new Boolean (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] = new Short (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] = new Long (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] = new Double (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] = new Float (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] = new Character(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.valueOf(values[i])).booleanValue();
                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.valueOf(values[i]).doubleValue();
                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]).floatValue();
                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) {
            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;
   
    String escString    = "";
    String shellSpChars = "&;`'\"|*?~<>^()[]{}$\\\n";
   
    for(int index=0; index<unescString.length(); index++) {
        char nextChar = unescString.charAt(index);

        if( shellSpChars.indexOf(nextChar) != -1 )
        escString += "\\";

        escString += nextChar;
    }
    return escString;
    }

    /**
     * Decode an URL formatted string.
     * @param encoded The string to decode.
     * @return The decoded string.
     */

    public static String decode(String encoded) {
        // speedily leave if we're not needed
    if (encoded == null) return null;
        if (encoded.indexOf('%') == -1 && encoded.indexOf('+') == -1)
        return encoded;

    //allocate the buffer - use byte[] to avoid calls to new.
        byte holdbuffer[] = new byte[encoded.length()];

        int bufcount = 0;

        for (int count = 0; count < encoded.length(); count++) {
        char cur = encoded.charAt(count);
            if (cur == '%') {
            holdbuffer[bufcount++] =
          (byte)Integer.parseInt(encoded.substring(count+1,count+3),16);
                if (count + 2 >= encoded.length())
                    count = encoded.length();
                else
                    count += 2;
            } else if (cur == '+') {
        holdbuffer[bufcount++] = (byte) ' ';
        } else {
            holdbuffer[bufcount++] = (byte) cur;
            }
        }
        // REVISIT -- remedy for Deprecated warning.
    //return new String(holdbuffer,0,0,bufcount);
    return new String(holdbuffer,0,bufcount);
    }

    // __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, null);
        } catch (Exception ex) {
            throw new JasperException (ex);
        }
        return value;
    }
    // __end lookupReadMethodMethod

    // handles <jsp:setProperty> with EL expression for 'value' attribute
/** Use proprietaryEvaluate
    public static void handleSetPropertyExpression(Object bean,
        String prop, String expression, PageContext pageContext,
        VariableResolver variableResolver, FunctionMapper functionMapper )
        throws JasperException
    {
        try {
            Method method = getWriteMethod(bean.getClass(), prop);
            method.invoke(bean, new Object[] { 
                pageContext.getExpressionEvaluator().evaluate(
                    expression,
                    method.getParameterTypes()[0],
                    variableResolver,
                    functionMapper,
                    null )
            });
        } catch (Exception ex) {
            throw new JasperException(ex);
        }
    }
**/
    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,
                    false )
            });
        } catch (Exception ex) {
            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) {
            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[] { new Integer(value) });
        } catch (Exception ex) {
            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[] { new Short(value) });
        } catch (Exception ex) {
            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[] { new Long(value) });
        } catch (Exception ex) {
            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[] { new Double(value) });
        } catch (Exception ex) {
            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[] { new Float(value) });
        } catch (Exception ex) {
            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[] { new Character(value) });
        } catch (Exception ex) {
            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[] { new Byte(value) });
        } catch (Exception ex) {
            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[] { new Boolean(value) });
        } catch (Exception ex) {
            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("javax.servlet.include.servlet_path");
        if (uri != null) {
            String pathInfo = (String)
                request.getAttribute("javax.servlet.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 
        }

        StringBuffer out = new StringBuffer(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;
    }

}
