# For JSTL changes:
# http://jcp.org/aboutJava/communityprocess/maintenance/jsr052/jstl-1_2-mr-changeLog_PFD.html
# Build system changes. New versions of spec jars (servlet, jsp, el). Cactus fix.
M build_sample_standard.properties
M build-tests.xml
M build.xml
# old tld is copied to the side for history. New tld sees some name/version changing and the addition of
# deferred value (as per JSTL change #1) to:
## ForEachTag
## ForTokensTag
## SetTag
A conf/c-1_1.tld
M conf/c.tld
# OutputProperties replaced with OutputPropertiesFactory. Deprecated method change in Xalan.
M src/org/apache/taglibs/standard/extra/spath/SPathFilter.java
# Change the version. Not spec related.
M src/org/apache/taglibs/standard/Version.java
# setItems moved from String to Object. JSTL change #1
M src/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java
# Support for Java 6 JDBC; AND SecurityManager code added to a call to get ClassLoader
M src/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java
# SecurityManager code added to call to get ClassLoader
M src/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java
# Test related to Version change
M test/org/apache/taglibs/standard/TestVersion.java
# Generified method as per JSTL change #3
M src/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.java
# New method added for JSP 2.1 additional method in stub class
M test/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java
# Large change to support JSTL change #2
#TODO# Commented out section with question in may need deleting or uncommenting
# Also the convertToExpectedType method is changed to use new EL API.
M src/org/apache/taglibs/standard/tag/common/core/SetSupport.java
# Changes to support JSTL change #1. Not as large as it looks - code was indented.
M src/javax/servlet/jsp/jstl/core/LoopTagSupport.java
# Large change to support JSTL change #1
#TODO# Various questions in determineLengthAndType to look at
#TODO# prepare has commented out code in it to consider deleting
M src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java
# Large change to support JSTL change #1
M src/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java
# New classes in JSTL 1.2. Only mention in spec is the javadoc,
# but they're there to support change#1 by the look of it.
#TODO# Need javadoc explaining all three.
A src/javax/servlet/jsp/jstl/core/IteratedExpression.java
#TODO# Ensure equals() method is explained. Broken hashcode contract?
A src/javax/servlet/jsp/jstl/core/IndexedValueExpression.java
A src/javax/servlet/jsp/jstl/core/IteratedValueExpression.java
diff --git a/build-tests.xml b/build-tests.xml
index aa9acb6..a6fde56 100644
--- a/build-tests.xml
+++ b/build-tests.xml
@@ -20,8 +20,9 @@
jstl.jar JSTL API jar file
standard.jar JSTL implementation jar file
- servlet24.jar Servlet 2.4 jar
- jsp20.jar JSP 2.0 jar
+ servlet25.jar Servlet 2.5 jar
+ jsp21.jar JSP 2.1 jar
+ el.jar Unified EL jar
junit.jar JUnit jar
@@ -99,6 +100,9 @@
<property name="junit.jar"
value="${tomcat.home}/../junit3.8.1/junit.jar"/>
+ <property name="commons-logging.jar"
+ value="${cactus.home}/lib/commons-logging-1.0.4.jar"/>
+
<property name="standard.jar"
value="${tomcat.home}/jstl/lib/standard.jar"/>
@@ -125,9 +129,11 @@
<echo>optimize: ${compile.optimize}</echo>
<echo>---------- Dependencies ---------------------</echo>
<echo>tomcat.home=${tomcat.home}</echo>
- <echo>servlet24.jar: ${servlet24.jar}</echo>
- <echo>jsp20.jar: ${jsp20.jar}</echo>
+ <echo>servlet25.jar: ${servlet25.jar}</echo>
+ <echo>jsp21.jar: ${jsp21.jar}</echo>
+ <echo>el.jar: ${el.jar}</echo>
<echo>junit.jar: ${junit.jar}</echo>
+ <echo>commons-logging.jar: ${commons-logging.jar}</echo>
<echo>cactus.home: ${cactus.home}</echo>
<echo>cactus.ant.jar: ${cactus.ant.jar}</echo>
<echo>cactus.jar: ${cactus.jar}</echo>
@@ -150,9 +156,11 @@
<path id="compile.classpath">
<pathelement location="${jstl.jar}"/>
<pathelement location="${standard.jar}"/>
- <pathelement location="${servlet24.jar}"/>
- <pathelement location="${jsp20.jar}"/>
+ <pathelement location="${servlet25.jar}"/>
+ <pathelement location="${jsp21.jar}"/>
+ <pathelement location="${el.jar}"/>
<pathelement location="${junit.jar}"/>
+ <pathelement location="${commons-logging.jar}"/>
<pathelement location="${cactus.jar}"/>
<pathelement location="${httpclient.jar}"/>
<pathelement location="${aspectjrt.jar}"/>
@@ -243,6 +251,7 @@
<copy file="${jstl.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
<copy file="${standard.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
<copy file="${junit.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
+ <copy file="${commons-logging.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
<copy file="${cactus.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
<copy file="${httpclient.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
<copy file="${aspectjrt.jar}" todir="${out.test.dir}/WEB-INF/lib"/>
@@ -377,7 +386,7 @@
<include name="**/TestVersion.java"/>
<include name="**/StaticFunctionTests.java"/>
<include name="**/ParserTest.java"/>
- <exclude name="**/EvaluationTest.java"/>
+ <include name="**/EvaluationTest.java"/>
<exclude name="**/testutil/*.java"/>
</fileset>
</batchtest>
diff --git a/build.xml b/build.xml
index 52f174a..8582a6e 100644
--- a/build.xml
+++ b/build.xml
@@ -4,7 +4,7 @@
<!-- Version Number -->
<!-- =================================================================== -->
- <property name="standard-version" value="1.1.2" />
+ <property name="standard-version" value="1.2.0" />
<property name="release.name" value="jakarta-taglibs-standard-${standard-version}" />
<property name="release.pre" value="nop" />
<property name="release.post" value="nop" />
@@ -54,8 +54,9 @@
<echo>deprecation: ${compile.deprecation}</echo>
<echo>optimize: ${optimize.debug}</echo>
<echo>---------- Dependencies ---------------------</echo>
- <echo>servlet24.jar: ${servlet24.jar}</echo>
- <echo>jsp20.jar: ${jsp20.jar}</echo>
+ <echo>servlet25.jar: ${servlet25.jar}</echo>
+ <echo>jsp21.jar: ${jsp21.jar}</echo>
+ <echo>el.jar: ${el.jar}</echo>
<echo>jdbc2_0-stdext.jar: ${jdbc2_0-stdext.jar}</echo>
<echo>jaxp-api.jar: ${jaxp-api.jar}</echo>
<echo>dom.jar: ${dom.jar}</echo>
@@ -78,15 +79,21 @@
<!-- Check the build/runtime dependencies -->
<antcall target="requiredJar">
- <param name="prop" value="servlet24.jar"/>
- <param name="file" value="${servlet24.jar}"/>
- <param name="desc" value="Servlet 2.4 API classes"/>
+ <param name="prop" value="servlet25.jar"/>
+ <param name="file" value="${servlet25.jar}"/>
+ <param name="desc" value="Servlet 2.5 API classes"/>
</antcall>
<antcall target="requiredJar">
- <param name="prop" value="jsp20.jar"/>
- <param name="file" value="${jsp20.jar}"/>
- <param name="desc" value="JSP 2.0 API classes"/>
+ <param name="prop" value="jsp21.jar"/>
+ <param name="file" value="${jsp21.jar}"/>
+ <param name="desc" value="JSP 2.1 API classes"/>
+ </antcall>
+
+ <antcall target="requiredJar">
+ <param name="prop" value="el.jar"/>
+ <param name="file" value="${el.jar}"/>
+ <param name="desc" value="Unified EL API classes"/>
</antcall>
<antcall target="processIfPropSet">
@@ -173,7 +180,7 @@
srcdir="${library.src}"
destdir="${build.library}/classes"
bootclasspath="${xalan.jar}:${java.runtime.jar}"
- classpath="${servlet24.jar}:${jsp20.jar}:${jdbc2_0-stdext.jar}:${jaxp-api.jar}:${dom.jar}:${sax.jar}"
+ classpath="${servlet25.jar}:${jsp21.jar}:${el.jar}:${jdbc2_0-stdext.jar}:${jaxp-api.jar}:${dom.jar}:${sax.jar}"
excludes="org/apache/taglibs/standard/lang/jstl/parser/jsp20/* org/apache/taglibs/standard/lang/jpath/** org/apache/taglibs/standard/lang/spel/**"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
@@ -276,7 +283,7 @@
<!-- Compile the examples source code -->
<javac srcdir="${examples.src}" destdir="${build.examples}/WEB-INF/classes"
- classpath="${servlet24.jar}:${jsp20.jar}:${build.library}/classes"
+ classpath="${servlet25.jar}:${jsp21.jar}:${el.jar}:${build.library}/classes"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
optimize="${compile.optimize}"/>
@@ -362,7 +369,7 @@
<target name="javadoc-dist" depends="prepare-dist">
<javadoc packagenames="javax.servlet.jsp.jstl.*"
sourcepath="src"
- classpath="${servlet24.jar}:${jsp20.jar}:${jdbc2_0-stdext.jar}:${jaxp-api.jar}:${dom.jar}:${sax.jar}:${xercesImpl.jar}:${xalan.jar}"
+ classpath="${servlet25.jar}:${jsp21.jar}:${el.jar}:${jdbc2_0-stdext.jar}:${jaxp-api.jar}:${dom.jar}:${sax.jar}:${xercesImpl.jar}:${xalan.jar}"
destdir="${dist.library}/javadoc"
bottom='<font size="-1">Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.</font>'/>
</target>
diff --git a/build_sample_standard.properties b/build_sample_standard.properties
index 217647e..5d32d27 100644
--- a/build_sample_standard.properties
+++ b/build_sample_standard.properties
@@ -66,12 +66,12 @@
junit.jar=
cactus.home=
-cactus.jar=${cactus.home}/lib/cactus-1.6.1.jar
-cactus.ant.jar=${cactus.home}/lib/cactus-ant-1.6.1.jar
-aspectjrt.jar=${cactus.home}/lib/aspectjrt-1.1.1.jar
-httpclient.jar=${cactus.home}/lib/commons-httpclient-2.0.jar
-commons-logging.jar=${cactus.home}/lib/commons-logging-1.0.3.jar
-derby.jar=${cactus.home}/lib/derby-10.2.2.0.jar
+cactus.jar=${cactus.home}/lib/cactus-1.7.1.jar
+cactus.ant.jar=${cactus.home}/lib/cactus-ant-1.7.1.jar
+aspectjrt.jar=${cactus.home}/lib/aspectjrt-1.2.1.jar
+httpclient.jar=${cactus.home}/lib/commons-httpclient-2.0.2.jar
+commons-logging.jar=${cactus.home}/lib/commons-logging-1.0.4.jar
+derby.jar=
# --------------------------------------------------
# RUN-TIME COMPONENTS FOR UNIT TESTS
diff --git a/conf/c-1_1.tld b/conf/c-1_1.tld
new file mode 100644
index 0000000..71d3a86
--- /dev/null
+++ b/conf/c-1_1.tld
@@ -0,0 +1,563 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
+ version="2.0">
+
+ <description>JSTL 1.1 core library</description>
+ <display-name>JSTL core</display-name>
+ <tlib-version>1.1</tlib-version>
+ <short-name>c</short-name>
+ <uri>http://java.sun.com/jsp/jstl/core_1_1</uri>
+
+ <validator>
+ <description>
+ Provides core validation features for JSTL tags.
+ </description>
+ <validator-class>
+ org.apache.taglibs.standard.tlv.JstlCoreTLV
+ </validator-class>
+ </validator>
+
+ <tag>
+ <description>
+ Catches any Throwable that occurs in its body and optionally
+ exposes it.
+ </description>
+ <name>catch</name>
+ <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+exception thrown from a nested action. The type of the
+scoped variable is the type of the exception thrown.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Simple conditional tag that establishes a context for
+ mutually exclusive conditional operations, marked by
+ <when> and <otherwise>
+ </description>
+ <name>choose</name>
+ <tag-class>org.apache.taglibs.standard.tag.common.core.ChooseTag</tag-class>
+ <body-content>JSP</body-content>
+ </tag>
+
+ <tag>
+ <description>
+ Simple conditional tag, which evalutes its body if the
+ supplied condition is true and optionally exposes a Boolean
+ scripting variable representing the evaluation of this condition
+ </description>
+ <name>if</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.IfTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+The test condition that determines whether or
+not the body content should be processed.
+ </description>
+ <name>test</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+resulting value of the test condition. The type
+of the scoped variable is Boolean.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Scope for var.
+ </description>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Retrieves an absolute or relative URL and exposes its contents
+ to either the page, a String in 'var', or a Reader in 'varReader'.
+ </description>
+ <name>import</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.ImportTag</tag-class>
+ <tei-class>org.apache.taglibs.standard.tei.ImportTEI</tei-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+The URL of the resource to import.
+ </description>
+ <name>url</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is String.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Scope for var.
+ </description>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+resource's content. The type of the scoped
+variable is Reader.
+ </description>
+ <name>varReader</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the context when accessing a relative
+URL resource that belongs to a foreign
+context.
+ </description>
+ <name>context</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Character encoding of the content at the input
+resource.
+ </description>
+ <name>charEncoding</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ The basic iteration tag, accepting many different
+ collection types and supporting subsetting and other
+ functionality
+ </description>
+ <name>forEach</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.ForEachTag</tag-class>
+ <tei-class>org.apache.taglibs.standard.tei.ForEachTEI</tei-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Collection of items to iterate over.
+ </description>
+ <name>items</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Object</type>
+ </attribute>
+ <attribute>
+ <description>
+If items specified:
+Iteration begins at the item located at the
+specified index. First item of the collection has
+index 0.
+If items not specified:
+Iteration begins with index set at the value
+specified.
+ </description>
+ <name>begin</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+If items specified:
+Iteration ends at the item located at the
+specified index (inclusive).
+If items not specified:
+Iteration ends when index reaches the value
+specified.
+ </description>
+ <name>end</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+Iteration will only process every step items of
+the collection, starting with the first one.
+ </description>
+ <name>step</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility. Its type depends
+on the object of the underlying collection.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of type
+javax.servlet.jsp.jstl.core.LoopTagStatus. This scoped variable has nested
+visibility.
+ </description>
+ <name>varStatus</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Iterates over tokens, separated by the supplied delimeters
+ </description>
+ <name>forTokens</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.ForTokensTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+String of tokens to iterate over.
+ </description>
+ <name>items</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ <attribute>
+ <description>
+The set of delimiters (the characters that
+separate the tokens in the string).
+ </description>
+ <name>delims</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ <attribute>
+ <description>
+Iteration begins at the token located at the
+specified index. First token has index 0.
+ </description>
+ <name>begin</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+Iteration ends at the token located at the
+specified index (inclusive).
+ </description>
+ <name>end</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+Iteration will only process every step tokens
+of the string, starting with the first one.
+ </description>
+ <name>step</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+current item of the iteration. This scoped
+variable has nested visibility.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+status of the iteration. Object exported is of
+type
+javax.servlet.jsp.jstl.core.LoopTag
+Status. This scoped variable has nested
+visibility.
+ </description>
+ <name>varStatus</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Like <%= ... >, but for expressions.
+ </description>
+ <name>out</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.OutTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Expression to be evaluated.
+ </description>
+ <name>value</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Default value if the resulting value is null.
+ </description>
+ <name>default</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Determines whether characters <,>,&,'," in the
+resulting string should be converted to their
+corresponding character entity codes. Default value is
+true.
+ </description>
+ <name>escapeXml</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+
+ <tag>
+ <description>
+ Subtag of <choose> that follows <when> tags
+ and runs only if all of the prior conditions evaluated to
+ 'false'
+ </description>
+ <name>otherwise</name>
+ <tag-class>org.apache.taglibs.standard.tag.common.core.OtherwiseTag</tag-class>
+ <body-content>JSP</body-content>
+ </tag>
+
+ <tag>
+ <description>
+ Adds a parameter to a containing 'import' tag's URL.
+ </description>
+ <name>param</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.ParamTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Name of the query string parameter.
+ </description>
+ <name>name</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Value of the parameter.
+ </description>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Redirects to a new URL.
+ </description>
+ <name>redirect</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.RedirectTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+The URL of the resource to redirect to.
+ </description>
+ <name>url</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the context when redirecting to a relative URL
+resource that belongs to a foreign context.
+ </description>
+ <name>context</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Removes a scoped variable (from a particular scope, if specified).
+ </description>
+ <name>remove</name>
+ <tag-class>org.apache.taglibs.standard.tag.common.core.RemoveTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>
+Name of the scoped variable to be removed.
+ </description>
+ <name>var</name>
+ <required>true</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Scope for var.
+ </description>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Sets the result of an expression evaluation in a 'scope'
+ </description>
+ <name>set</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.SetTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Name of the exported scoped variable to hold the value
+specified in the action. The type of the scoped variable is
+whatever type the value expression evaluates to.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Expression to be evaluated.
+ </description>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Target object whose property will be set. Must evaluate to
+a JavaBeans object with setter property property, or to a
+java.util.Map object.
+ </description>
+ <name>target</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the property to be set in the target object.
+ </description>
+ <name>property</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Scope for var.
+ </description>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Creates a URL with optional query parameters.
+ </description>
+ <name>url</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.UrlTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+Name of the exported scoped variable for the
+processed url. The type of the scoped variable is
+String.
+ </description>
+ <name>var</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Scope for var.
+ </description>
+ <name>scope</name>
+ <required>false</required>
+ <rtexprvalue>false</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+URL to be processed.
+ </description>
+ <name>value</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ <attribute>
+ <description>
+Name of the context when specifying a relative URL
+resource that belongs to a foreign context.
+ </description>
+ <name>context</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ </attribute>
+ </tag>
+
+ <tag>
+ <description>
+ Subtag of <choose> that includes its body if its
+ condition evalutes to 'true'
+ </description>
+ <name>when</name>
+ <tag-class>org.apache.taglibs.standard.tag.rt.core.WhenTag</tag-class>
+ <body-content>JSP</body-content>
+ <attribute>
+ <description>
+The test condition that determines whether or not the
+body content should be processed.
+ </description>
+ <name>test</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>boolean</type>
+ </attribute>
+ </tag>
+
+</taglib>
diff --git a/conf/c.tld b/conf/c.tld
index 22698c9..60879c2 100644
--- a/conf/c.tld
+++ b/conf/c.tld
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
+<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
- version="2.0">
-
- <description>JSTL 1.1 core library</description>
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
+ version="2.1">
+
+ <description>JSTL 1.2 core library</description>
<display-name>JSTL core</display-name>
- <tlib-version>1.1</tlib-version>
+ <tlib-version>1.2</tlib-version>
<short-name>c</short-name>
<uri>http://java.sun.com/jsp/jstl/core</uri>
@@ -174,6 +174,9 @@
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.Object</type>
+ <deferred-value>
+ <type>java.lang.Object</type>
+ </deferred-value>
</attribute>
<attribute>
<description>
@@ -253,6 +256,9 @@
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>java.lang.String</type>
+ <deferred-value>
+ <type>java.lang.String</type>
+ </deferred-value>
</attribute>
<attribute>
<description>
@@ -467,6 +473,9 @@
<name>value</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
+ <deferred-value>
+ <type>java.lang.Object</type>
+ </deferred-value>
</attribute>
<attribute>
<description>
diff --git a/src/javax/servlet/jsp/jstl/core/IndexedValueExpression.java b/src/javax/servlet/jsp/jstl/core/IndexedValueExpression.java
new file mode 100644
index 0000000..9ed0e2d
--- /dev/null
+++ b/src/javax/servlet/jsp/jstl/core/IndexedValueExpression.java
@@ -0,0 +1,80 @@
+/**
+ * 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 javax.servlet.jsp.jstl.core;
+
+import java.io.Serializable;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+
+public final class IndexedValueExpression extends ValueExpression implements Serializable {
+
+ private static final long serialVersionUID = -7300711701036452952L;
+ protected final Integer i;
+ protected final ValueExpression orig;
+
+ public IndexedValueExpression(ValueExpression valueExpression, int _i) {
+ orig = valueExpression;
+ i=_i;
+ }
+
+ public boolean equals(Object arg0) {
+ boolean rc=false;
+ if (arg0!=null) {
+ if (arg0.equals(orig)) {
+ rc = true;
+ }
+ }
+ return rc;
+ }
+
+ public Class getExpectedType() {
+ return orig.getExpectedType();
+ }
+
+ public String getExpressionString() {
+ return orig.getExpressionString();
+ }
+
+ public Class getType(ELContext elContext) {
+ return elContext.getELResolver().getType(elContext, orig.getValue(elContext), i);
+ }
+
+ public Object getValue(ELContext elContext) {
+ return elContext.getELResolver().getValue(elContext, orig.getValue(elContext), i);
+ }
+
+ public int hashCode() {
+ return orig.hashCode()+i;
+ }
+
+ public boolean isLiteralText() {
+ return false;
+ }
+
+ public boolean isReadOnly(ELContext elContext) {
+ return elContext.getELResolver().isReadOnly(elContext, orig.getValue(elContext), i);
+ }
+
+ public void setValue(ELContext elContext, Object arg1) {
+ elContext.getELResolver().setValue(elContext, orig.getValue(elContext), i, arg1);
+ }
+
+}
diff --git a/src/javax/servlet/jsp/jstl/core/IteratedExpression.java b/src/javax/servlet/jsp/jstl/core/IteratedExpression.java
new file mode 100644
index 0000000..6c7b7dd
--- /dev/null
+++ b/src/javax/servlet/jsp/jstl/core/IteratedExpression.java
@@ -0,0 +1,136 @@
+/**
+ * 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 javax.servlet.jsp.jstl.core;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+
+public final class IteratedExpression {
+ protected final ValueExpression orig;
+ protected final String delims;
+ private Object originalListObject = null;
+ private Iterator currentListObject = null;
+ private int currentIndex=0;
+ private enum TypesEnum {Undefined, ACollection, AnIterator, AnEnumeration, AMap, AString};
+ private TypesEnum type = TypesEnum.Undefined;
+
+ public IteratedExpression(ValueExpression valueExpression, String stringTokenSeparator) {
+ orig = valueExpression;
+ delims = stringTokenSeparator;
+ }
+
+ public Object getItem(ELContext context, int i) {
+ if (originalListObject == null) {
+ originalListObject = orig.getValue(context);
+ if (originalListObject instanceof Collection){
+ type=TypesEnum.ACollection;
+ } else if (originalListObject instanceof Iterator) {
+ type=TypesEnum.AnIterator;
+ } else if (originalListObject instanceof Enumeration) {
+ type=TypesEnum.AnEnumeration;
+ } else if (originalListObject instanceof Map) {
+ type=TypesEnum.AMap;
+ } else if (originalListObject instanceof String) { //StringTokens
+ type=TypesEnum.AString;
+ } else {
+ //it's of some other type ... should never get here
+ throw new RuntimeException("IteratedExpression.getItem: Object not of correct type.");
+ }
+ currentListObject = returnNewIterator(originalListObject, type);
+ }
+ Object currentObject=null;
+ if (i<currentIndex) {
+ currentListObject = returnNewIterator(originalListObject, type);
+ currentIndex = 0;
+ }
+ for (;currentIndex<=i;currentIndex++) {
+ if (currentListObject.hasNext()) {
+ currentObject= currentListObject.next();
+ } else {
+ throw new RuntimeException("IteratedExpression.getItem: Index out of Bounds");
+ }
+ }
+ return currentObject;
+ }
+
+ public ValueExpression getValueExpression() {
+ return orig;
+ }
+
+ private Iterator returnNewIterator(Object o, TypesEnum type) {
+ Iterator i = null;
+ switch (type) {
+ case ACollection:
+ i = ((Collection)o).iterator();
+ break;
+ case AnIterator:
+ if (currentListObject==null) {
+ //first time through ... need to create Vector for originalListObject
+ Vector v = new Vector();
+ Iterator myI = (Iterator)o;
+ while (myI.hasNext()) {
+ v.add(myI.next());
+ }
+ originalListObject = v;
+ }
+ i = ((Vector)originalListObject).iterator();
+ break;
+ case AnEnumeration:
+ if (currentListObject==null) {
+ //first time through ... need to create Vector for originalListObject
+ Vector v = new Vector();
+ Enumeration myE = (Enumeration)o;
+ while (myE.hasMoreElements()) {
+ v.add(myE.nextElement());
+ }
+ originalListObject = v;
+ }
+ i = ((Vector)originalListObject).iterator();
+ break;
+ case AMap:
+ Set s = ((Map)o).entrySet();
+ i = s.iterator();
+ break;
+ case AString:
+ if (currentListObject==null) {
+ //first time through ... need to create Vector for originalListObject
+ Vector v = new Vector();
+ StringTokenizer st = new StringTokenizer((String)o, delims);
+ while (st.hasMoreElements()) {
+ v.add(st.nextElement());
+ }
+ originalListObject = v;
+ }
+ i = ((Vector)originalListObject).iterator();
+ break;
+ default: //do Nothing ... this is not possible
+ break;
+ }
+ return i;
+ }
+}
\ No newline at end of file
diff --git a/src/javax/servlet/jsp/jstl/core/IteratedValueExpression.java b/src/javax/servlet/jsp/jstl/core/IteratedValueExpression.java
new file mode 100644
index 0000000..fe11b52
--- /dev/null
+++ b/src/javax/servlet/jsp/jstl/core/IteratedValueExpression.java
@@ -0,0 +1,78 @@
+/**
+ * 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 javax.servlet.jsp.jstl.core;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+
+public final class IteratedValueExpression extends ValueExpression {
+
+ private static final long serialVersionUID = 2771035360633553883L;
+ //IteratedExpression is not serializable
+ protected final IteratedExpression iteratedExpression;
+ protected final int i;
+
+ public IteratedValueExpression(IteratedExpression _iteratedExpression, int _i) {
+ iteratedExpression = _iteratedExpression;
+ i = _i;
+ }
+
+ public boolean equals(Object arg0) {
+ if (arg0==null) {
+ return false;
+ }
+ if (iteratedExpression.getValueExpression().equals(arg0)) {
+ return true;
+ }
+ return false;
+ }
+
+ public Class getExpectedType() {
+ return iteratedExpression.getValueExpression().getExpectedType();
+ }
+
+ public String getExpressionString() {
+ return iteratedExpression.getValueExpression().getExpressionString();
+ }
+
+ public Class getType(ELContext elContext) {
+ return iteratedExpression.getValueExpression().getType(elContext);
+ }
+
+ public Object getValue(ELContext elContext) {
+ return iteratedExpression.getItem(elContext, i);
+ }
+
+ public int hashCode() {
+ return iteratedExpression.hashCode()+i;
+ }
+
+ public boolean isLiteralText() {
+ return false;
+ }
+
+ public boolean isReadOnly(ELContext elContext) {
+ return true;
+ }
+
+ public void setValue(ELContext elContext, Object arg1) {
+ }
+
+}
diff --git a/src/javax/servlet/jsp/jstl/core/LoopTagSupport.java b/src/javax/servlet/jsp/jstl/core/LoopTagSupport.java
index efd6612..051deaf 100644
--- a/src/javax/servlet/jsp/jstl/core/LoopTagSupport.java
+++ b/src/javax/servlet/jsp/jstl/core/LoopTagSupport.java
@@ -17,6 +17,9 @@
package javax.servlet.jsp.jstl.core;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
@@ -105,6 +108,7 @@
/** Attribute-exposing control */
protected String itemId, statusId;
+ protected ValueExpression deferredExpression=null;
//*********************************************************************
// 'Private' state (implementation details)
@@ -501,28 +505,33 @@
*/
private void exposeVariables() throws JspTagException {
- /*
- * We need to support null items returned from next(); we
- * do this simply by passing such non-items through to the
- * scoped variable as effectively 'null' (that is, by calling
- * removeAttribute()).
- *
- * Also, just to be defensive, we handle the case of a null
- * 'status' object as well.
- *
- * We call getCurrent() and getLoopStatus() (instead of just using
- * 'item' and 'status') to bridge to subclasses correctly.
- * A subclass can override getCurrent() or getLoopStatus() but still
- * depend on our doStartTag() and doAfterBody(), which call this
- * method (exposeVariables()), to expose 'item' and 'status'
- * correctly.
- */
-
- if (itemId != null) {
- if (getCurrent() == null)
- pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
- else
- pageContext.setAttribute(itemId, getCurrent());
+ if (deferredExpression==null) {
+ /*
+ * We need to support null items returned from next(); we
+ * do this simply by passing such non-items through to the
+ * scoped variable as effectively 'null' (that is, by calling
+ * removeAttribute()).
+ *
+ * Also, just to be defensive, we handle the case of a null
+ * 'status' object as well.
+ *
+ * We call getCurrent() and getLoopStatus() (instead of just using
+ * 'item' and 'status') to bridge to subclasses correctly.
+ * A subclass can override getCurrent() or getLoopStatus() but still
+ * depend on our doStartTag() and doAfterBody(), which call this
+ * method (exposeVariables()), to expose 'item' and 'status'
+ * correctly.
+ */
+ if (itemId != null) {
+ if (getCurrent() == null)
+ pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
+ else
+ pageContext.setAttribute(itemId, getCurrent());
+ }
+ } else { //this is using a DeferredExpression
+ ELContext myELContext = pageContext.getELContext();
+ VariableMapper vm = myELContext.getVariableMapper();
+ vm.setVariable(itemId, (ValueExpression)getCurrent());
}
if (statusId != null) {
if (getLoopStatus() == null)
@@ -538,9 +547,16 @@
* restores them to their prior values (and scopes).
*/
private void unExposeVariables() {
- // "nested" variables are now simply removed
- if (itemId != null)
- pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
+ if (deferredExpression==null) {
+ // "nested" variables are now simply removed
+ if (itemId != null)
+ pageContext.removeAttribute(itemId, PageContext.PAGE_SCOPE);
+ } else {
+ //we're deferred ... remove variable mapping
+ ELContext myELContext = pageContext.getELContext();
+ VariableMapper vm = myELContext.getVariableMapper();
+ vm.setVariable(itemId, null);
+ }
if (statusId != null)
pageContext.removeAttribute(statusId, PageContext.PAGE_SCOPE);
}
@@ -590,4 +606,11 @@
private boolean atEnd() {
return ((end != -1) && (begin + index >= end));
}
+ /**
+ * Get the delimiter for string tokens. Used only for constructing
+ * the deferred expression for it.
+ */
+ protected String getDelims() {
+ return ",";
+ }
}
diff --git a/src/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.java b/src/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.java
index c10919a..de73a56 100644
--- a/src/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.java
+++ b/src/javax/servlet/jsp/jstl/tlv/ScriptFreeTLV.java
@@ -77,7 +77,7 @@
* @param initParms a mapping from the names of the initialization parameters
* to their values, as specified in the TLD.
*/
- public void setInitParameters (Map initParms) {
+ public void setInitParameters (Map<java.lang.String, java.lang.Object> initParms) {
super.setInitParameters(initParms);
String declarationsParm = (String) initParms.get("allowDeclarations");
String scriptletsParm = (String) initParms.get("allowScriptlets");
diff --git a/src/org/apache/taglibs/standard/Version.java b/src/org/apache/taglibs/standard/Version.java
index 9e8da95..f3c4e99 100644
--- a/src/org/apache/taglibs/standard/Version.java
+++ b/src/org/apache/taglibs/standard/Version.java
@@ -90,7 +90,7 @@
*/
public static int getReleaseVersionNum()
{
- return 1;
+ return 2;
}
/**
@@ -104,7 +104,7 @@
*/
public static int getMaintenanceVersionNum()
{
- return 2;
+ return 0;
}
/**
diff --git a/src/org/apache/taglibs/standard/extra/spath/SPathFilter.java b/src/org/apache/taglibs/standard/extra/spath/SPathFilter.java
index 12df102..7f49813 100644
--- a/src/org/apache/taglibs/standard/extra/spath/SPathFilter.java
+++ b/src/org/apache/taglibs/standard/extra/spath/SPathFilter.java
@@ -21,9 +21,9 @@
import java.util.List;
import java.util.Stack;
-import org.apache.xalan.serialize.Serializer;
-import org.apache.xalan.serialize.SerializerFactory;
-import org.apache.xalan.templates.OutputProperties;
+import org.apache.xml.serializer.Serializer;
+import org.apache.xml.serializer.SerializerFactory;
+import org.apache.xml.serializer.OutputPropertiesFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -77,7 +77,7 @@
f1.setParent(r);
f2.setParent(f1);
Serializer sz = SerializerFactory.getSerializer
- (OutputProperties.getDefaultMethodProperties("xml"));
+ (OutputPropertiesFactory.getDefaultMethodProperties("xml"));
sz.setOutputStream(System.out);
f2.setContentHandler(sz.asContentHandler());
diff --git a/src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java b/src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java
index 1b65453..586c640 100644
--- a/src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java
+++ b/src/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java
@@ -24,7 +24,13 @@
import java.util.Map;
import java.util.StringTokenizer;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.jstl.core.IndexedValueExpression;
+import javax.servlet.jsp.jstl.core.IteratedExpression;
+import javax.servlet.jsp.jstl.core.IteratedValueExpression;
import javax.servlet.jsp.jstl.core.LoopTagSupport;
import org.apache.taglibs.standard.resources.Resources;
@@ -109,7 +115,133 @@
return i.next();
}
}
+
+ protected class DeferredForEachIterator implements ForEachIterator {
+ private ValueExpression itemsValueExpression;
+ private IteratedExpression itemsValueIteratedExpression;
+ private int length = -1;
+ private int currentIndex = 0;
+ private boolean isIndexedValueExpression = false;
+ private boolean anIterator = false;
+ private Iterator myIterator;
+ private boolean anEnumeration = false;
+ private Enumeration myEnumeration;
+ public DeferredForEachIterator(ValueExpression o) throws JspTagException {
+ itemsValueExpression = o;
+ determineLengthAndType();
+ }
+ public boolean hasNext() throws JspTagException {
+ if (isIndexedValueExpression) {
+ if (currentIndex<length) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (length!=-1) {
+ //a Collection, Map, or StringTokenizer
+ if (currentIndex<length) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (anIterator) {
+ return myIterator.hasNext();
+ } else if (anEnumeration) {
+ return myEnumeration.hasMoreElements();
+ } else {
+ //don't know what this is
+ return false;
+ }
+ }
+ }
+ }
+ public Object next() throws JspTagException {
+ ValueExpression nextValue = null;
+ if (isIndexedValueExpression) {
+ nextValue = new IndexedValueExpression(itemsValueExpression, currentIndex);
+ currentIndex++;
+ } else {
+ if (itemsValueIteratedExpression==null) {
+ itemsValueIteratedExpression = new IteratedExpression(itemsValueExpression, getDelims());
+ }
+ nextValue = new IteratedValueExpression(itemsValueIteratedExpression, currentIndex);
+ currentIndex++;
+ if (length!=-1) {
+ //a Collection, Map, or StringTokenizer
+ //nothing else needed
+ } else {
+ //need to increment these guys
+ if (anIterator) {
+ myIterator.next();
+ } else if (anEnumeration) {
+ myEnumeration.nextElement();
+ }
+ }
+ }
+ return nextValue;
+ }
+ private void determineLengthAndType() throws JspTagException {
+ ELContext myELContext = pageContext.getELContext();
+ Object o = itemsValueExpression.getValue(myELContext);
+ if (o instanceof Object[]) {
+ length = ((Object[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof boolean[]) {
+ length = ((boolean[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof byte[]) {
+ length = ((byte[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof char[]) {
+ length = ((char[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof short[]) {
+ length = ((short[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof int[]) {
+ length = ((int[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof long[]) {
+ length = ((long[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof float[]) {
+ length = ((float[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof double[]) {
+ length = ((double[])o).length;
+ isIndexedValueExpression = true;
+ } else if (o instanceof Collection) {
+ length = ((Collection)o).size();
+ isIndexedValueExpression = false;
+ } else if (o instanceof Iterator) {
+ //have to reproduce iterator here so we can determine the size
+ isIndexedValueExpression = false;
+ anIterator = true;
+ myIterator = (Iterator)o;
+ } else if (o instanceof Enumeration) {
+ isIndexedValueExpression = false;
+ anEnumeration=true;
+ myEnumeration = (Enumeration)o;
+ } else if (o instanceof Map) {
+ length = ((Map)o).size();
+ isIndexedValueExpression = false;
+ //
+ //else if (o instanceof ResultSet)
+ // items = toForEachIterator((ResultSet) o);
+ //
+ } else if (o instanceof String) {
+ StringTokenizer st = new StringTokenizer((String)o, ",");
+ length = st.countTokens();
+ isIndexedValueExpression = false;
+ } else {
+ //What does this mean if we get here???
+ length=0;
+ }
+ }
+ }
//*********************************************************************
// ForEach-specifc state (protected)
@@ -134,8 +266,17 @@
protected void prepare() throws JspTagException {
// produce the right sort of ForEachIterator
if (rawItems != null) {
- // extract an iterator over the 'items' we've got
- items = supportedTypeForEachIterator(rawItems);
+ if (rawItems instanceof ValueExpression) {
+ deferredExpression = (ValueExpression)rawItems;
+ ELContext myELContext = pageContext.getELContext();
+ VariableMapper vm = myELContext.getVariableMapper();
+ //String itemsName=deferredExpression.getExpressionString();
+ //vm.setVariable(itemsName, deferredExpression);
+ items = toDeferredForEachIterator(deferredExpression);
+ } else {
+ // extract an iterator over the 'items' we've got
+ items = supportedTypeForEachIterator(rawItems);
+ }
} else {
// no 'items', so use 'begin' and 'end'
items = beginEndForEachIterator();
@@ -165,6 +306,7 @@
// Private generation methods for the ForEachIterators we produce
/* Extracts a ForEachIterator given an object of a supported type. */
+ //This should not be called for a deferred ValueExpression
protected ForEachIterator supportedTypeForEachIterator(Object o)
throws JspTagException {
@@ -250,6 +392,10 @@
//*********************************************************************
// Private conversion methods to handle the various types we support
+ protected ForEachIterator toDeferredForEachIterator(ValueExpression o) throws JspTagException {
+ return new DeferredForEachIterator(o);
+ }
+
// catch-all method whose invocation currently signals a 'matching error'
protected ForEachIterator toForEachIterator(Object o)
throws JspTagException {
diff --git a/src/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java b/src/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java
index 608ea26..0c876d5 100644
--- a/src/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java
+++ b/src/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java
@@ -19,7 +19,12 @@
import java.util.StringTokenizer;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.jstl.core.IteratedExpression;
+import javax.servlet.jsp.jstl.core.IteratedValueExpression;
import javax.servlet.jsp.jstl.core.LoopTagSupport;
/**
@@ -50,9 +55,11 @@
//*********************************************************************
// ForEachTokens-specific state (protected)
- protected String items; // 'items' attribute
+ protected Object items; // 'items' attribute
protected String delims; // 'delims' attribute
protected StringTokenizer st; // digested tokenizer
+ protected int currentIndex = 0;
+ private IteratedExpression itemsValueIteratedExpression;
//*********************************************************************
@@ -64,7 +71,18 @@
*/
protected void prepare() throws JspTagException {
- st = new StringTokenizer(items, delims);
+ if (items instanceof ValueExpression) {
+ deferredExpression = (ValueExpression) items;
+ ELContext myELContext = pageContext.getELContext();
+ Object originalValue = deferredExpression.getValue(myELContext);
+ if (originalValue instanceof String) {
+ st = new StringTokenizer((String)originalValue, delims);
+ } else {
+ throw new JspTagException();
+ }
+ } else {
+ st = new StringTokenizer((String)items, delims);
+ }
}
protected boolean hasNext() throws JspTagException {
@@ -72,7 +90,17 @@
}
protected Object next() throws JspTagException {
- return st.nextElement();
+ if (deferredExpression!=null) {
+ st.nextElement();
+ if (itemsValueIteratedExpression==null) {
+ itemsValueIteratedExpression = new IteratedExpression(deferredExpression, getDelims());
+ }
+ ValueExpression nextValue = new IteratedValueExpression(itemsValueIteratedExpression, currentIndex);
+ currentIndex++;
+ return nextValue;
+ } else {
+ return st.nextElement();
+ }
}
@@ -87,4 +115,11 @@
st = null;
}
+ /**
+ * Get the delimiter for string tokens. Used only for constructing
+ * the deferred expression for it.
+ */
+ protected String getDelims() {
+ return delims;
+ }
}
diff --git a/src/org/apache/taglibs/standard/tag/common/core/SetSupport.java b/src/org/apache/taglibs/standard/tag/common/core/SetSupport.java
index 878bb05..90e22a9 100644
--- a/src/org/apache/taglibs/standard/tag/common/core/SetSupport.java
+++ b/src/org/apache/taglibs/standard/tag/common/core/SetSupport.java
@@ -27,12 +27,15 @@
import java.util.Map;
import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspFactory;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
-import javax.servlet.jsp.el.ELException;
-import javax.servlet.jsp.el.ExpressionEvaluator;
-import javax.servlet.jsp.el.VariableResolver;
+import javax.el.ELException;
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.el.VariableMapper;
+import javax.el.ExpressionFactory;
import javax.servlet.jsp.tagext.BodyTagSupport;
@@ -114,9 +117,30 @@
* is made to store something in the session without any
* HttpSession existing).
*/
+ ELContext myELContext = pageContext.getELContext();
+ VariableMapper vm = myELContext.getVariableMapper();
if (result != null) {
- pageContext.setAttribute(var, result, scope);
+ //check for instanceof valueExpression
+ if (result instanceof ValueExpression) {
+ if (scope!=PageContext.PAGE_SCOPE) {
+ throw new JspException("Incorrect scope for ValueExpression. PageScope is required.");
+ }
+ //set variable in var Mapper
+ vm.setVariable(var, (ValueExpression)result);
+ } else {
+ /*
+ //else if not valueExpression - make sure to remove it from the Var mapper
+ //if the scope is page, should I remove this?
+ if (vm.resolveVariable(var)!=null) {
+ vm.setVariable(var, null);
+ }*/
+ pageContext.setAttribute(var, result, scope);
+ }
} else {
+ //make sure to remove it from the Var mapper
+ if (vm.resolveVariable(var)!=null) {
+ vm.setVariable(var, null);
+ }
if (scopeSpecified)
pageContext.removeAttribute(var, scope);
else
@@ -179,15 +203,9 @@
* rules of the Expression Language.
*/
private Object convertToExpectedType(final Object value, Class expectedType) throws ELException {
- ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
- return evaluator.evaluate( "${result}",
- expectedType,
- new VariableResolver() {
- public Object resolveVariable(String pName) throws ELException {
- return value;
- }
- },
- null);
+ JspFactory jspFactory = JspFactory.getDefaultFactory();
+ ExpressionFactory expressionFactory = jspFactory.getJspApplicationContext(pageContext.getServletContext()).getExpressionFactory();
+ return expressionFactory.coerceToType(value, expectedType);
}
//*********************************************************************
diff --git a/src/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java b/src/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java
index 257240c..ccd78b3 100644
--- a/src/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java
+++ b/src/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java
@@ -201,8 +201,8 @@
if (locCtxt == null) {
// try using the root resource bundle with the given basename
try {
- bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE,
- Thread.currentThread().getContextClassLoader());
+ ClassLoader cl = getClassLoaderCheckingPrivilege();
+ bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE, cl);
if (bundle != null) {
locCtxt = new LocalizationContext(bundle, null);
}
@@ -279,9 +279,8 @@
ResourceBundle match = null;
try {
- ResourceBundle bundle =
- ResourceBundle.getBundle(basename, pref,
- Thread.currentThread().getContextClassLoader());
+ ClassLoader cl = getClassLoaderCheckingPrivilege();
+ ResourceBundle bundle = ResourceBundle.getBundle(basename, pref, cl);
Locale avail = bundle.getLocale();
if (pref.equals(avail)) {
// Exact match
@@ -326,4 +325,17 @@
return match;
}
+
+ private static ClassLoader getClassLoaderCheckingPrivilege() {
+ ClassLoader cl;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ cl = Thread.currentThread().getContextClassLoader();
+ } else {
+ cl = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<ClassLoader>()
+ {public ClassLoader run() {return Thread.currentThread().getContextClassLoader();}});
+ }
+ return cl;
+ }
}
diff --git a/src/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java b/src/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java
index 9bf632d..626d0fb 100644
--- a/src/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java
+++ b/src/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java
@@ -40,12 +40,24 @@
private String password;
public void setDriverClassName(String driverClassName)
- throws ClassNotFoundException, InstantiationException,
- IllegalAccessException {
+ throws ClassNotFoundException, InstantiationException,
+ IllegalAccessException {
- this.driverClassName = driverClassName;
- Class.forName(driverClassName, true,
- Thread.currentThread().getContextClassLoader()).newInstance();
+ this.driverClassName = driverClassName;
+
+ //get the classloader
+ ClassLoader cl;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null) {
+ cl = Thread.currentThread().getContextClassLoader();
+ } else {
+ cl = java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<ClassLoader>()
+ {public ClassLoader run() {return Thread.currentThread().getContextClassLoader();}});
+ }
+ //done getting classloader
+
+ Class.forName(driverClassName, true, cl).newInstance();
}
public void setJdbcURL(String jdbcURL) {
@@ -111,6 +123,13 @@
public synchronized void setLogWriter(PrintWriter out) throws SQLException {
throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
}
+
+ public synchronized boolean isWrapperFor(Class c) throws SQLException {
+ throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
+ }
+ public synchronized Object unwrap(Class c) throws SQLException {
+ throw new SQLException(Resources.getMessage("NOT_SUPPORTED"));
+ }
}
diff --git a/src/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java b/src/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java
index a0c26da..0d207d2 100644
--- a/src/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java
+++ b/src/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java
@@ -59,8 +59,8 @@
validateStep();
}
- // stores the 'items' String we're passed
- public void setItems(String s) throws JspTagException {
+ // stores the 'items' Object we're passed
+ public void setItems(Object s) throws JspTagException {
items = s;
// use the empty string to indicate "no iteration"
if (s == null)
diff --git a/test/org/apache/taglibs/standard/TestVersion.java b/test/org/apache/taglibs/standard/TestVersion.java
index 7dc05de..460beb6 100644
--- a/test/org/apache/taglibs/standard/TestVersion.java
+++ b/test/org/apache/taglibs/standard/TestVersion.java
@@ -48,7 +48,7 @@
}
public void testGetMaintenanceVersionNum() {
- int expectedReturn = 2;
+ int expectedReturn = 0;
int actualReturn = version.getMaintenanceVersionNum();
assertEquals("return value", expectedReturn, actualReturn);
}
@@ -66,13 +66,13 @@
}
public void testGetReleaseVersionNum() {
- int expectedReturn = 1;
+ int expectedReturn = 2;
int actualReturn = version.getReleaseVersionNum();
assertEquals("return value", expectedReturn, actualReturn);
}
public void testGetVersion() {
- String expectedReturn = "standard-taglib 1.1.2";
+ String expectedReturn = "standard-taglib 1.2.0";
String actualReturn = version.getVersion();
assertEquals("return value", expectedReturn, actualReturn);
}
diff --git a/test/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java b/test/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java
index e188c5f..d5f4cc4 100644
--- a/test/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java
+++ b/test/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java
@@ -32,6 +32,7 @@
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.el.ExpressionEvaluator;
import javax.servlet.jsp.el.VariableResolver;
+import javax.el.ELContext;
/**
*
@@ -299,4 +300,5 @@
public ExpressionEvaluator getExpressionEvaluator() { return null; }
public VariableResolver getVariableResolver() { return null; }
+ public ELContext getELContext() { return null; }
}