You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2009/09/28 02:43:39 UTC
svn commit: r819435 [17/23] - in
/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper:
./ compiler/ compiler/tagplugin/ el/ runtime/ security/ servlet/
tagplugins/ tagplugins/jstl/ tagplugins/jstl/core/ util/ xmlparser/
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFactoryImpl.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFactoryImpl.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFactoryImpl.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFactoryImpl.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,202 @@
+/*
+ * 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.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.jsp.JspApplicationContext;
+import javax.servlet.jsp.JspEngineInfo;
+import javax.servlet.jsp.JspFactory;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.jasper.Constants;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * Implementation of JspFactory.
+ *
+ * @author Anil K. Vijendran
+ */
+public class JspFactoryImpl extends JspFactory {
+
+ // Logger
+ private Log log = LogFactory.getLog(JspFactoryImpl.class);
+
+ private static final String SPEC_VERSION = "2.1";
+ private static final boolean USE_POOL =
+ Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true")).booleanValue();
+ private static final int POOL_SIZE =
+ Integer.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8")).intValue();
+
+ private ThreadLocal<PageContextPool> localPool = new ThreadLocal<PageContextPool>();
+
+ public PageContext getPageContext(Servlet servlet, ServletRequest request,
+ ServletResponse response, String errorPageURL, boolean needsSession,
+ int bufferSize, boolean autoflush) {
+
+ if( Constants.IS_SECURITY_ENABLED ) {
+ PrivilegedGetPageContext dp = new PrivilegedGetPageContext(
+ (JspFactoryImpl)this, servlet, request, response, errorPageURL,
+ needsSession, bufferSize, autoflush);
+ return (PageContext)AccessController.doPrivileged(dp);
+ } else {
+ return internalGetPageContext(servlet, request, response,
+ errorPageURL, needsSession,
+ bufferSize, autoflush);
+ }
+ }
+
+ public void releasePageContext(PageContext pc) {
+ if( pc == null )
+ return;
+ if( Constants.IS_SECURITY_ENABLED ) {
+ PrivilegedReleasePageContext dp = new PrivilegedReleasePageContext(
+ (JspFactoryImpl)this,pc);
+ AccessController.doPrivileged(dp);
+ } else {
+ internalReleasePageContext(pc);
+ }
+ }
+
+ public JspEngineInfo getEngineInfo() {
+ return new JspEngineInfo() {
+ public String getSpecificationVersion() {
+ return SPEC_VERSION;
+ }
+ };
+ }
+
+ private PageContext internalGetPageContext(Servlet servlet, ServletRequest request,
+ ServletResponse response, String errorPageURL, boolean needsSession,
+ int bufferSize, boolean autoflush) {
+ try {
+ PageContext pc;
+ if (USE_POOL) {
+ PageContextPool pool = localPool.get();
+ if (pool == null) {
+ pool = new PageContextPool();
+ localPool.set(pool);
+ }
+ pc = pool.get();
+ if (pc == null) {
+ pc = new PageContextImpl();
+ }
+ } else {
+ pc = new PageContextImpl();
+ }
+ pc.initialize(servlet, request, response, errorPageURL,
+ needsSession, bufferSize, autoflush);
+ return pc;
+ } catch (Throwable ex) {
+ /* FIXME: need to do something reasonable here!! */
+ log.fatal("Exception initializing page context", ex);
+ return null;
+ }
+ }
+
+ private void internalReleasePageContext(PageContext pc) {
+ pc.release();
+ if (USE_POOL && (pc instanceof PageContextImpl)) {
+ localPool.get().put(pc);
+ }
+ }
+
+ private class PrivilegedGetPageContext implements PrivilegedAction {
+
+ private JspFactoryImpl factory;
+ private Servlet servlet;
+ private ServletRequest request;
+ private ServletResponse response;
+ private String errorPageURL;
+ private boolean needsSession;
+ private int bufferSize;
+ private boolean autoflush;
+
+ PrivilegedGetPageContext(JspFactoryImpl factory, Servlet servlet,
+ ServletRequest request, ServletResponse response, String errorPageURL,
+ boolean needsSession, int bufferSize, boolean autoflush) {
+ this.factory = factory;
+ this.servlet = servlet;
+ this.request = request;
+ this.response = response;
+ this.errorPageURL = errorPageURL;
+ this.needsSession = needsSession;
+ this.bufferSize = bufferSize;
+ this.autoflush = autoflush;
+ }
+
+ public Object run() {
+ return factory.internalGetPageContext(servlet, request, response,
+ errorPageURL, needsSession, bufferSize, autoflush);
+ }
+ }
+
+ private class PrivilegedReleasePageContext implements PrivilegedAction {
+
+ private JspFactoryImpl factory;
+ private PageContext pageContext;
+
+ PrivilegedReleasePageContext(JspFactoryImpl factory,
+ PageContext pageContext) {
+ this.factory = factory;
+ this.pageContext = pageContext;
+ }
+
+ public Object run() {
+ factory.internalReleasePageContext(pageContext);
+ return null;
+ }
+ }
+
+ protected final class PageContextPool {
+
+ private PageContext[] pool;
+
+ private int current = -1;
+
+ public PageContextPool() {
+ this.pool = new PageContext[POOL_SIZE];
+ }
+
+ public void put(PageContext o) {
+ if (current < (POOL_SIZE - 1)) {
+ current++;
+ pool[current] = o;
+ }
+ }
+
+ public PageContext get() {
+ PageContext item = null;
+ if (current >= 0) {
+ item = pool[current];
+ current--;
+ }
+ return item;
+ }
+
+ }
+
+ public JspApplicationContext getJspApplicationContext(ServletContext context) {
+ return JspApplicationContextImpl.getInstance(context);
+ }
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFragmentHelper.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFragmentHelper.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFragmentHelper.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspFragmentHelper.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,65 @@
+/*
+ * 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 javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.JspFragment;
+import javax.servlet.jsp.tagext.JspTag;
+
+/**
+ * Helper class from which all Jsp Fragment helper classes extend.
+ * This class allows for the emulation of numerous fragments within
+ * a single class, which in turn reduces the load on the class loader
+ * since there are potentially many JspFragments in a single page.
+ * <p>
+ * The class also provides various utility methods for JspFragment
+ * implementations.
+ *
+ * @author Mark Roth
+ */
+public abstract class JspFragmentHelper
+ extends JspFragment
+{
+
+ protected int discriminator;
+ protected JspContext jspContext;
+ protected PageContext _jspx_page_context;
+ protected JspTag parentTag;
+
+ public JspFragmentHelper( int discriminator, JspContext jspContext,
+ JspTag parentTag )
+ {
+ this.discriminator = discriminator;
+ this.jspContext = jspContext;
+ this._jspx_page_context = null;
+ if( jspContext instanceof PageContext ) {
+ _jspx_page_context = (PageContext)jspContext;
+ }
+ this.parentTag = parentTag;
+ }
+
+ public JspContext getJspContext() {
+ return this.jspContext;
+ }
+
+ public JspTag getParentTag() {
+ return this.parentTag;
+ }
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspRuntimeLibrary.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspRuntimeLibrary.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspRuntimeLibrary.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspRuntimeLibrary.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,1047 @@
+/*
+ * 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.Constants;
+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( Constants.IS_SECURITY_ENABLED ) {
+ 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 {
+ Object tmpval = null;
+ 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()];
+
+ char holdchar;
+ 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, (Object[]) 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;
+ }
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspSourceDependent.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspSourceDependent.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspSourceDependent.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspSourceDependent.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * Interface for tracking the source files dependencies, for the purpose
+ * of compiling out of date pages. This is used for
+ * 1) files that are included by page directives
+ * 2) files that are included by include-prelude and include-coda in jsp:config
+ * 3) files that are tag files and referenced
+ * 4) TLDs referenced
+ */
+
+public interface JspSourceDependent {
+
+ /**
+ * Returns a list of files names that the current page has a source
+ * dependency on.
+ */
+ // FIXME: Type used is Object due to very weird behavior
+ // with Eclipse JDT 3.1 in Java 5 mode
+ public Object getDependants();
+
+}
Added: struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspWriterImpl.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspWriterImpl.java?rev=819435&view=auto
==============================================================================
--- struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspWriterImpl.java (added)
+++ struts/struts2/trunk/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/runtime/JspWriterImpl.java Mon Sep 28 00:43:34 2009
@@ -0,0 +1,590 @@
+/*
+ * 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.io.IOException;
+import java.io.Writer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.servlet.ServletResponse;
+import javax.servlet.jsp.JspWriter;
+
+import org.apache.jasper.Constants;
+import org.apache.jasper.compiler.Localizer;
+import org.apache.jasper.security.SecurityUtil;
+
+/**
+ * Write text to a character-output stream, buffering characters so as
+ * to provide for the efficient writing of single characters, arrays,
+ * and strings.
+ *
+ * Provide support for discarding for the output that has been
+ * buffered.
+ *
+ * This needs revisiting when the buffering problems in the JSP spec
+ * are fixed -akv
+ *
+ * @author Anil K. Vijendran
+ */
+public class JspWriterImpl extends JspWriter {
+
+ private Writer out;
+ private ServletResponse response;
+ private char cb[];
+ private int nextChar;
+ private boolean flushed = false;
+ private boolean closed = false;
+
+ public JspWriterImpl() {
+ super( Constants.DEFAULT_BUFFER_SIZE, true );
+ }
+
+ /**
+ * Create a buffered character-output stream that uses a default-sized
+ * output buffer.
+ *
+ * @param response A Servlet Response
+ */
+ public JspWriterImpl(ServletResponse response) {
+ this(response, Constants.DEFAULT_BUFFER_SIZE, true);
+ }
+
+ /**
+ * Create a new buffered character-output stream that uses an output
+ * buffer of the given size.
+ *
+ * @param response A Servlet Response
+ * @param sz Output-buffer size, a positive integer
+ *
+ * @exception IllegalArgumentException If sz is <= 0
+ */
+ public JspWriterImpl(ServletResponse response, int sz,
+ boolean autoFlush) {
+ super(sz, autoFlush);
+ if (sz < 0)
+ throw new IllegalArgumentException("Buffer size <= 0");
+ this.response = response;
+ cb = sz == 0 ? null : new char[sz];
+ nextChar = 0;
+ }
+
+ void init( ServletResponse response, int sz, boolean autoFlush ) {
+ this.response= response;
+ if( sz > 0 && ( cb == null || sz > cb.length ) )
+ cb=new char[sz];
+ nextChar = 0;
+ this.autoFlush=autoFlush;
+ this.bufferSize=sz;
+ }
+
+ /** Package-level access
+ */
+ void recycle() {
+ flushed = false;
+ closed = false;
+ out = null;
+ nextChar = 0;
+ response = null;
+ }
+
+ /**
+ * Flush the output buffer to the underlying character stream, without
+ * flushing the stream itself. This method is non-private only so that it
+ * may be invoked by PrintStream.
+ */
+ protected final void flushBuffer() throws IOException {
+ if (bufferSize == 0)
+ return;
+ flushed = true;
+ ensureOpen();
+ if (nextChar == 0)
+ return;
+ initOut();
+ out.write(cb, 0, nextChar);
+ nextChar = 0;
+ }
+
+ private void initOut() throws IOException {
+ if (out == null) {
+ out = response.getWriter();
+ }
+ }
+
+ private String getLocalizeMessage(final String message){
+ if (SecurityUtil.isPackageProtectionEnabled()){
+ return (String)AccessController.doPrivileged(new PrivilegedAction(){
+ public Object run(){
+ return Localizer.getMessage(message);
+ }
+ });
+ } else {
+ return Localizer.getMessage(message);
+ }
+ }
+
+ /**
+ * Discard the output buffer.
+ */
+ public final void clear() throws IOException {
+ if ((bufferSize == 0) && (out != null))
+ // clear() is illegal after any unbuffered output (JSP.5.5)
+ throw new IllegalStateException(
+ getLocalizeMessage("jsp.error.ise_on_clear"));
+ if (flushed)
+ throw new IOException(
+ getLocalizeMessage("jsp.error.attempt_to_clear_flushed_buffer"));
+ ensureOpen();
+ nextChar = 0;
+ }
+
+ public void clearBuffer() throws IOException {
+ if (bufferSize == 0)
+ throw new IllegalStateException(
+ getLocalizeMessage("jsp.error.ise_on_clear"));
+ ensureOpen();
+ nextChar = 0;
+ }
+
+ private final void bufferOverflow() throws IOException {
+ throw new IOException(getLocalizeMessage("jsp.error.overflow"));
+ }
+
+ /**
+ * Flush the stream.
+ *
+ */
+ public void flush() throws IOException {
+ flushBuffer();
+ if (out != null) {
+ out.flush();
+ }
+ }
+
+ /**
+ * Close the stream.
+ *
+ */
+ public void close() throws IOException {
+ if (response == null || closed)
+ // multiple calls to close is OK
+ return;
+ flush();
+ if (out != null)
+ out.close();
+ out = null;
+ closed = true;
+ }
+
+ /**
+ * @return the number of bytes unused in the buffer
+ */
+ public int getRemaining() {
+ return bufferSize - nextChar;
+ }
+
+ /** check to make sure that the stream has not been closed */
+ private void ensureOpen() throws IOException {
+ if (response == null || closed)
+ throw new IOException("Stream closed");
+ }
+
+
+ /**
+ * Write a single character.
+ */
+ public void write(int c) throws IOException {
+ ensureOpen();
+ if (bufferSize == 0) {
+ initOut();
+ out.write(c);
+ }
+ else {
+ if (nextChar >= bufferSize)
+ if (autoFlush)
+ flushBuffer();
+ else
+ bufferOverflow();
+ cb[nextChar++] = (char) c;
+ }
+ }
+
+ /**
+ * Our own little min method, to avoid loading java.lang.Math if we've run
+ * out of file descriptors and we're trying to print a stack trace.
+ */
+ private int min(int a, int b) {
+ if (a < b) return a;
+ return b;
+ }
+
+ /**
+ * Write a portion of an array of characters.
+ *
+ * <p> Ordinarily this method stores characters from the given array into
+ * this stream's buffer, flushing the buffer to the underlying stream as
+ * needed. If the requested length is at least as large as the buffer,
+ * however, then this method will flush the buffer and write the characters
+ * directly to the underlying stream. Thus redundant
+ * <code>DiscardableBufferedWriter</code>s will not copy data unnecessarily.
+ *
+ * @param cbuf A character array
+ * @param off Offset from which to start reading characters
+ * @param len Number of characters to write
+ */
+ public void write(char cbuf[], int off, int len)
+ throws IOException
+ {
+ ensureOpen();
+
+ if (bufferSize == 0) {
+ initOut();
+ out.write(cbuf, off, len);
+ return;
+ }
+
+ if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+ ((off + len) > cbuf.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return;
+ }
+
+ if (len >= bufferSize) {
+ /* If the request length exceeds the size of the output buffer,
+ flush the buffer and then write the data directly. In this
+ way buffered streams will cascade harmlessly. */
+ if (autoFlush)
+ flushBuffer();
+ else
+ bufferOverflow();
+ initOut();
+ out.write(cbuf, off, len);
+ return;
+ }
+
+ int b = off, t = off + len;
+ while (b < t) {
+ int d = min(bufferSize - nextChar, t - b);
+ System.arraycopy(cbuf, b, cb, nextChar, d);
+ b += d;
+ nextChar += d;
+ if (nextChar >= bufferSize)
+ if (autoFlush)
+ flushBuffer();
+ else
+ bufferOverflow();
+ }
+
+ }
+
+ /**
+ * Write an array of characters. This method cannot be inherited from the
+ * Writer class because it must suppress I/O exceptions.
+ */
+ public void write(char buf[]) throws IOException {
+ write(buf, 0, buf.length);
+ }
+
+ /**
+ * Write a portion of a String.
+ *
+ * @param s String to be written
+ * @param off Offset from which to start reading characters
+ * @param len Number of characters to be written
+ */
+ public void write(String s, int off, int len) throws IOException {
+ ensureOpen();
+ if (bufferSize == 0) {
+ initOut();
+ out.write(s, off, len);
+ return;
+ }
+ int b = off, t = off + len;
+ while (b < t) {
+ int d = min(bufferSize - nextChar, t - b);
+ s.getChars(b, b + d, cb, nextChar);
+ b += d;
+ nextChar += d;
+ if (nextChar >= bufferSize)
+ if (autoFlush)
+ flushBuffer();
+ else
+ bufferOverflow();
+ }
+ }
+
+ /**
+ * Write a string. This method cannot be inherited from the Writer class
+ * because it must suppress I/O exceptions.
+ */
+ public void write(String s) throws IOException {
+ // Simple fix for Bugzilla 35410
+ // Calling the other write function so as to init the buffer anyways
+ if(s == null) {
+ write(s, 0, 0);
+ } else {
+ write(s, 0, s.length());
+ }
+ }
+
+
+ static String lineSeparator = System.getProperty("line.separator");
+
+ /**
+ * Write a line separator. The line separator string is defined by the
+ * system property <tt>line.separator</tt>, and is not necessarily a single
+ * newline ('\n') character.
+ *
+ * @exception IOException If an I/O error occurs
+ */
+
+ public void newLine() throws IOException {
+ write(lineSeparator);
+ }
+
+
+ /* Methods that do not terminate lines */
+
+ /**
+ * Print a boolean value. The string produced by <code>{@link
+ * java.lang.String#valueOf(boolean)}</code> is translated into bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link
+ * #write(int)}</code> method.
+ *
+ * @param b The <code>boolean</code> to be printed
+ */
+ public void print(boolean b) throws IOException {
+ write(b ? "true" : "false");
+ }
+
+ /**
+ * Print a character. The character is translated into one or more bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link
+ * #write(int)}</code> method.
+ *
+ * @param c The <code>char</code> to be printed
+ */
+ public void print(char c) throws IOException {
+ write(String.valueOf(c));
+ }
+
+ /**
+ * Print an integer. The string produced by <code>{@link
+ * java.lang.String#valueOf(int)}</code> is translated into bytes according
+ * to the platform's default character encoding, and these bytes are
+ * written in exactly the manner of the <code>{@link #write(int)}</code>
+ * method.
+ *
+ * @param i The <code>int</code> to be printed
+ */
+ public void print(int i) throws IOException {
+ write(String.valueOf(i));
+ }
+
+ /**
+ * Print a long integer. The string produced by <code>{@link
+ * java.lang.String#valueOf(long)}</code> is translated into bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link #write(int)}</code>
+ * method.
+ *
+ * @param l The <code>long</code> to be printed
+ */
+ public void print(long l) throws IOException {
+ write(String.valueOf(l));
+ }
+
+ /**
+ * Print a floating-point number. The string produced by <code>{@link
+ * java.lang.String#valueOf(float)}</code> is translated into bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link #write(int)}</code>
+ * method.
+ *
+ * @param f The <code>float</code> to be printed
+ */
+ public void print(float f) throws IOException {
+ write(String.valueOf(f));
+ }
+
+ /**
+ * Print a double-precision floating-point number. The string produced by
+ * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
+ * bytes according to the platform's default character encoding, and these
+ * bytes are written in exactly the manner of the <code>{@link
+ * #write(int)}</code> method.
+ *
+ * @param d The <code>double</code> to be printed
+ */
+ public void print(double d) throws IOException {
+ write(String.valueOf(d));
+ }
+
+ /**
+ * Print an array of characters. The characters are converted into bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link #write(int)}</code>
+ * method.
+ *
+ * @param s The array of chars to be printed
+ *
+ * @throws NullPointerException If <code>s</code> is <code>null</code>
+ */
+ public void print(char s[]) throws IOException {
+ write(s);
+ }
+
+ /**
+ * Print a string. If the argument is <code>null</code> then the string
+ * <code>"null"</code> is printed. Otherwise, the string's characters are
+ * converted into bytes according to the platform's default character
+ * encoding, and these bytes are written in exactly the manner of the
+ * <code>{@link #write(int)}</code> method.
+ *
+ * @param s The <code>String</code> to be printed
+ */
+ public void print(String s) throws IOException {
+ if (s == null) {
+ s = "null";
+ }
+ write(s);
+ }
+
+ /**
+ * Print an object. The string produced by the <code>{@link
+ * java.lang.String#valueOf(Object)}</code> method is translated into bytes
+ * according to the platform's default character encoding, and these bytes
+ * are written in exactly the manner of the <code>{@link #write(int)}</code>
+ * method.
+ *
+ * @param obj The <code>Object</code> to be printed
+ */
+ public void print(Object obj) throws IOException {
+ write(String.valueOf(obj));
+ }
+
+ /* Methods that do terminate lines */
+
+ /**
+ * Terminate the current line by writing the line separator string. The
+ * line separator string is defined by the system property
+ * <code>line.separator</code>, and is not necessarily a single newline
+ * character (<code>'\n'</code>).
+ *
+ * Need to change this from PrintWriter because the default
+ * println() writes to the sink directly instead of through the
+ * write method...
+ */
+ public void println() throws IOException {
+ newLine();
+ }
+
+ /**
+ * Print a boolean value and then terminate the line. This method behaves
+ * as though it invokes <code>{@link #print(boolean)}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(boolean x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print a character and then terminate the line. This method behaves as
+ * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
+ * #println()}</code>.
+ */
+ public void println(char x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print an integer and then terminate the line. This method behaves as
+ * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
+ * #println()}</code>.
+ */
+ public void println(int x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print a long integer and then terminate the line. This method behaves
+ * as though it invokes <code>{@link #print(long)}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(long x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print a floating-point number and then terminate the line. This method
+ * behaves as though it invokes <code>{@link #print(float)}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(float x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print a double-precision floating-point number and then terminate the
+ * line. This method behaves as though it invokes <code>{@link
+ * #print(double)}</code> and then <code>{@link #println()}</code>.
+ */
+ public void println(double x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print an array of characters and then terminate the line. This method
+ * behaves as though it invokes <code>{@link #print(char[])}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(char x[]) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print a String and then terminate the line. This method behaves as
+ * though it invokes <code>{@link #print(String)}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(String x) throws IOException {
+ print(x);
+ println();
+ }
+
+ /**
+ * Print an Object and then terminate the line. This method behaves as
+ * though it invokes <code>{@link #print(Object)}</code> and then
+ * <code>{@link #println()}</code>.
+ */
+ public void println(Object x) throws IOException {
+ print(x);
+ println();
+ }
+
+}