diff --git a/Java-base/tomcat-taglibs-standard/Dockerfile b/Java-base/tomcat-taglibs-standard/Dockerfile new file mode 100644 index 000000000..e208c4890 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/Dockerfile @@ -0,0 +1,28 @@ +FROM ubuntu:22.04 + +RUN export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y software-properties-common \ + && add-apt-repository ppa:deadsnakes/ppa \ + && apt-get update \ + && apt-get install -y \ + build-essential \ + git \ + vim \ + jq \ + && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/list/* + +RUN apt-get -y install sudo \ + openjdk-8-jdk \ + maven + +RUN bash -c "echo 2 | update-alternatives --config java" + +COPY src /workspace +WORKDIR /workspace + +RUN mvn install -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false + +RUN mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 + +ENV TZ=Asia/Seoul diff --git a/Java-base/tomcat-taglibs-standard/src/CHANGES.txt b/Java-base/tomcat-taglibs-standard/src/CHANGES.txt new file mode 100644 index 000000000..abcbf0f50 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/CHANGES.txt @@ -0,0 +1,93 @@ +Changes in 1.2.6 release +60950 JSTL TransformSupport XSL import not finding relative path +57434 Race condition in EL1.0 validation + +Changes in 1.2.5 release +- Set version identifiers correctly, no other changes. + +Changes in 1.2.4 release (not released due to incorrect version numbers) + +57673 AccessControlException accessing org.apache.taglibs.standard.xml.accessExternalEntity +37466 Reverted changes that overrode HTTP method when importing local resources. + +Changes in 1.2.3 release + +57560 Check protocol when resolving on older JREs +57549 Fix reference to old SNAPSHOT version of taglibs-build-tools in pom files. +57548 Update library version number printed by Version class +57547 Fix regression with running on older JREs + +XML tags now enable FEATURE_SECURE_PROCESSING when parsing and transforming. The JSTL-specific +EntityResolver also checks the protocol being used against a white-list specified in the system +property org.apache.taglibs.standard.xml.accessExternalEntity in to order to limit access on +older JREs. + +Changes in 1.2.2 release [WITHDRAWN due to regressions in older JREs] + +57433 Double-check locking in ExpressionEvaluatorManager +57427 1.0 TLDs are missing from -compat jar +57289 XML factories should be located using the JSTL library's ClassLoader + +Changes in 1.2.1 release +- Documentation cleanup + +Major changes in 1.2.0 release +- Transitioned project from Apache Jakarta to Apache Tomcat +- Implementation of new functionality for JSTL 1.2; requires Java 1.5 +- Switched to Maven-based build +- Renamed JARs and modified packaging structure; OSGI metadata added +- XML processing performance improved by direct use of Xalan + +The following issues from Bugzilla (https://issues.apache.org/bugzilla) appear related. +However, due to the time since the last 1.1 release some issues may be missing or misclassified. + +55608 fmt:bundle tag unnecessarily buffers body content +54544 Loop vars are not reset for fortoken with deferred expression +52637 Broken link +50674 Some maven pom improvments +50462 xalan import should not be optional in maven-bundle-plugin +50461 out tag's escapeXml attribute should be set as true by default +50414 tlv package cause another split package issue in impl and jstlel bundles +50266 Javadoc and import corrections +50265 FormatDateSupport.dateFormatCache lazy init is not safe +50264 Missing @Override annotations +50263 README_src.txt out of date +50250 Split package issue in impl and jstlel bundles +50064 bundle-ify the taglibs jars +49900 BundleSupport.release() does not call super.release() to clear bodyContent +49578 XPath handling only supports single reference to variable +49565 Findbugs: Util.specialCharactersRepresentation should be both final and package protected +49561 Remove proprietary URLEncoder +49554 Clean up Functions +49548 Refactoring SetSupport +49547 Minor performance enhancement in set result evaluation +49546 Add test cases for SetSupport +49542 IteratedValueExpression and IndexedValueExpression implementation +49534 ForEachSupport handles unsupported items inconsistently +49526 c:set does not remove variables from ELContext VariableMapper +49510 Remove dependency on classes copied from commons +48848 fn:endsWith fails with repeated search string +48773 DataSourceWrapper and DriverManager problems +48772 Bad information in impl module pom.xml +46086 javax.servlet.jsp.jstl.sql.ResultSupport.java silently swallows SQLException +45197 Need to support the JSTL 1.2 specification +45183 Starting from mysql JDBC connector 5.1.6 a wrong behavior +43831 Unexpected Result with mysql jdbc 5.1.5, column aliases not reported +43640 Move the tests package to JUnit +43544 LRUCache implementation not updated to match latest collections code +43393 x:out provokes an IllegalStateException if session is forbidden +41343 Build fails on OS X. +41221 Fix source headers in source +39480 calling getContextClassLoader without doPriv +39195 getRequestLocale could throw exception on JBOSS +39284 fn:endsWith('abcda', 'a') returns false +37466 c:import doesn't work with HEAD requests +37029 TLD Validation error for HTML "param" element +35216 x:forEach causes session scope exception +34109 doesn't merge slashes at the boundary of "context" and "value" +33934 [standard] memory leak in jstl c:set tag +32896 Invalid endsWith function +30068 Wrong behaviour of x:out inside x:forEach +27717 very slow in JSTL 1.1 +17388 Result set created in query tag is never released + update tag +14465 position() and last() are critical diff --git a/Java-base/tomcat-taglibs-standard/src/Jenkinsfile b/Java-base/tomcat-taglibs-standard/src/Jenkinsfile new file mode 100644 index 000000000..dc0a88303 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/Jenkinsfile @@ -0,0 +1,64 @@ +#!groovy + +pipeline { + agent any + options { + durabilityHint('PERFORMANCE_OPTIMIZED') + buildDiscarder(logRotator(numToKeepStr: '7', artifactNumToKeepStr: '2')) + timeout(time: 60, unit: 'MINUTES') + } + stages { + stage( "Parallel Stage" ) { + parallel { + stage( "Build / Test - JDK8" ) { + agent { node { label 'ubuntu' } } + options { timeout( time: 120, unit: 'MINUTES' ) } + steps { + mavenBuild( "JDK 1.8 (latest)", "clean install" ) + script { + if (env.BRANCH_NAME == 'master') { + mavenBuild( "JDK 1.8 (latest)", "deploy" ) + } + } + } + } + stage( "Build / Test - JDK11" ) { + agent { node { label 'ubuntu' } } + options { timeout( time: 120, unit: 'MINUTES' ) } + steps { + mavenBuild( "JDK 11 (latest)", "clean install" ) + } + } + } + } + } +} + + + +/** + * To other developers, if you are using this method above, please use the following syntax. + * + * mavenBuild("", " " + * + * @param jdk the jdk tool name (in jenkins) to use for this build + * @param cmdline the command line in " "`format. + * @return the Jenkinsfile step representing a maven build + */ +def mavenBuild(jdk, cmdline) { + def mvnName = 'Maven 3.6.3' + //def localRepo = "${env.JENKINS_HOME}/${env.EXECUTOR_NUMBER}" // ".repository" // + //def settingsName = 'oss-settings.xml' + def mavenOpts = '-Xms2g -Xmx2g -Djava.awt.headless=true' + + withMaven( + maven: mvnName, + jdk: "$jdk", + publisherStrategy: 'EXPLICIT', + //globalMavenSettingsConfig: settingsName, + options: [junitPublisher(disabled: false)], + mavenOpts: mavenOpts) { + // Some common Maven command line + provided command line + sh "mvn -V -B -DfailIfNoTests=false -Dmaven.test.failure.ignore=true $cmdline" + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/LICENSE b/Java-base/tomcat-taglibs-standard/src/LICENSE new file mode 100644 index 000000000..f49a4e16e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. \ No newline at end of file diff --git a/Java-base/tomcat-taglibs-standard/src/NOTICE b/Java-base/tomcat-taglibs-standard/src/NOTICE new file mode 100644 index 000000000..1d484e76a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/NOTICE @@ -0,0 +1,5 @@ +Apache Standard Taglib +Copyright 2001-2020 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/Java-base/tomcat-taglibs-standard/src/README_bin.txt b/Java-base/tomcat-taglibs-standard/src/README_bin.txt new file mode 100644 index 000000000..245f06447 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/README_bin.txt @@ -0,0 +1,116 @@ +--------------------------------------------------------------------------- +Apache Standard Tag Library 1.2.6 -- BINARY DISTRIBUTION +--------------------------------------------------------------------------- +Thanks for downloading this release of the Standard tag library, +an implementation of the JavaServer Pages(tm)(JSP) +Standard Tag Library (JSTL). + +This code is licensed to you by the Apache Software Foundation and its +contributors under the terms of the Apache License V2.0; +please see the included NOTICE and LICENSE files for details. + +JSTL is an effort of the Java Community Process (JCP) and +comes out of the JSR-052 expert group. For more information on JSTL, +please go to http://jcp.org/en/jsr/detail?id=52 . + +--------------------------------------------------------------------------- +LIBRARY DEPENDENCIES + +This version of the Standard Tag Library has the following runtime +dependencies: + + 1. Dependencies provided by a JSP 2.1 container: + - Java 1.5 or later + - Servlet 2.5 or later + - JSP 2.1 or later + + 2. Additional dependencies + - The XML tag library requires Apache Xalan 2.7.1 or later + +--- +Apache Xalan 2.7.1 + +To address performance issues with XSLT processing, this version relies on +implementation specific functionality from Apache Xalan. The following +libraries should be included in the classpath for your application: + - xalan-2.7.1.jar + - serializer-2.7.1.jar + +--------------------------------------------------------------------------- +ADD DEPENDENCIES TO A WEB APPLICATION + +To use this distribution with your own web applications, add the following JAR +files to the '/WEB-INF/lib' directory of your application: + - taglibs-standard-spec-1.2.5.jar + - taglibs-standard-impl-1.2.5.jar + - taglibs-standard-jstlel-1.2.5.jar + - xalan-2.7.1.jar + - serializer-2.7.1.jar + +If you do not use JSTL 1.0 tags then the "taglibs-standard-jstlel" JAR may be +omitted. If you do not use the XML library, then the Apache Xalan dependencies +may also be omitted. + +If you build you application with Maven, add the following dependencies to +your pom.xml file: + + + org.apache.taglibs + taglibs-standard-spec + 1.2.5 + + + org.apache.taglibs + taglibs-standard-impl + 1.2.5 + + +--------------------------------------------------------------------------- +USING JSTL TAGS FROM A JSP + +The JSTL tag library can be imported into your pages with the following directives: + + CORE LIBRARY + <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + XML LIBRARY + <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + FMT LIBRARY + <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + SQL LIBRARY + <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> + + FUNCTIONS LIBRARY + <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + +--------------------------------------------------------------------------- +COMPATIBILITY + +The 1.2 version of the Standard Taglib has been tested using Tomcat 7.0.57 +and should work in any compliant JSP 2.1 (or later) container. + +In version 1.2.3 and later, the XML libraries enable FEATURE_SECURE_PROCESSING +when parsing and transforming. The system property + + org.apache.taglibs.standard.xml.accessExternalEntity + +can be used to further restrict the protocols over which external entities can +be resolved. When a SecurityManager is enabled this will, by default, allow +access to no protocols. Permission must be granted to the taglibs-standard-impl +library to read this property. + + permission java.util.PropertyPermission "org.apache.taglibs.standard.xml.accessExternalEntity", "read"; + +--------------------------------------------------------------------------- +COMMENTS AND QUESTIONS + +Please join the taglibs-user@tomcat.apache.org mailing list if you have +general usage questions about Apache Taglibs. + +Comments about the JSTL specification itself should be sent to +jsr-52-comments@jcp.org. + +Enjoy! + diff --git a/Java-base/tomcat-taglibs-standard/src/README_src.txt b/Java-base/tomcat-taglibs-standard/src/README_src.txt new file mode 100644 index 000000000..a83738f78 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/README_src.txt @@ -0,0 +1,59 @@ +--------------------------------------------------------------------------- +Apache Standard Tag Library 1.2.6 -- SOURCE DISTRIBUTION +--------------------------------------------------------------------------- +Thanks for downloading the source code for the Apache Software Foundation's +implementation of the JavaServer Pages(tm)(JSP) Standard Tag Library (JSTL) +specification. This code is licensed to you by the Apache Software +Foundation and its contributors under the terms of the Apache License V2.0; +please see the included NOTICE and LICENSE files for details. + +--------------------------------------------------------------------------- +BUILD ENVIRONMENT SETUP + +For the 1.2 release, the project migrated to the Apache Maven build system. +Download and install version 3.0 or higher from http://maven.apache.org + +The build requires a Java Development Kit Version 5 or higher. + +--------------------------------------------------------------------------- +BUILDING + +From the 'standard' directory, the entire project can be built with the +normal Maven goals: + + $ mvn install <-- builds all targets and installs in local repository + $ mvn clean <-- removes all build artifacts + +A typical build will use the 'install' goal that compiles all classes, runs +all the unit tests, creates the target bundles, and installs them in the +local Maven repository. + +All library dependencies will be downloaded from the central Maven +repositories. You should be online when building. + +Information about the project can be found in the 'pom.xml' project +descriptor. + +For information about performing a release at Apache, please refer to +"Publishing Maven Artifacts" at http://www.apache.org/dev/publishing-maven-artifacts.html +To rebuild the released artifacts locally from this source distribution +or from a SVN tag, run: + $ mvn -Papache-release install + +--------------------------------------------------------------------------- +PROJECT MODULES + +There are three primary sub-modules: + + spec <-- contains Apache's implementation of the API classes + impl <-- contains the implementation of tags from the 1.1 + namespace http://java.sun.com/jsp/jstl/* + jstlel <-- contains the implementation of tags from the 1.0 + namespace http://java.sun.com/jstl/* and uses the + original JSTL 1.0 version of EL + +In addition, the following modules provide supporting functionality + build-tools <-- build support such as checkstyle rules + compat <-- contains the implementation of tags from the 1.0 + namespace but uses the JSP container's implementation + of EL (which will be 2.1 or later). diff --git a/Java-base/tomcat-taglibs-standard/src/RELEASING.txt b/Java-base/tomcat-taglibs-standard/src/RELEASING.txt new file mode 100644 index 000000000..d1ac24b28 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/RELEASING.txt @@ -0,0 +1,42 @@ +The project is configured to be released using the Maven Release Plugin. + +Some manual steps are required before performing a release build. + +* Update the version strings in README_bin.txt and README_src.tst +* Update the version number in the Version class +* Update the version number in the VersionTest class +Commit these changes. + +Push the Maven Artifacts to the Apache Staging Repository: +$ mvn release:prepare -Papache-release -DautoVersionSubmodules=true +$ mvn release:perform + +Don't forget to close the staging repository prior to the vote. + +Stage the Apache download repository at + https://dist.apache.org/repos/dist/dev/tomcat/taglibs +with the following files: +NOTICE +README_bin.txt +README_src.txt +taglibs-standard-1.2.x-source-release.zip +taglibs-standard-1.2.x-source-release.zip.asc +taglibs-standard-1.2.x-source-release.zip.md5 +taglibs-standard-1.2.x-source-release.zip.sha1 +taglibs-standard-compat-1.2.x.jar +taglibs-standard-compat-1.2.x.jar.asc +taglibs-standard-compat-1.2.x.jar.md5 +taglibs-standard-compat-1.2.x.jar.sha1 +taglibs-standard-impl-1.2.x.jar +taglibs-standard-impl-1.2.x.jar.asc +taglibs-standard-impl-1.2.x.jar.md5 +taglibs-standard-impl-1.2.x.jar.sha1 +taglibs-standard-jstlel-1.2.x.jar +taglibs-standard-jstlel-1.2.x.jar.asc +taglibs-standard-jstlel-1.2.x.jar.md5 +taglibs-standard-jstlel-1.2.x.jar.sha1 +taglibs-standard-spec-1.2.x.jar +taglibs-standard-spec-1.2.x.jar.asc +taglibs-standard-spec-1.2.x.jar.md5 +taglibs-standard-spec-1.2.x.jar.sha1 + diff --git a/Java-base/tomcat-taglibs-standard/src/build-tools/pom.xml b/Java-base/tomcat-taglibs-standard/src/build-tools/pom.xml new file mode 100644 index 000000000..95d94f9f4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/build-tools/pom.xml @@ -0,0 +1,33 @@ + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-build-tools + 2.0.0-SNAPSHOT + Apache Standard Taglib Build Tools + + Build tool settings common to all Standard Taglib modules + + diff --git a/Java-base/tomcat-taglibs-standard/src/build-tools/src/main/resources/taglibs/checkstyle.xml b/Java-base/tomcat-taglibs-standard/src/build-tools/src/main/resources/taglibs/checkstyle.xml new file mode 100644 index 000000000..52c572768 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/build-tools/src/main/resources/taglibs/checkstyle.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/compat/pom.xml b/Java-base/tomcat-taglibs-standard/src/compat/pom.xml new file mode 100644 index 000000000..377492205 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/pom.xml @@ -0,0 +1,149 @@ + + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-standard-compat + 2.0.0-SNAPSHOT + bundle + + Apache Standard Taglib 1.0 Compatibility + + + Supports JSTL 1.0 tags using the Servlet container's EL implementation. + + + + + org.apache.taglibs + taglibs-standard-spec + + + org.apache.taglibs + taglibs-standard-impl + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + provided + + + xalan + xalan + provided + true + + + + junit + junit + test + + + org.easymock + easymock + test + + + + + + + org.apache.felix + maven-bundle-plugin + + true + + *;version="1.2" + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../build-tools/src/main/resources/taglibs/checkstyle.xml + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + ${maven.compiler.target} + + + + + pmd + cpd + + + + + + org.codehaus.mojo + taglist-maven-plugin + 2.4 + + + org.codehaus.mojo + javancss-maven-plugin + 2.0 + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + Normal + Default + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForEachTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForEachTag.java new file mode 100644 index 000000000..07dc8f204 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForEachTag.java @@ -0,0 +1,90 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import java.util.Collections; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ForEachSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * JSTL 1.0 compatible implementation of <foreach> that uses JSP EL support. + */ +public class ForEachTag extends ForEachSupport { + + private ValueExpression beginExpression; + private ValueExpression endExpression; + private ValueExpression stepExpression; + private ValueExpression itemsExpression; + + public ForEachTag() { + } + + @Override + public void release() { + beginExpression = null; + endExpression = null; + stepExpression = null; + itemsExpression = null; + super.release(); + } + + @Override + public int doStartTag() throws JspException { + if (beginSpecified) { + begin = (Integer) beginExpression.getValue(pageContext.getELContext()); + validateBegin(); + } + if (endSpecified) { + end = (Integer) endExpression.getValue(pageContext.getELContext()); + validateEnd(); + } + if (stepSpecified) { + step = (Integer) stepExpression.getValue(pageContext.getELContext()); + validateStep(); + } + if (itemsExpression != null) { + rawItems = itemsExpression.getValue(pageContext.getELContext()); + if (rawItems == null) { + rawItems = Collections.emptyList(); + } + } + return super.doStartTag(); + } + + public void setBegin(String begin) { + beginExpression = ExpressionUtil.createValueExpression(pageContext, begin, Integer.TYPE); + beginSpecified = true; + } + + public void setEnd(String end) { + endExpression = ExpressionUtil.createValueExpression(pageContext, end, Integer.TYPE); + endSpecified = true; + } + + public void setStep(String step) { + stepExpression = ExpressionUtil.createValueExpression(pageContext, step, Integer.TYPE); + stepSpecified = true; + } + + public void setItems(String items) { + itemsExpression = ExpressionUtil.createValueExpression(pageContext, items, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForTokensTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForTokensTag.java new file mode 100644 index 000000000..e2bebcadb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ForTokensTag.java @@ -0,0 +1,100 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ForTokensSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * JSTL 1.0 compatible implementation of <fortokens> that uses JSP EL support. + */ +public class ForTokensTag extends ForTokensSupport { + + private ValueExpression beginExpression; + private ValueExpression endExpression; + private ValueExpression stepExpression; + private ValueExpression itemsExpression; + private ValueExpression delimsExpression; + + public ForTokensTag() { + } + + @Override + public void release() { + beginExpression = null; + endExpression = null; + stepExpression = null; + itemsExpression = null; + delimsExpression = null; + super.release(); + } + + @Override + public int doStartTag() throws JspException { + if (beginSpecified) { + begin = (Integer) beginExpression.getValue(pageContext.getELContext()); + validateBegin(); + } + if (endSpecified) { + end = (Integer) endExpression.getValue(pageContext.getELContext()); + validateEnd(); + } + if (stepSpecified) { + step = (Integer) stepExpression.getValue(pageContext.getELContext()); + validateStep(); + } + if (itemsExpression != null) { + items = itemsExpression.getValue(pageContext.getELContext()); + if (items == null) { + items = ""; + } + } + if (delimsExpression != null) { + delims = (String) delimsExpression.getValue(pageContext.getELContext()); + if (delims == null) { + delims = ""; + } + } + return super.doStartTag(); + } + + public void setBegin(String begin) { + beginExpression = ExpressionUtil.createValueExpression(pageContext, begin, Integer.TYPE); + beginSpecified = true; + } + + public void setEnd(String end) { + endExpression = ExpressionUtil.createValueExpression(pageContext, end, Integer.TYPE); + endSpecified = true; + } + + public void setStep(String step) { + stepExpression = ExpressionUtil.createValueExpression(pageContext, step, Integer.TYPE); + stepSpecified = true; + } + + public void setItems(String items) { + itemsExpression = ExpressionUtil.createValueExpression(pageContext, items, Object.class); + } + + public void setDelims(String delims) { + delimsExpression = ExpressionUtil.createValueExpression(pageContext, delims, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/IfTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/IfTag.java new file mode 100644 index 000000000..d2ff736da --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/IfTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; + +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * JSTL 1.0 compatible implementation of <if> that uses JSP EL support. + */ +public class IfTag extends ConditionalTagSupport { + private ValueExpression testExpression; + + public IfTag() { + } + + @Override + public void release() { + testExpression = null; + super.release(); + } + + @Override + protected boolean condition() throws JspTagException { + return (Boolean) testExpression.getValue(pageContext.getELContext()); + } + + public void setTest(String test) { + testExpression = ExpressionUtil.createValueExpression(pageContext, test, Boolean.TYPE); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ImportTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ImportTag.java new file mode 100644 index 000000000..285c61909 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ImportTag.java @@ -0,0 +1,67 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ImportSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class ImportTag extends ImportSupport { + + private ValueExpression urlExpression; + private ValueExpression contextExpression; + private ValueExpression charEncodingExpression; + + public ImportTag() { + } + + @Override + public void release() { + urlExpression = null; + contextExpression = null; + charEncodingExpression = null; + super.release(); + } + + @Override + public int doStartTag() throws JspException { + url = (String) urlExpression.getValue(pageContext.getELContext()); + if (contextExpression != null) { + context = (String) contextExpression.getValue(pageContext.getELContext()); + } + if (charEncodingExpression != null) { + charEncoding = (String) charEncodingExpression.getValue(pageContext.getELContext()); + } + return super.doStartTag(); + } + + public void setUrl(String url) { + urlExpression = ExpressionUtil.createValueExpression(pageContext, url, String.class); + } + + public void setContext(String context) { + contextExpression = ExpressionUtil.createValueExpression(pageContext, context, String.class); + } + + public void setCharEncoding(String charEncoding) { + charEncodingExpression = ExpressionUtil.createValueExpression(pageContext, charEncoding, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/OutTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/OutTag.java new file mode 100644 index 000000000..ad9149d64 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/OutTag.java @@ -0,0 +1,79 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.OutSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class OutTag extends OutSupport { + + private ValueExpression valueExpression; + private ValueExpression defaultExpression; + private ValueExpression escapeXmlExpression; + + public OutTag() { + } + + @Override + public void release() { + valueExpression = null; + defaultExpression = null; + escapeXmlExpression = null; + super.release(); + } + + public void setValue(String value) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, value, Object.class); + } + + public void setDefault(String def) { + defaultExpression = ExpressionUtil.createValueExpression(pageContext, def, String.class); + } + + public void setEscapeXml(String escapeXml) { + escapeXmlExpression = ExpressionUtil.createValueExpression(pageContext, escapeXml, Boolean.TYPE); + } + + @Override + protected Object evalValue() throws JspException { + if (valueExpression == null) { + return null; + } + return valueExpression.getValue(pageContext.getELContext()); + } + + @Override + protected String evalDefault() throws JspException { + if (defaultExpression == null) { + return null; + } + return (String) defaultExpression.getValue(pageContext.getELContext()); + } + + @Override + protected boolean evalEscapeXml() throws JspException { + if (escapeXmlExpression == null) { + return true; + } + return (Boolean) escapeXmlExpression.getValue(pageContext.getELContext()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ParamTag.java new file mode 100644 index 000000000..c5d7de6fc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/ParamTag.java @@ -0,0 +1,56 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ParamSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class ParamTag extends ParamSupport { + + private ValueExpression nameExpression; + private ValueExpression valueExpression; + + public ParamTag() { + } + + @Override + public int doStartTag() throws JspException { + name = (String) nameExpression.getValue(pageContext.getELContext()); + value = (String) valueExpression.getValue(pageContext.getELContext()); + return super.doStartTag(); + } + + @Override + public void release() { + nameExpression = null; + valueExpression = null; + super.release(); + } + + public void setName(String name) { + nameExpression = ExpressionUtil.createValueExpression(pageContext, name, String.class); + } + + public void setValue(String value) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, value, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/RedirectTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/RedirectTag.java new file mode 100644 index 000000000..708ab66be --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/RedirectTag.java @@ -0,0 +1,58 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.RedirectSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class RedirectTag extends RedirectSupport { + + private ValueExpression urlExpression; + private ValueExpression contextExpression; + + public RedirectTag() { + } + + @Override + public void release() { + urlExpression = null; + contextExpression = null; + super.release(); + } + + @Override + public int doStartTag() throws JspException { + url = (String) urlExpression.getValue(pageContext.getELContext()); + if (contextExpression != null) { + context = (String) contextExpression.getValue(pageContext.getELContext()); + } + return super.doStartTag(); + } + + public void setUrl(String url) { + urlExpression = ExpressionUtil.createValueExpression(pageContext, url, String.class); + } + + public void setContext(String context) { + contextExpression = ExpressionUtil.createValueExpression(pageContext, context, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/SetTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/SetTag.java new file mode 100644 index 000000000..f65a12a39 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/SetTag.java @@ -0,0 +1,75 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.SetSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class SetTag extends SetSupport { + + private ValueExpression valueExpression; + private ValueExpression targetExpression; + private ValueExpression propertyExpression; + + public SetTag() { + } + + public void setValue(String value) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, value, Object.class); + } + + public void setTarget(String target) { + targetExpression = ExpressionUtil.createValueExpression(pageContext, target, Object.class); + } + + public void setProperty(String property) { + propertyExpression = ExpressionUtil.createValueExpression(pageContext, property, String.class); + } + + @Override + public void release() { + valueExpression = null; + targetExpression = null; + propertyExpression = null; + super.release(); + } + + @Override + protected boolean isValueSpecified() { + return valueExpression != null; + } + + @Override + protected Object evalValue() throws JspException { + return valueExpression.getValue(pageContext.getELContext()); + } + + @Override + protected Object evalTarget() throws JspException { + return targetExpression.getValue(pageContext.getELContext()); + } + + @Override + protected String evalProperty() throws JspException { + return (String) propertyExpression.getValue(pageContext.getELContext()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/UrlTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/UrlTag.java new file mode 100644 index 000000000..52bd33cdf --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/UrlTag.java @@ -0,0 +1,58 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.UrlSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class UrlTag extends UrlSupport { + + private ValueExpression valueExpression; + private ValueExpression contextExpression; + + public UrlTag() { + } + + @Override + public int doStartTag() throws JspException { + value = (String) valueExpression.getValue(pageContext.getELContext()); + if (contextExpression != null) { + context = (String) contextExpression.getValue(pageContext.getELContext()); + } + return super.doStartTag(); + } + + @Override + public void release() { + valueExpression = null; + contextExpression = null; + super.release(); + } + + public void setValue(String value) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, value, String.class); + } + + public void setContext(String context) { + contextExpression = ExpressionUtil.createValueExpression(pageContext, context, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/WhenTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/WhenTag.java new file mode 100644 index 000000000..a8e7a4b5f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/core/WhenTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.compat.core; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + */ +public class WhenTag extends WhenTagSupport { + + private ValueExpression testExpression; + + public WhenTag() { + } + + @Override + public void release() { + testExpression = null; + super.release(); + } + + @Override + protected boolean condition() throws JspTagException { + return (Boolean) testExpression.getValue(pageContext.getELContext()); + } + + public void setTest(String test) { + testExpression = ExpressionUtil.createValueExpression(pageContext, test, Boolean.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/BundleTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/BundleTag.java new file mode 100644 index 000000000..e8dae9bef --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/BundleTag.java @@ -0,0 +1,56 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.BundleSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class BundleTag extends BundleSupport { + + private ValueExpression basenameExpression; + private ValueExpression prefixExpression; + + public int doStartTag() throws JspException { + basename = ExpressionUtil.evaluate(basenameExpression, pageContext); + prefix = ExpressionUtil.evaluate(prefixExpression, pageContext); + + return super.doStartTag(); + } + + public void release() { + super.release(); + + basenameExpression = null; + prefixExpression = null; + } + + + public void setBasename(String expression) { + basenameExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPrefix(String expression) { + prefixExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatDateTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatDateTag.java new file mode 100644 index 000000000..f3f4e4bb7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatDateTag.java @@ -0,0 +1,86 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import java.util.Date; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.FormatDateSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class FormatDateTag extends FormatDateSupport { + + private ValueExpression valueExpression; + private ValueExpression typeExpression; + private ValueExpression dateStyleExpression; + private ValueExpression timeStyleExpression; + private ValueExpression patternExpression; + private ValueExpression timeZoneExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + type = ExpressionUtil.evaluate(typeExpression, pageContext); + dateStyle = ExpressionUtil.evaluate(dateStyleExpression, pageContext); + timeStyle = ExpressionUtil.evaluate(timeStyleExpression, pageContext); + pattern = ExpressionUtil.evaluate(patternExpression, pageContext); + timeZone = ExpressionUtil.evaluate(timeZoneExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + valueExpression = null; + typeExpression = null; + dateStyleExpression = null; + timeStyleExpression = null; + patternExpression = null; + timeZoneExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Date.class); + } + + public void setType(String expression) { + typeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setDateStyle(String expression) { + dateStyleExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setTimeStyle(String expression) { + timeStyleExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPattern(String expression) { + patternExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setTimeZone(String expression) { + timeZoneExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatNumberTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatNumberTag.java new file mode 100644 index 000000000..04c3745ea --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/FormatNumberTag.java @@ -0,0 +1,119 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.FormatNumberSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class FormatNumberTag extends FormatNumberSupport { + + private ValueExpression valueExpression; + private ValueExpression typeExpression; + private ValueExpression patternExpression; + private ValueExpression currencyCodeExpression; + private ValueExpression currencySymbolExpression; + private ValueExpression groupingUsedExpression; + private ValueExpression maxIntegerDigitsExpression; + private ValueExpression minIntegerDigitsExpression; + private ValueExpression maxFractionDigitsExpression; + private ValueExpression minFractionDigitsExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + type = ExpressionUtil.evaluate(typeExpression, pageContext); + pattern = ExpressionUtil.evaluate(patternExpression, pageContext); + currencyCode = ExpressionUtil.evaluate(currencyCodeExpression, pageContext); + currencySymbol = ExpressionUtil.evaluate(currencySymbolExpression, pageContext); + isGroupingUsed = ExpressionUtil.evaluate(groupingUsedExpression, pageContext, false); + maxIntegerDigits = ExpressionUtil.evaluate(maxIntegerDigitsExpression, pageContext, 0); + minIntegerDigits = ExpressionUtil.evaluate(minIntegerDigitsExpression, pageContext, 0); + maxFractionDigits = ExpressionUtil.evaluate(maxFractionDigitsExpression, pageContext, 0); + minFractionDigits = ExpressionUtil.evaluate(minFractionDigitsExpression, pageContext, 0); + + return super.doStartTag(); + } + + @Override + public void release() { + valueExpression = null; + typeExpression = null; + patternExpression = null; + currencyCodeExpression = null; + currencySymbolExpression = null; + groupingUsedExpression = null; + maxIntegerDigitsExpression = null; + minIntegerDigitsExpression = null; + maxFractionDigitsExpression = null; + minFractionDigitsExpression = null; + + super.release(); + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + valueSpecified = true; + } + + public void setType(String expression) { + typeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPattern(String expression) { + patternExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setCurrencyCode(String expression) { + currencyCodeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setCurrencySymbol(String expression) { + currencySymbolExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setGroupingUsed(String expression) { + groupingUsedExpression = ExpressionUtil.createValueExpression(pageContext, expression, Boolean.class); + groupingUsedSpecified = true; + } + + public void setMaxIntegerDigits(String expression) { + maxIntegerDigitsExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + maxIntegerDigitsSpecified = true; + } + + public void setMinIntegerDigits(String expression) { + minIntegerDigitsExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + minIntegerDigitsSpecified = true; + } + + public void setMaxFactionDigits(String expression) { + maxFractionDigitsExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + maxFractionDigitsSpecified = true; + } + + public void setMinFractionDigits(String expression) { + minFractionDigitsExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + minFractionDigitsSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/MessageTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/MessageTag.java new file mode 100644 index 000000000..dc6fb8d6b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/MessageTag.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; + +import org.apache.taglibs.standard.tag.common.fmt.MessageSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class MessageTag extends MessageSupport { + + private ValueExpression keyExpression; + private ValueExpression bundleExpression; + + @Override + public int doStartTag() throws JspException { + keyAttrValue = ExpressionUtil.evaluate(keyExpression, pageContext); + bundleAttrValue = ExpressionUtil.evaluate(bundleExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + keyExpression = null; + bundleExpression = null; + } + + public void setKey(String expression) { + keyExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + keySpecified = true; + } + + public void setBundle(String expression) { + bundleExpression = ExpressionUtil.createValueExpression(pageContext, expression, LocalizationContext.class); + bundleSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParamTag.java new file mode 100644 index 000000000..2dbb96602 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParamTag.java @@ -0,0 +1,50 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.ParamSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParamTag extends ParamSupport { + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + valueSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseDateTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseDateTag.java new file mode 100644 index 000000000..6e1a515c9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseDateTag.java @@ -0,0 +1,94 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseDateSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParseDateTag extends ParseDateSupport { + + private ValueExpression valueExpression; + private ValueExpression typeExpression; + private ValueExpression dateStyleExpression; + private ValueExpression timeStyleExpression; + private ValueExpression patternExpression; + private ValueExpression timeZoneExpression; + private ValueExpression parseLocaleExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + type = ExpressionUtil.evaluate(typeExpression, pageContext); + dateStyle = ExpressionUtil.evaluate(dateStyleExpression, pageContext); + timeStyle = ExpressionUtil.evaluate(timeStyleExpression, pageContext); + pattern = ExpressionUtil.evaluate(patternExpression, pageContext); + timeZone = ExpressionUtil.evaluate(timeZoneExpression, pageContext); + parseLocale = LocaleUtil.parseLocaleAttributeValue( + ExpressionUtil.evaluate(parseLocaleExpression, pageContext)); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + valueExpression = null; + typeExpression = null; + dateStyleExpression = null; + timeStyleExpression = null; + patternExpression = null; + timeZoneExpression = null; + parseLocaleExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + valueSpecified = true; + } + + public void setType(String expression) { + typeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setDateStyle(String expression) { + dateStyleExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setTimeStyle(String expression) { + timeStyleExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPattern(String expression) { + patternExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setTimeZone(String expression) { + timeZoneExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } + + public void setParseLocale(String expression) { + parseLocaleExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseNumberTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseNumberTag.java new file mode 100644 index 000000000..38b8161ba --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/ParseNumberTag.java @@ -0,0 +1,82 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseNumberSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParseNumberTag extends ParseNumberSupport { + + private ValueExpression valueExpression; + private ValueExpression typeExpression; + private ValueExpression patternExpression; + private ValueExpression parseLocaleExpression; + private ValueExpression integerOnlyExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + type = ExpressionUtil.evaluate(typeExpression, pageContext); + pattern = ExpressionUtil.evaluate(patternExpression, pageContext); + parseLocale = LocaleUtil.parseLocaleAttributeValue( + ExpressionUtil.evaluate(parseLocaleExpression, pageContext)); + isIntegerOnly = ExpressionUtil.evaluate(integerOnlyExpression, pageContext, false); + + return super.doStartTag(); + } + + @Override + public void release() { + valueExpression = null; + typeExpression = null; + patternExpression = null; + parseLocaleExpression = null; + integerOnlyExpression = null; + + super.release(); + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + valueSpecified = true; + } + + public void setType(String expression) { + typeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPattern(String expression) { + patternExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setParseLocale(String expression) { + parseLocaleExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } + + public void setIntegerOnly(String expression) { + integerOnlyExpression = ExpressionUtil.createValueExpression(pageContext, expression, Boolean.class); + integerOnlySpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/RequestEncodingTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/RequestEncodingTag.java new file mode 100644 index 000000000..5fe07ca61 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/RequestEncodingTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.RequestEncodingSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class RequestEncodingTag extends RequestEncodingSupport { + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetBundleTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetBundleTag.java new file mode 100644 index 000000000..35ca19f79 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetBundleTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.SetBundleSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class SetBundleTag extends SetBundleSupport { + + private ValueExpression basenameExpression; + + public int doStartTag() throws JspException { + basename = ExpressionUtil.evaluate(basenameExpression, pageContext); + + return super.doStartTag(); + } + + public void release() { + super.release(); + + basenameExpression = null; + } + + + public void setBasename(String expression) { + basenameExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetLocaleTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetLocaleTag.java new file mode 100644 index 000000000..c3e521482 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetLocaleTag.java @@ -0,0 +1,56 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.SetLocaleSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class SetLocaleTag extends SetLocaleSupport { + private ValueExpression valueExpression; + private ValueExpression variantExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + variant = ExpressionUtil.evaluate(variantExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + variantExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } + + public void setVariant(String expression) { + variantExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetTimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetTimeZoneTag.java new file mode 100644 index 000000000..e3963f1e6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/SetTimeZoneTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.SetTimeZoneSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class SetTimeZoneTag extends SetTimeZoneSupport { + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/TimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/TimeZoneTag.java new file mode 100644 index 000000000..22ad2e873 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/fmt/TimeZoneTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.fmt; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.fmt.TimeZoneSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class TimeZoneTag extends TimeZoneSupport { + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/DateParamTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/DateParamTag.java new file mode 100644 index 000000000..689a8fe8e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/DateParamTag.java @@ -0,0 +1,58 @@ +/* + * 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.taglibs.standard.tag.compat.sql; + +import java.util.Date; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.DateParamTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class DateParamTag extends DateParamTagSupport { + private ValueExpression valueExpression; + private ValueExpression typeExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + type = ExpressionUtil.evaluate(typeExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + typeExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Date.class); + } + + public void setType(String expression) { + typeExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/ParamTag.java new file mode 100644 index 000000000..25b2953be --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/ParamTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.sql; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.ParamTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParamTag extends ParamTagSupport { + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + valueExpression = null; + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/QueryTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/QueryTag.java new file mode 100644 index 000000000..3416aa929 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/QueryTag.java @@ -0,0 +1,72 @@ +/* + * 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.taglibs.standard.tag.compat.sql; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.QueryTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class QueryTag extends QueryTagSupport { + private ValueExpression dataSourceExpression; + private ValueExpression sqlExpression; + private ValueExpression startRowExpression; + private ValueExpression maxRowsExpression; + + @Override + public int doStartTag() throws JspException { + rawDataSource = ExpressionUtil.evaluate(dataSourceExpression, pageContext); + sql = ExpressionUtil.evaluate(sqlExpression, pageContext); + startRow = ExpressionUtil.evaluate(startRowExpression, pageContext, 0); + maxRows = ExpressionUtil.evaluate(maxRowsExpression, pageContext, -1); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + dataSourceExpression = null; + sqlExpression = null; + startRowExpression = null; + maxRowsExpression = null; + } + + public void setDataSource(String expression) { + dataSourceExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + dataSourceSpecified = true; + } + + public void setSql(String expression) { + sqlExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setStartRow(String expression) { + startRowExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + } + + public void setMaxRows(String expression) { + maxRowsExpression = ExpressionUtil.createValueExpression(pageContext, expression, Integer.class); + maxRowsSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/SetDataSourceTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/SetDataSourceTag.java new file mode 100644 index 000000000..8718dfa46 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/SetDataSourceTag.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 org.apache.taglibs.standard.tag.compat.sql; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.SetDataSourceTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class SetDataSourceTag extends SetDataSourceTagSupport { + private ValueExpression dataSourceExpression; + private ValueExpression driverClassNameExpression; + private ValueExpression jdbcUrlExpression; + private ValueExpression usernameExpression; + private ValueExpression passwordExpression; + + @Override + public int doStartTag() throws JspException { + dataSource = ExpressionUtil.evaluate(dataSourceExpression, pageContext); + driverClassName = ExpressionUtil.evaluate(driverClassNameExpression, pageContext); + jdbcURL = ExpressionUtil.evaluate(jdbcUrlExpression, pageContext); + userName = ExpressionUtil.evaluate(usernameExpression, pageContext); + password = ExpressionUtil.evaluate(passwordExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + dataSourceExpression = null; + driverClassNameExpression = null; + jdbcUrlExpression = null; + usernameExpression = null; + passwordExpression = null; + } + + public void setDataSource(String expression) { + dataSourceExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + dataSourceSpecified = true; + } + + public void setDriver(String expression) { + driverClassNameExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setUrl(String expression) { + jdbcUrlExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setUser(String expression) { + usernameExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setPassword(String expression) { + passwordExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/TransactionTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/TransactionTag.java new file mode 100644 index 000000000..6259a8f1e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/TransactionTag.java @@ -0,0 +1,59 @@ +/* + * 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.taglibs.standard.tag.compat.sql; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.TransactionTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class TransactionTag extends TransactionTagSupport { + private ValueExpression dataSourceExpression; + private ValueExpression isolationExpression; + + @Override + public int doStartTag() throws JspException { + rawDataSource = ExpressionUtil.evaluate(dataSourceExpression, pageContext); + if (isolationExpression != null) { + super.setIsolation((String) ExpressionUtil.evaluate(isolationExpression, pageContext)); + } + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + dataSourceExpression = null; + isolationExpression = null; + } + + public void setDataSource(String expression) { + dataSourceExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + dataSourceSpecified = true; + } + + public void setIsolation(String expression) { + isolationExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/UpdateTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/UpdateTag.java new file mode 100644 index 000000000..ab71c3688 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/sql/UpdateTag.java @@ -0,0 +1,57 @@ +/* + * 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.taglibs.standard.tag.compat.sql; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.UpdateTagSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class UpdateTag extends UpdateTagSupport { + private ValueExpression dataSourceExpression; + private ValueExpression sqlExpression; + + @Override + public int doStartTag() throws JspException { + rawDataSource = ExpressionUtil.evaluate(dataSourceExpression, pageContext); + sql = ExpressionUtil.evaluate(sqlExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + dataSourceExpression = null; + sqlExpression = null; + } + + public void setDataSource(String expression) { + dataSourceExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + dataSourceSpecified = true; + } + + public void setSql(String expression) { + sqlExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ExprTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ExprTag.java new file mode 100644 index 000000000..55641c22d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ExprTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tag.compat.xml; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.xml.ExprSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ExprTag extends ExprSupport { + private ValueExpression escapeXmlExpression; + + @Override + public int doStartTag() throws JspException { + escapeXml = ExpressionUtil.evaluate(escapeXmlExpression, pageContext, true); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + escapeXmlExpression = null; + } + + public void setEscapeXml(String expression) { + escapeXmlExpression = ExpressionUtil.createValueExpression(pageContext, expression, Boolean.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParamTag.java new file mode 100644 index 000000000..c6e23f8f3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParamTag.java @@ -0,0 +1,56 @@ +/* + * 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.taglibs.standard.tag.compat.xml; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.xml.ParamSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParamTag extends ParamSupport { + private ValueExpression nameExpression; + private ValueExpression valueExpression; + + @Override + public int doStartTag() throws JspException { + name = ExpressionUtil.evaluate(nameExpression, pageContext); + value = ExpressionUtil.evaluate(valueExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + nameExpression = null; + valueExpression = null; + } + + public void setName(String expression) { + nameExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setValue(String expression) { + valueExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParseTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParseTag.java new file mode 100644 index 000000000..f7db1eee3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/ParseTag.java @@ -0,0 +1,64 @@ +/* + * 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.taglibs.standard.tag.compat.xml; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.xml.ParseSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; +import org.xml.sax.XMLFilter; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class ParseTag extends ParseSupport { + private ValueExpression xmlExpression; + private ValueExpression systemIdExpression; + private ValueExpression filterExpression; + + @Override + public int doStartTag() throws JspException { + xml = ExpressionUtil.evaluate(xmlExpression, pageContext); + systemId = ExpressionUtil.evaluate(systemIdExpression, pageContext); + filter = ExpressionUtil.evaluate(filterExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + xmlExpression = null; + systemIdExpression = null; + filterExpression = null; + } + + public void setXml(String expression) { + xmlExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } + + public void setSystemId(String expression) { + systemIdExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setFilter(String expression) { + filterExpression = ExpressionUtil.createValueExpression(pageContext, expression, XMLFilter.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/TransformTag.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/TransformTag.java new file mode 100644 index 000000000..abd36b700 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tag/compat/xml/TransformTag.java @@ -0,0 +1,79 @@ +/* + * 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.taglibs.standard.tag.compat.xml; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspException; +import javax.xml.transform.Result; + +import org.apache.taglibs.standard.tag.common.xml.TransformSupport; +import org.apache.taglibs.standard.util.ExpressionUtil; + +/** + * Implementation of JSTL 1.0 {@code } using the container's EL implementation. + */ +public class TransformTag extends TransformSupport { + private ValueExpression xmlExpression; + private ValueExpression xmlSystemIdExpression; + private ValueExpression xsltExpression; + private ValueExpression xsltSystemIdExpression; + private ValueExpression resultExpression; + + @Override + public int doStartTag() throws JspException { + xml = ExpressionUtil.evaluate(xmlExpression, pageContext); + xmlSystemId = ExpressionUtil.evaluate(xmlSystemIdExpression, pageContext); + xslt = ExpressionUtil.evaluate(xsltExpression, pageContext); + xsltSystemId = ExpressionUtil.evaluate(xsltSystemIdExpression, pageContext); + result = ExpressionUtil.evaluate(resultExpression, pageContext); + + return super.doStartTag(); + } + + @Override + public void release() { + super.release(); + + xmlExpression = null; + xmlSystemIdExpression = null; + xsltExpression = null; + xsltSystemIdExpression = null; + resultExpression = null; + } + + public void setXml(String expression) { + xmlExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + xmlSpecified = true; + } + + public void setXmlSystemId(String expression) { + xmlSystemIdExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setXslt(String expression) { + xsltExpression = ExpressionUtil.createValueExpression(pageContext, expression, Object.class); + } + + public void setXsltSystemId(String expression) { + xsltSystemIdExpression = ExpressionUtil.createValueExpression(pageContext, expression, String.class); + } + + public void setResult(String expression) { + resultExpression = ExpressionUtil.createValueExpression(pageContext, expression, Result.class); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELCoreTLV.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELCoreTLV.java new file mode 100644 index 000000000..a5d7d8738 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELCoreTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.compat; + +import org.apache.taglibs.standard.tlv.JstlCoreTLV; + +/** + */ +public class JstlELCoreTLV extends JstlCoreTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELFmtTLV.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELFmtTLV.java new file mode 100644 index 000000000..4134c1d6d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELFmtTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.compat; + +import org.apache.taglibs.standard.tlv.JstlFmtTLV; + +/** + */ +public class JstlELFmtTLV extends JstlFmtTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELSqlTLV.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELSqlTLV.java new file mode 100644 index 000000000..53807f507 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELSqlTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.compat; + +import org.apache.taglibs.standard.tlv.JstlSqlTLV; + +/** + */ +public class JstlELSqlTLV extends JstlSqlTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELXmlTLV.java b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELXmlTLV.java new file mode 100644 index 000000000..1bd893d6a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/java/org/apache/taglibs/standard/tlv/compat/JstlELXmlTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.compat; + +import org.apache.taglibs.standard.tlv.JstlXmlTLV; + +/** + */ +public class JstlELXmlTLV extends JstlXmlTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/c-1_0.tld b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/c-1_0.tld new file mode 100644 index 000000000..da3573fb5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/c-1_0.tld @@ -0,0 +1,432 @@ + + + + + 1.0 + 1.2 + c + http://java.sun.com/jstl/core + JSTL core + JSTL 1.0 core library + + + + org.apache.taglibs.standard.tlv.compat.JstlELCoreTLV + + + expressionAttributes + + out:value + out:default + out:escapeXml + if:test + import:url + import:context + import:charEncoding + forEach:items + forEach:begin + forEach:end + forEach:step + forTokens:items + forTokens:begin + forTokens:end + forTokens:step + param:encode + param:name + param:value + redirect:context + redirect:url + set:property + set:target + set:value + url:context + url:value + when:test + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + catch + org.apache.taglibs.standard.tag.common.core.CatchTag + JSP + + Catches any Throwable that occurs in its body and optionally + exposes it. + + + var + false + false + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + out + org.apache.taglibs.standard.tag.compat.core.OutTag + JSP + + Like <%= ... >, but for expressions. + + + value + true + false + + + default + false + false + + + escapeXml + false + false + + + + + if + org.apache.taglibs.standard.tag.compat.core.IfTag + JSP + + 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 + + + test + true + false + + + var + false + false + + + scope + false + false + + + + + import + org.apache.taglibs.standard.tag.compat.core.ImportTag + org.apache.taglibs.standard.tei.ImportTEI + JSP + + Retrieves an absolute or relative URL and exposes its contents + to either the page, a String in 'var', or a Reader in 'varReader'. + + + url + true + false + + + var + false + false + + + scope + false + false + + + varReader + false + false + + + context + false + false + + + charEncoding + false + false + + + + + forEach + org.apache.taglibs.standard.tag.compat.core.ForEachTag + org.apache.taglibs.standard.tei.ForEachTEI + JSP + + The basic iteration tag, accepting many different + collection types and supporting subsetting and other + functionality + + + items + false + false + + + begin + false + false + + + end + false + false + + + step + false + false + + + var + false + false + + + varStatus + false + false + + + + + forTokens + org.apache.taglibs.standard.tag.compat.core.ForTokensTag + JSP + + Iterates over tokens, separated by the supplied delimeters + + + items + true + false + + + delims + true + false + + + begin + false + false + + + end + false + false + + + step + false + false + + + var + false + false + + + varStatus + false + false + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.compat.core.ParamTag + JSP + + Adds a parameter to a containing 'import' tag's URL. + + + name + true + false + + + value + false + false + + + + + redirect + org.apache.taglibs.standard.tag.compat.core.RedirectTag + JSP + + Redirects to a new URL. + + + var + false + false + + + scope + false + false + + + url + true + false + + + context + false + false + + + + + remove + org.apache.taglibs.standard.tag.common.core.RemoveTag + empty + + Removes a scoped variable (from a particular scope, if specified). + + + var + true + false + + + scope + false + false + + + + + set + org.apache.taglibs.standard.tag.compat.core.SetTag + JSP + + Sets the result of an expression evaluation in a 'scope' + + + var + false + false + + + value + false + false + + + target + false + false + + + property + false + false + + + scope + false + false + + + + + url + org.apache.taglibs.standard.tag.compat.core.UrlTag + JSP + + Prints or exposes a URL with optional query parameters + (via the c:param tag). + + + var + false + false + + + scope + false + false + + + value + true + false + + + context + false + false + + + + + when + org.apache.taglibs.standard.tag.compat.core.WhenTag + JSP + + Subtag of <choose> that includes its body if its + condition evalutes to 'true' + + + test + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/fmt-1_0.tld b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/fmt-1_0.tld new file mode 100644 index 000000000..4caec3d67 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/fmt-1_0.tld @@ -0,0 +1,458 @@ + + + + + 1.0 + 1.2 + fmt + http://java.sun.com/jstl/fmt + JSTL fmt + JSTL 1.0 i18n-capable formatting library + + + + org.apache.taglibs.standard.tlv.compat.JstlELFmtTLV + + + expressionAttributes + + requestEncoding:value + setLocale:value + setLocale:variant + timeZone:value + setTimeZone:value + bundle:basename + bundle:prefix + setBundle:basename + message:key + message:bundle + param:value + formatNumber:value + formatNumber:pattern + formatNumber:currencyCode + formatNumber:currencySymbol + formatNumber:groupingUsed + formatNumber:maxIntegerDigits + formatNumber:minIntegerDigits + formatNumber:maxFractionDigits + formatNumber:minFractionDigits + parseNumber:value + parseNumber:pattern + parseNumber:parseLocale + parseNumber:integerOnly + formatDate:value + formatDate:pattern + formatDate:timeZone + parseDate:value + parseDate:pattern + parseDate:timeZone + parseDate:parseLocale + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + requestEncoding + org.apache.taglibs.standard.tag.compat.fmt.RequestEncodingTag + empty + + Sets the request character encoding + + + value + false + false + + + + + setLocale + org.apache.taglibs.standard.tag.compat.fmt.SetLocaleTag + empty + + Stores the given locale in the locale configuration variable + + + value + true + false + + + variant + false + false + + + scope + false + false + + + + + timeZone + org.apache.taglibs.standard.tag.compat.fmt.TimeZoneTag + JSP + + Specifies the time zone for any time formatting or parsing actions + nested in its body + + + value + true + false + + + + + setTimeZone + org.apache.taglibs.standard.tag.compat.fmt.SetTimeZoneTag + empty + + Stores the given time zone in the time zone configuration variable + + + value + true + false + + + var + false + false + + + scope + false + false + + + + + bundle + org.apache.taglibs.standard.tag.compat.fmt.BundleTag + JSP + + Loads a resource bundle to be used by its tag body + + + basename + true + false + + + prefix + false + false + + + + + setBundle + org.apache.taglibs.standard.tag.compat.fmt.SetBundleTag + empty + + Loads a resource bundle and stores it in the named scoped variable or + the bundle configuration variable + + + basename + true + false + + + var + false + false + + + scope + false + false + + + + + message + org.apache.taglibs.standard.tag.compat.fmt.MessageTag + JSP + + Maps key to localized message and performs parametric replacement + + + key + false + false + + + bundle + false + false + + + var + false + false + + + scope + false + false + + + + + param + org.apache.taglibs.standard.tag.compat.fmt.ParamTag + JSP + + Supplies an argument for parametric replacement to a containing + <message> tag + + + value + false + false + + + + + formatNumber + org.apache.taglibs.standard.tag.compat.fmt.FormatNumberTag + JSP + + Formats a numeric value as a number, currency, or percentage + + + value + false + false + + + type + false + false + + + pattern + false + false + + + currencyCode + false + false + + + currencySymbol + false + false + + + groupingUsed + false + false + + + maxIntegerDigits + false + false + + + minIntegerDigits + false + false + + + maxFractionDigits + false + false + + + minFractionDigits + false + false + + + var + false + false + + + scope + false + false + + + + + parseNumber + org.apache.taglibs.standard.tag.compat.fmt.ParseNumberTag + JSP + + Parses the string representation of a number, currency, or percentage + + + value + false + false + + + type + false + false + + + pattern + false + false + + + parscompatocale + false + false + + + integerOnly + false + false + + + var + false + false + + + scope + false + false + + + + + formatDate + org.apache.taglibs.standard.tag.compat.fmt.FormatDateTag + empty + + Formats a date and/or time using the supplied styles and pattern + + + value + true + false + + + type + false + false + + + dateStyle + false + false + + + timeStyle + false + false + + + pattern + false + false + + + timeZone + false + false + + + var + false + false + + + scope + false + false + + + + + parseDate + org.apache.taglibs.standard.tag.compat.fmt.ParseDateTag + JSP + + Parses the string representation of a date and/or time + + + value + false + false + + + type + false + false + + + dateStyle + false + false + + + timeStyle + false + false + + + pattern + false + false + + + timeZone + false + false + + + parscompatocale + false + false + + + var + false + false + + + scope + false + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/sql-1_0.tld b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/sql-1_0.tld new file mode 100644 index 000000000..fa6353ee9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/sql-1_0.tld @@ -0,0 +1,229 @@ + + + + + 1.0 + 1.2 + sql + http://java.sun.com/jstl/sql + JSTL sql + JSTL 1.0 sql library + + + + org.apache.taglibs.standard.tlv.compat.JstlELSqlTLV + + + expressionAttributes + + transaction:dataSource + transaction:isolation + query:sql + query:dataSource + query:startRow + query:maxRows + update:sql + update:dataSource + param:value + dateParam:value + dateParam:type + setDataSource:dataSource + setDataSource:driver + setDataSource:url + setDataSource:user + setDataSource:password + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + transaction + org.apache.taglibs.standard.tag.compat.sql.TransactionTag + JSP + + Provides nested database action elements with a shared Connection, + set up to execute all statements as one transaction. + + + dataSource + false + false + + + isolation + false + false + + + + + query + org.apache.taglibs.standard.tag.compat.sql.QueryTag + JSP + + Executes the SQL query defined in its body or through the + sql attribute. + + + var + true + false + + + scope + false + false + + + sql + false + false + + + dataSource + false + false + + + startRow + false + false + + + maxRows + false + false + + + + + update + org.apache.taglibs.standard.tag.compat.sql.UpdateTag + JSP + + Executes the SQL update defined in its body or through the + sql attribute. + + + var + false + false + + + scope + false + false + + + sql + false + false + + + dataSource + false + false + + + + + param + org.apache.taglibs.standard.tag.compat.sql.ParamTag + JSP + + Sets a parameter in an SQL statement to the specified value. + + + value + false + false + + + + + dateParam + org.apache.taglibs.standard.tag.compat.sql.DateParamTag + empty + + Sets a parameter in an SQL statement to the specified java.util.Date val + ue. + + + value + true + true + + + type + false + true + + + + + setDataSource + org.apache.taglibs.standard.tag.compat.sql.SetDataSourceTag + empty + + Creates a simple DataSource suitable only for prototyping. + + + var + false + false + + + scope + false + false + + + dataSource + false + false + + + driver + false + false + + + url + false + false + + + user + false + false + + + password + false + false + + + diff --git a/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/x-1_0.tld b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/x-1_0.tld new file mode 100644 index 000000000..5ff891189 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/compat/src/main/resources/META-INF/x-1_0.tld @@ -0,0 +1,289 @@ + + + + + 1.0 + 1.2 + x + http://java.sun.com/jstl/xml + JSTL XML + JSTL 1.0 XML library + + + + org.apache.taglibs.standard.tlv.compat.JstlELXmlTLV + + + expressionAttributes + + out:escapeXml + parse:xml + parse:systemId + parse:filter + transform:xml + transform:xmlSystemId + transform:xslt + transform:xsltSystemId + transform:result + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + out + org.apache.taglibs.standard.tag.compat.xml.ExprTag + empty + + Like <%= ... >, but for XPath expressions. + + + select + true + false + + + escapeXml + false + false + + + + + if + org.apache.taglibs.standard.tag.common.xml.IfTag + JSP + + XML conditional tag, which evalutes its body if the + supplied XPath expression evalutes to 'true' as a boolean + + + select + true + false + + + var + false + false + + + scope + false + false + + + + + forEach + org.apache.taglibs.standard.tag.common.xml.ForEachTag + JSP + + XML iteration tag. + + + var + false + false + + + select + true + false + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.compat.xml.ParamTag + JSP + + Adds a parameter to a containing 'transform' tag's Transformer + + + name + true + false + + + value + false + false + + + + + parse + org.apache.taglibs.standard.tag.compat.xml.ParseTag + org.apache.taglibs.standard.tei.XmlParseTEI + JSP + + Parses XML content from 'source' attribute or 'body' + + + var + false + false + + + varDom + false + false + + + scope + false + false + + + scopeDom + false + false + + + xml + false + false + + + systemId + false + false + + + filter + false + false + + + + + set + org.apache.taglibs.standard.tag.common.xml.SetTag + empty + + Saves the result of an XPath expression evaluation in a 'scope' + + + var + true + false + + + select + false + false + + + scope + false + false + + + + + transform + org.apache.taglibs.standard.tag.compat.xml.TransformTag + org.apache.taglibs.standard.tei.XmlTransformTEI + JSP + + Conducts a transformation given a source XML document + and an XSLT stylesheet + + + var + false + false + + + scope + false + false + + + result + false + false + + + xml + false + false + + + xmlSystemId + false + false + + + xslt + false + false + + + xsltSystemId + false + false + + + + + when + org.apache.taglibs.standard.tag.common.xml.WhenTag + JSP + + Subtag of <choose> that includes its body if its + expression evalutes to 'true' + + + select + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/pom.xml b/Java-base/tomcat-taglibs-standard/src/impl/pom.xml new file mode 100644 index 000000000..8e6bfa69a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/pom.xml @@ -0,0 +1,142 @@ + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-standard-impl + 2.0.0-SNAPSHOT + bundle + + Apache Standard Taglib Implementation + + + An implementation of the JSP Standard Tag Library (JSTL). + + + + + org.apache.taglibs + taglibs-standard-spec + provided + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + provided + + + xalan + xalan + provided + true + + + + junit + junit + test + + + org.easymock + easymock + test + + + + + + + org.apache.felix + maven-bundle-plugin + + true + + *;version="1.2" + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../build-tools/src/main/resources/taglibs/checkstyle.xml + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + ${maven.compiler.target} + + + + + pmd + cpd + + + + + + org.codehaus.mojo + taglist-maven-plugin + 2.4 + + + org.codehaus.mojo + javancss-maven-plugin + 2.0 + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + Normal + Default + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/Version.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/Version.java new file mode 100644 index 000000000..f2539c78e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/Version.java @@ -0,0 +1,121 @@ +/* + * 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.taglibs.standard; + +/** + * [lifted from xalan] + * + * Administrative class to keep track of the version number of + * the standard tag library. + *

This class implements the upcoming standard of having + * org.apache.project-name.Version.getVersion() be a standard way + * to get version information. + */ +public class Version { + /** + * Get the basic version string for the current release. + * Version String formatted like + * "standard-taglib v.r[.dd| Dnn]". + *

Futurework: have this read version info from jar manifest. + * + * @return String denoting our current version + */ + public static String getVersion() { + return getProduct() + " " + + getMajorVersionNum() + "." + getReleaseVersionNum() + "." + + getMaintenanceVersionNum() + + ((getDevelopmentVersionNum() > 0) ? + ("_D" + getDevelopmentVersionNum()) : ""); + } + + /** + * Print the processor version to the command line. + * + * @param argv command line arguments, unused. + */ + public static void main(String argv[]) { + System.out.println(getVersion()); + } + + /** + * Name of product + */ + public static String getProduct() { + return "standard-taglib"; + } + + /** + * Major version number. + * Version number. This changes only when there is a + * significant, externally apparent enhancement from + * the previous release. 'n' represents the n'th + * version. + *

Clients should carefully consider the implications + * of new versions as external interfaces and behaviour + * may have changed. + */ + public static int getMajorVersionNum() { + return 1; + } + + /** + * Release Number. + * Release number. This changes when: + * - a new set of functionality is to be added, eg, + * implementation of a new W3C specification. + * - API or behaviour change. + * - its designated as a reference release. + */ + public static int getReleaseVersionNum() { + return 2; + } + + /** + * Maintenance Drop Number. + * Optional identifier used to designate maintenance + * drop applied to a specific release and contains + * fixes for defects reported. It maintains compatibility + * with the release and contains no API changes. + * When missing, it designates the final and complete + * development drop for a release. + */ + public static int getMaintenanceVersionNum() { + // TODO: BZ 57548: Make this autogenerated by Maven, or read from "Implementation-Version" + // of Manifest. Note that there is a test class that has to be kept in sync (VersionTest). + return 6; + } + + /** + * Development Drop Number. + * Optional identifier designates development drop of + * a specific release. D01 is the first development drop + * of a new release. + *

Development drops are works in progress towards a + * compeleted, final release. A specific development drop + * may not completely implement all aspects of a new + * feature, which may take several development drops to + * complete. At the point of the final drop for the + * release, the D suffix will be omitted. + *

Each 'D' drops can contain functional enhancements as + * well as defect fixes. 'D' drops may not be as stable as + * the final releases. + */ + public static int getDevelopmentVersionNum() { + return 0; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/functions/Functions.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/functions/Functions.java new file mode 100644 index 000000000..2837b0564 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/functions/Functions.java @@ -0,0 +1,338 @@ +/* + * 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.taglibs.standard.functions; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.StringTokenizer; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.util.EscapeXML; + +/** + * Static functions that extend the Expression Language with standardized behaviour + * commonly used by page authors. + *

Implementation Note: When passing a String parameter, section + * 1.18.2 of the EL specification requires the container to coerce a null value to an + * empty string. These implementation assume such behaviour and do not check for null + * parameters. Passing a null will generally trigger a NullPointerException. + * + * @author Pierre Delisle + */ +public class Functions { + + //********************************************************************* + // String capitalization + + /** + * Converts all of the characters of the input string to upper case according to the + * semantics of method String#toUpperCase(). + * + * @param input the input string on which the transformation to upper case is applied + * @return the input string transformed to upper case + */ + public static String toUpperCase(String input) { + return input.toUpperCase(); + } + + /** + * Converts all of the characters of the input string to lower case according to the + * semantics of method String#toLowerCase(). + * + * @param input the input string on which the transformation to lower case is applied + * @return the input string transformed to lower case + */ + public static String toLowerCase(String input) { + return input.toLowerCase(); + } + + //********************************************************************* + // Substring processing + + /** + * Returns the index (0-based) withing a string of the first occurrence of a specified + * substring according to the semantics of the method String#indexOf(). + *

If substring is empty, this matches the beginning of the string and the + * value returned is 0. + * + * @param input the input string on which the function is applied + * @param substring the substring to search for in the input string + * @return the 0-based index of the first matching substring, or -1 if it does not occur + */ + public static int indexOf(String input, String substring) { + return input.indexOf(substring); + } + + /** + * Tests if a string contains the specified substring. + * + * @param input the input string on which the function is applied + * @param substring the substring tested for + * @return true if the character sequence represented by the substring + * exists in the string + */ + public static boolean contains(String input, String substring) { + return input.contains(substring); + } + + /** + * Tests if a string contains the specified substring in a case insensitive way. + * Equivalent to fn:contains(fn:toUpperCase(string), fn:toUpperCase(substring)). + * + * @param input the input string on which the function is applied + * @param substring the substring tested for + * @return true if the character sequence represented by the substring + * exists in the string + */ + public static boolean containsIgnoreCase(String input, String substring) { + return contains(input.toUpperCase(), substring.toUpperCase()); + } + + /** + * Tests if a string starts with the specified prefix according to the semantics + * of String#startsWith(). + * + * @param input the input string on which the function is applied + * @param prefix the prefix to be matched + * @return true if the input string starts with the prefix + */ + public static boolean startsWith(String input, String prefix) { + return input.startsWith(prefix); + } + + /** + * Tests if a string ends with the specified suffix according to the semantics + * of String#endsWith(). + * + * @param input the input string on which the function is applied + * @param suffix the suffix to be matched + * @return true if the input string ends with the suffix + */ + public static boolean endsWith(String input, String suffix) { + return input.endsWith(suffix); + } + + /** + * Returns a subset of a string according to the semantics of String#substring() + * with additional semantics as follows: + *

    + *
  • if beginIndex < 0 its value is adjusted to 0
  • + *
  • if endIndex < 0 or greater than the string length, + * its value is adjusted to the length of the string
  • + *
  • if endIndex < beginIndex, an empty string is returned
  • + *
+ * + * @param input the input string on which the substring function is applied + * @param beginIndex the beginning index (0-based), inclusive + * @param endIndex the end index (0-based), exclusive + * @return a subset of string + */ + public static String substring(String input, int beginIndex, int endIndex) { + if (beginIndex < 0) { + beginIndex = 0; + } + if (endIndex < 0 || endIndex > input.length()) { + endIndex = input.length(); + } + if (endIndex < beginIndex) { + return ""; + } + return input.substring(beginIndex, endIndex); + } + + /** + * Returns a subset of a string following the first occurrence of a specific substring. + *

If the substring is empty, it matches the beginning of the input string and the + * entire input string is returned. If the substring does not occur, an empty string is returned. + * + * @param input the input string on which the substring function is applied + * @param substring the substring that delimits the beginning of the subset + * of the input string to be returned + * @return a substring of the input string that starts at the first character after the specified substring + */ + public static String substringAfter(String input, String substring) { + int index = input.indexOf(substring); + if (index == -1) { + return ""; + } else { + return input.substring(index + substring.length()); + } + } + + /** + * Returns a subset of a string immediately before the first occurrence of a specific substring. + *

If the substring is empty, it matches the beginning of the input string and an empty string is returned. + * If the substring does not occur, an empty string is returned. + * + * @param input the input string on which the substring function is applied + * @param substring the substring that delimits the beginning of the subset + * of the input string to be returned + * @return a substring of the input string that starts at the first character after the specified substring + */ + public static String substringBefore(String input, String substring) { + int index = input.indexOf(substring); + if (index == -1) { + return ""; + } else { + return input.substring(0, index); + } + } + + //********************************************************************* + // Character replacement + + /** + * Escapes characters that could be interpreted as XML markup as defined by the <c:out> action. + * + * @param input the string to escape + * @return escaped string + */ + public static String escapeXml(String input) { + return EscapeXML.escape(input); + } + + /** + * removes whitespace from both ends of a string according to the semantics of String#trim(). + * + * @param input the input string to be trimmed + * @return the trimmed string + */ + public static String trim(String input) { + return input.trim(); + } + + /** + * Returns a string resulting from replacing all occurrences of a "before" substring with an "after" substring. + * The string is processed once and not reprocessed for further replacements. + * + * @param input the string on which the replacement is to be applied + * @param before the substring to replace + * @param after the replacement substring + * @return a string with before replaced with after + */ + public static String replace(String input, String before, String after) { + if (before.length() == 0) { + return input; + } + return input.replace(before, after); + } + + /** + * Splits a string into an array of substrings according to the semantics of StringTokenizer. + * If the input string is empty, a single element array containing an empty string is returned. + * If the delimiters are empty, a single element array containing the input string is returned. + * + * @param input the string to split + * @param delimiters characters used to split the string + * @return an array of strings + */ + public static String[] split(String input, String delimiters) { + if (input.length() == 0 || delimiters.length() == 0) { + return new String[]{input}; + } + + StringTokenizer tok = new StringTokenizer(input, delimiters); + String[] array = new String[tok.countTokens()]; + int i = 0; + while (tok.hasMoreTokens()) { + array[i++] = tok.nextToken(); + } + return array; + } + + /** + * Joins all elements of an array into a string. + *

Implementation Note: The specification does not define what happens when + * elements in the array are null. For compatibility with previous implementations, the string + * "null" is used although EL conventions would suggest an empty string might be better. + * + * @param array an array of strings to be joined + * @param separator used to separate the joined strings + * @return all array elements joined into one string with the specified separator + */ + public static String join(String[] array, String separator) { + if (array == null || array.length == 0) { + return ""; + } + if (array.length == 1) { + return array[0] == null ? "null" : array[0]; + } + + StringBuilder buf = new StringBuilder(); + buf.append(array[0]); + for (int i = 1; i < array.length; i++) { + buf.append(separator).append(array[i]); + } + return buf.toString(); + } + + //********************************************************************* + // Collections processing + + /** + * Returns the number of items in a collection or the number of characters in a string. + * The collection can be of any type supported for the items attribute of + * the <c:forEach> action. + * + * @param obj the collection or string whose length should be computed + * @return the length of the collection or string; 0 if obj is null + * @throws JspTagException if the type is not valid + */ + public static int length(Object obj) throws JspTagException { + if (obj == null) { + return 0; + } + + if (obj instanceof String) { + return ((String) obj).length(); + } + if (obj instanceof Collection) { + return ((Collection) obj).size(); + } + if (obj instanceof Map) { + return ((Map) obj).size(); + } + if (obj instanceof Iterator) { + int count = 0; + Iterator iter = (Iterator) obj; + while (iter.hasNext()) { + count++; + iter.next(); + } + return count; + } + if (obj instanceof Enumeration) { + Enumeration enum_ = (Enumeration) obj; + int count = 0; + while (enum_.hasMoreElements()) { + count++; + enum_.nextElement(); + } + return count; + } + if (obj.getClass().isArray()) { + return Array.getLength(obj); + } + throw new JspTagException(Resources.getMessage("PARAM_BAD_VALUE")); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.java new file mode 100644 index 000000000..d819c9839 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/resources/Resources.java @@ -0,0 +1,77 @@ +/* + * 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.taglibs.standard.resources; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + *

Provides locale-neutral access to string resources. Only the + * documentation and code are in English. :-) + * + *

The major goal, aside from globalization, is convenience. + * Access to resources with no parameters is made in the form:

+ *
+ *     Resources.getMessage(MESSAGE_NAME);
+ * 
+ * + *

Access to resources with one parameter works like

+ *
+ *     Resources.getMessage(MESSAGE_NAME, arg1);
+ * 
+ * + *

... and so on.

+ * + * @author Shawn Bayern + */ +public class Resources { + + /** + * Our class-wide ResourceBundle. + */ + private static final ResourceBundle rb = ResourceBundle.getBundle(Resources.class.getName()); + + + //********************************************************************* + // Public static methods + + /** + * Retrieves a message with no arguments. + * + * @param name the name of the message + * @return the localized message text + * @throws MissingResourceException if the message does not exist + */ + public static String getMessage(String name) throws MissingResourceException { + return rb.getString(name); + } + + /** + * Retrieves a message with arbitrarily many arguments. + * + * @param name the name of the message + * @param a arguments to be substituted into the message text + * @return the localized message text + * @throws MissingResourceException if the message does not exist + */ + public static String getMessage(String name, Object... a) throws MissingResourceException { + String res = rb.getString(name); + return MessageFormat.format(res, a); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/CatchTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/CatchTag.java new file mode 100644 index 000000000..91fc5ff40 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/CatchTag.java @@ -0,0 +1,100 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; + +/** + *

Tag handler for <catch> in JSTL 1.0.

+ * + *

<catch> simply catches any Throwables that occur in its body + * and optionally exposes them. + * + * @author Shawn Bayern + */ + +public class CatchTag extends TagSupport implements TryCatchFinally { + + /* + * If all tags that I proposed were this simple, people might + * think I was just trying to avoid work. :-) + */ + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public CatchTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + private void init() { + var = null; + } + + + //********************************************************************* + // Private state + + private String var; // tag attribute + private boolean caught; // internal status + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() { + caught = false; + return EVAL_BODY_INCLUDE; + } + + public void doCatch(Throwable t) { + if (var != null) { + pageContext.setAttribute(var, t, PageContext.PAGE_SCOPE); + } + caught = true; + } + + public void doFinally() { + if (var != null && !caught) { + pageContext.removeAttribute(var, PageContext.PAGE_SCOPE); + } + } + + + //********************************************************************* + // Attribute accessors + + public void setVar(String var) { + this.var = var; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ChooseTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ChooseTag.java new file mode 100644 index 000000000..408f418c0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ChooseTag.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Tag handler for <choose> in JSTL.

+ * + *

<choose> is a very simple tag that acts primarily as a container; + * it always includes its body and allows exactly one of its child + * <when> tags to run. Since this tag handler doesn't have any + * attributes, it is common.core to both the rtexprvalue and expression- + * evaluating versions of the JSTL library. + * + * @author Shawn Bayern + */ + +public class ChooseTag extends TagSupport { + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public ChooseTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Private state + + private boolean subtagGateClosed; // has one subtag already executed? + + + //********************************************************************* + // Public methods implementing exclusivity checks + + /** + * Returns status indicating whether a subtag should run or not. + * + * @return true if the subtag should evaluate its condition + * and decide whether to run, false otherwise. + */ + public synchronized boolean gainPermission() { + return (!subtagGateClosed); + } + + /** + * Called by a subtag to indicate that it plans to evaluate its + * body. + */ + public synchronized void subtagSucceeded() { + if (subtagGateClosed) { + throw new IllegalStateException( + Resources.getMessage("CHOOSE_EXCLUSIVITY")); + } + subtagGateClosed = true; + } + + + //********************************************************************* + // Tag logic + + // always include body + + @Override + public int doStartTag() throws JspException { + subtagGateClosed = false; // when we start, no children have run + return EVAL_BODY_INCLUDE; + } + + + //********************************************************************* + // Private utility methods + + private void init() { + subtagGateClosed = false; // reset flag + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/DeclareTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/DeclareTag.java new file mode 100644 index 000000000..3cc25b46e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/DeclareTag.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

Tag handler for <declaregt; in JSTL. This tag handler is + * essentially a runtime no-op as far as tag logic is concerned; the + * only important functionality of the tag is to expose a scripting + * variable for an existing scoped attribute.

+ * + * @author Shawn Bayern + */ + +public class DeclareTag extends TagSupport { + + /* + * We're not identical to TagSupport only because we need to + * accept an additional "type" attribute. + */ + + public void setType(String x) { + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java new file mode 100644 index 000000000..fd5edbcff --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForEachSupport.java @@ -0,0 +1,237 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.IndexedValueExpression; +import jakarta.servlet.jsp.jstl.core.IteratedExpression; +import jakarta.servlet.jsp.jstl.core.IteratedValueExpression; +import jakarta.servlet.jsp.jstl.core.LoopTagSupport; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Support for tag handlers for <forEach>, the core iteration + * tag in JSTL 1.0. This class extends LoopTagSupport and provides + * ForEach-specific functionality. The rtexprvalue library and the + * expression-evaluating library each have handlers that extend this + * class.

+ *

Localized here is the logic for handling the veritable smorgasbord + * of types supported by <forEach>, including arrays, + * Collections, and others. To see how the actual iteration is controlled, + * review the jakarta.servlet.jsp.jstl.core.LoopTagSupport class instead. + *

+ * + * @author Shawn Bayern + * @see jakarta.servlet.jsp.jstl.core.LoopTagSupport + */ +public abstract class ForEachSupport extends LoopTagSupport { + protected Iterator items; // our 'digested' items + protected Object rawItems; // our 'raw' items + + @Override + protected void prepare() throws JspTagException { + // produce the right sort of ForEachIterator + if (rawItems == null) { + // if no items were specified, iterate from begin to end + items = new ToEndIterator(end); + } else if (rawItems instanceof ValueExpression) { + deferredExpression = (ValueExpression) rawItems; + Object o = deferredExpression.getValue(pageContext.getELContext()); + Iterator iterator = toIterator(o); + if (isIndexed(o)) { + items = new IndexedDeferredIterator(iterator, deferredExpression); + } else { + items = new IteratedDeferredIterator(iterator, new IteratedExpression(deferredExpression, getDelims())); + } + } else { + items = toIterator(rawItems); + } + } + + private Iterator toIterator(Object rawItems) throws JspTagException { + if (rawItems instanceof Collection) { + return ((Collection) rawItems).iterator(); + } else if (rawItems.getClass().isArray()) { + return new ArrayIterator(rawItems); + } else if (rawItems instanceof Iterator) { + return (Iterator) rawItems; + } else if (rawItems instanceof Enumeration) { + return new EnumerationIterator((Enumeration) rawItems); + } else if (rawItems instanceof Map) { + return ((Map) rawItems).entrySet().iterator(); + } else if (rawItems instanceof String) { + return new EnumerationIterator(new StringTokenizer((String) rawItems, ",")); + } else { + throw new JspTagException(Resources.getMessage("FOREACH_BAD_ITEMS")); + } + } + + private boolean isIndexed(Object o) { + return o.getClass().isArray(); + } + + @Override + protected boolean hasNext() throws JspTagException { + return items.hasNext(); + } + + @Override + protected Object next() throws JspTagException { + return items.next(); + } + + @Override + public void release() { + super.release(); + items = null; + rawItems = null; + } + + + /** + * Iterator that simply counts up to 'end.' + * Unlike the previous implementation this does not attempt to pre-allocate an array + * containing all values from 0 to 'end' as that can result in excessive memory allocation + * for large values of 'end.' + * LoopTagSupport calls next() 'begin' times in order to discard the initial values, + * In order to maintain this contract, this implementation always starts at 0. + * Future optimization to skip these redundant calls might be possible. + */ + private static class ToEndIterator extends ReadOnlyIterator { + private final int end; + private int i; + + private ToEndIterator(int end) { + this.end = end; + } + + public boolean hasNext() { + return i <= end; + } + + public Object next() { + if (i <= end) { + return i++; + } else { + throw new NoSuchElementException(); + } + } + } + + /** + * Iterator over an Enumeration. + */ + private static class EnumerationIterator extends ReadOnlyIterator { + private final Enumeration e; + + private EnumerationIterator(Enumeration e) { + this.e = e; + } + + public boolean hasNext() { + return e.hasMoreElements(); + } + + public Object next() { + return e.nextElement(); + } + } + + /** + * Iterator over an array, including arrays of primitive types. + */ + private static class ArrayIterator extends ReadOnlyIterator { + private final Object array; + private final int length; + private int i = 0; + + private ArrayIterator(Object array) { + this.array = array; + length = Array.getLength(array); + } + + public boolean hasNext() { + return i < length; + } + + public Object next() { + try { + return Array.get(array, i++); + } catch (ArrayIndexOutOfBoundsException e) { + throw new NoSuchElementException(); + } + } + } + + private static class IndexedDeferredIterator extends DeferredIterator { + private final ValueExpression itemsValueExpression; + + private IndexedDeferredIterator(Iterator iterator, ValueExpression itemsValueExpression) { + super(iterator); + this.itemsValueExpression = itemsValueExpression; + } + + public Object next() { + iterator.next(); + return new IndexedValueExpression(itemsValueExpression, currentIndex++); + } + } + + private static class IteratedDeferredIterator extends DeferredIterator { + private final IteratedExpression itemsValueIteratedExpression; + + private IteratedDeferredIterator(Iterator iterator, IteratedExpression itemsValueIteratedExpression) { + super(iterator); + this.itemsValueIteratedExpression = itemsValueIteratedExpression; + } + + public Object next() { + iterator.next(); + return new IteratedValueExpression(itemsValueIteratedExpression, currentIndex++); + } + } + + private abstract static class DeferredIterator extends ReadOnlyIterator { + protected final Iterator iterator; + protected int currentIndex = 0; + + protected DeferredIterator(Iterator iterator) { + this.iterator = iterator; + } + + public boolean hasNext() { + return iterator.hasNext(); + } + } + + private abstract static class ReadOnlyIterator implements Iterator { + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java new file mode 100644 index 000000000..4b5fc469d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ForTokensSupport.java @@ -0,0 +1,126 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.util.StringTokenizer; + +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.IteratedExpression; +import jakarta.servlet.jsp.jstl.core.IteratedValueExpression; +import jakarta.servlet.jsp.jstl.core.LoopTagSupport; + +/** + *

Support for tag handlers for <forTokens>, the tokenizing + * iteration tag in JSTL 1.0. This class extends LoopTagSupport and + * provides ForTokens-specific functionality. The rtexprvalue and + * expression-evaluating libraries each have handlers that extend this + * class.

+ * + * @author Shawn Bayern + * @see jakarta.servlet.jsp.jstl.core.LoopTagSupport + */ + +public abstract class ForTokensSupport extends LoopTagSupport { + + //********************************************************************* + // Implementation overview + + /* + * This handler simply constructs a StringTokenizer based on its input + * and relays tokens to the iteration implementation that it inherits. + * The 'items' and 'delims' attributes are expected to be provided by + * a subtag (presumably in the rtexprvalue or expression-evaluating + * versions of the JSTL library). + */ + + + //********************************************************************* + // ForEachTokens-specific state (protected) + + protected Object items; // 'items' attribute + protected String delims; // 'delims' attribute + protected StringTokenizer st; // digested tokenizer + protected int currentIndex; + private IteratedExpression itemsValueIteratedExpression; + + + //********************************************************************* + // Iteration control methods + + /* + * These just create and use a StringTokenizer. + * We inherit semantics and Javadoc from LoopTagSupport. + */ + + @Override + protected void prepare() throws JspTagException { + if (items instanceof ValueExpression) { + deferredExpression = (ValueExpression) items; + itemsValueIteratedExpression = new IteratedExpression(deferredExpression, getDelims()); + currentIndex = 0; + + Object originalValue = deferredExpression.getValue(pageContext.getELContext()); + if (originalValue instanceof String) { + st = new StringTokenizer((String) originalValue, delims); + } else { + throw new JspTagException(); + } + } else { + st = new StringTokenizer((String) items, delims); + } + } + + @Override + protected boolean hasNext() throws JspTagException { + return st.hasMoreElements(); + } + + @Override + protected Object next() throws JspTagException { + if (deferredExpression != null) { + st.nextElement(); + return new IteratedValueExpression(itemsValueIteratedExpression, currentIndex++); + } else { + return st.nextElement(); + } + } + + + //********************************************************************* + // Tag logic and lifecycle management + + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + items = delims = null; + st = null; + } + + /** + * Get the delimiter for string tokens. Used only for constructing + * the deferred expression for it. + */ + @Override + protected String getDelims() { + return delims; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ImportSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ImportSupport.java new file mode 100644 index 000000000..d4c5cb210 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ImportSupport.java @@ -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.taglibs.standard.tag.common.core; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.util.UrlUtil; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.Locale; + +/** + *

Support for tag handlers for <import>, the general-purpose + * text-importing mechanism for JSTL 1.0. The rtexprvalue and expression- + * evaluating libraries each have handlers that extend this class.

+ * + * @author Shawn Bayern + */ + +public abstract class ImportSupport extends BodyTagSupport + implements TryCatchFinally, ParamParent { + + //********************************************************************* + // Public constants + + /** + * Default character encoding for response. + */ + public static final String DEFAULT_ENCODING = "ISO-8859-1"; + + //********************************************************************* + // Protected state + + protected String url; // 'url' attribute + protected String context; // 'context' attribute + protected String charEncoding; // 'charEncoding' attrib. + + //********************************************************************* + // Private state (implementation details) + + private String var; // 'var' attribute + private int scope; // processed 'scope' attribute + private String varReader; // 'varReader' attribute + private Reader r; // exposed reader, if relevant + private boolean isAbsoluteUrl; // is our URL absolute? + private ParamSupport.ParamManager params; // parameters + private String urlWithParams; // URL with parameters, if applicable + + //********************************************************************* + // Constructor and initialization + + public ImportSupport() { + super(); + init(); + } + + private void init() { + url = var = varReader = context = charEncoding = urlWithParams = null; + params = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag logic + + // determines what kind of import and variable exposure to perform + + @Override + public int doStartTag() throws JspException { + // Sanity check + if (context != null + && (!context.startsWith("/") || !url.startsWith("/"))) { + throw new JspTagException( + Resources.getMessage("IMPORT_BAD_RELATIVE")); + } + + // reset parameter-related state + urlWithParams = null; + params = new ParamSupport.ParamManager(); + + // check the URL + if (url == null || url.equals("")) { + throw new NullAttributeException("import", "url"); + } + + // Record whether our URL is absolute or relative + isAbsoluteUrl = UrlUtil.isAbsoluteUrl(url); + + try { + // If we need to expose a Reader, we've got to do it right away + if (varReader != null) { + r = acquireReader(); + pageContext.setAttribute(varReader, r); + } + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } + + return EVAL_BODY_INCLUDE; + } + + // manages connections as necessary (creating or destroying) + + @Override + public int doEndTag() throws JspException { + try { + // If we didn't expose a Reader earlier... + if (varReader == null) { + // ... store it in 'var', if available ... + if (var != null) { + pageContext.setAttribute(var, acquireString(), scope); + } + // ... or simply output it, if we have nowhere to expose it + else { + pageContext.getOut().print(acquireString()); + } + } + return EVAL_PAGE; + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } + } + + // simply rethrows its exception + + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + // cleans up if appropriate + + public void doFinally() { + try { + // If we exposed a Reader in doStartTag(), close it. + if (varReader != null) { + // 'r' can be null if an exception was thrown... + if (r != null) { + r.close(); + } + pageContext.removeAttribute(varReader, PageContext.PAGE_SCOPE); + } + } catch (IOException ex) { + // ignore it; close() failed, but there's nothing more we can do + } + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + super.release(); + } + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setVarReader(String varReader) { + this.varReader = varReader; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Collaboration with subtags + + // inherit Javadoc + + public void addParameter(String name, String value) { + params.addParameter(name, value); + } + + //********************************************************************* + // Actual URL importation logic + + /* + * Overall strategy: we have two entry points, acquireString() and + * acquireReader(). The latter passes data through unbuffered if + * possible (but note that it is not always possible -- specifically + * for cases where we must use the RequestDispatcher. The remaining + * methods handle the common.core logic of loading either a URL or a local + * resource. + * + * We consider the 'natural' form of absolute URLs to be Readers and + * relative URLs to be Strings. Thus, to avoid doing extra work, + * acquireString() and acquireReader() delegate to one another as + * appropriate. (Perhaps I could have spelled things out more clearly, + * but I thought this implementation was instructive, not to mention + * somewhat cute...) + */ + + private String acquireString() throws IOException, JspException { + if (isAbsoluteUrl) { + // for absolute URLs, delegate to our peer + BufferedReader r = new BufferedReader(acquireReader()); + StringBuilder sb = new StringBuilder(); + int i; + + // under JIT, testing seems to show this simple loop is as fast + // as any of the alternatives + while ((i = r.read()) != -1) { + sb.append((char) i); + } + + return sb.toString(); + } else { + // handle relative URLs ourselves + + // URL is relative, so we must be an HTTP request + if (!(pageContext.getRequest() instanceof HttpServletRequest + && pageContext.getResponse() instanceof HttpServletResponse)) { + throw new JspTagException( + Resources.getMessage("IMPORT_REL_WITHOUT_HTTP")); + } + + // retrieve an appropriate ServletContext + ServletContext c = null; + String targetUrl = targetUrl(); + if (context != null) { + c = pageContext.getServletContext().getContext(context); + } else { + c = pageContext.getServletContext(); + + // normalize the URL if we have an HttpServletRequest + if (!targetUrl.startsWith("/")) { + String sp = ((HttpServletRequest) + pageContext.getRequest()).getServletPath(); + targetUrl = sp.substring(0, sp.lastIndexOf('/')) + + '/' + targetUrl; + } + } + + if (c == null) { + throw new JspTagException( + Resources.getMessage( + "IMPORT_REL_WITHOUT_DISPATCHER", context, targetUrl)); + } + + // from this context, get a dispatcher + RequestDispatcher rd = c.getRequestDispatcher(stripSession(targetUrl)); + if (rd == null) { + throw new JspTagException(stripSession(targetUrl)); + } + + // Wrap the response so we capture the capture the output. + // This relies on the underlying container to return content even if this is a HEAD + // request. Some containers (e.g. Tomcat versions without the fix for + // https://bz.apache.org/bugzilla/show_bug.cgi?id=57601 ) may not do that. + ImportResponseWrapper irw = + new ImportResponseWrapper((HttpServletResponse) pageContext.getResponse()); + + // spec mandates specific error handling from include() + try { + rd.include(pageContext.getRequest(), irw); + } catch (IOException | RuntimeException ex) { + throw new JspException(ex); + } catch (ServletException ex) { + Throwable rc = ex.getRootCause(); + while (rc instanceof ServletException) { + rc = ((ServletException) rc).getRootCause(); + } + if (rc == null) { + throw new JspException(ex); + } else { + throw new JspException(rc); + } + } + + // disallow inappropriate response codes per JSTL spec + if (irw.getStatus() < 200 || irw.getStatus() > 299) { + throw new JspTagException(irw.getStatus() + " " + + stripSession(targetUrl)); + } + + // recover the response String from our wrapper + return irw.getString(); + } + } + + private Reader acquireReader() throws IOException, JspException { + if (!isAbsoluteUrl) { + // for relative URLs, delegate to our peer + return new StringReader(acquireString()); + } else { + // absolute URL + String target = targetUrl(); + try { + // handle absolute URLs ourselves, using java.net.URL + URL u = new URL(target); + URLConnection uc = u.openConnection(); + InputStream i = uc.getInputStream(); + + // okay, we've got a stream; encode it appropriately + Reader r = null; + String charSet; + if (charEncoding != null && !charEncoding.equals("")) { + charSet = charEncoding; + } else { + // charSet extracted according to RFC 2045, section 5.1 + String contentType = uc.getContentType(); + if (contentType != null) { + charSet = Util.getContentTypeAttribute(contentType, "charset"); + if (charSet == null) { + charSet = DEFAULT_ENCODING; + } + } else { + charSet = DEFAULT_ENCODING; + } + } + try { + r = new InputStreamReader(i, charSet); + } catch (Exception ex) { + r = new InputStreamReader(i, DEFAULT_ENCODING); + } + + // check response code for HTTP URLs before returning, per spec, + // before returning + if (uc instanceof HttpURLConnection) { + int status = ((HttpURLConnection) uc).getResponseCode(); + if (status < 200 || status > 299) { + throw new JspTagException(status + " " + target); + } + } + + return r; + } catch (IOException ex) { + throw new JspException( + Resources.getMessage("IMPORT_ABS_ERROR", target, ex), ex); + } catch (RuntimeException ex) { // because the spec makes us + throw new JspException( + Resources.getMessage("IMPORT_ABS_ERROR", target, ex), ex); + } + } + } + + /** + * Wraps responses to allow us to retrieve results as Strings. + */ + private class ImportResponseWrapper extends HttpServletResponseWrapper { + + //************************************************************ + // Overview + + /* + * We provide either a Writer or an OutputStream as requested. + * We actually have a true Writer and an OutputStream backing + * both, since we don't want to use a character encoding both + * ways (Writer -> OutputStream -> Writer). So we use no + * encoding at all (as none is relevant) when the target resource + * uses a Writer. And we decode the OutputStream's bytes + * using OUR tag's 'charEncoding' attribute, or ISO-8859-1 + * as the default. We thus ignore setLocale() and setContentType() + * in this wrapper. + * + * In other words, the target's asserted encoding is used + * to convert from a Writer to an OutputStream, which is typically + * the medium through with the target will communicate its + * ultimate response. Since we short-circuit that mechanism + * and read the target's characters directly if they're offered + * as such, we simply ignore the target's encoding assertion. + */ + + //************************************************************ + // Data + + /** + * The Writer we convey. + */ + private StringWriter sw = new StringWriter(); + + /** + * A buffer, alternatively, to accumulate bytes. + */ + private ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + /** + * A ServletOutputStream we convey, tied to this Writer. + */ + private ServletOutputStream sos = new ServletOutputStream() { + + private WriteListener writeListener; + + @Override + public void write(int b) throws IOException { + try { + bos.write(b); + } catch ( Exception e ) { + if(this.writeListener!=null) { + this.writeListener.onError( e ); + } + throw new IOException(e); + } + } + + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener( WriteListener writeListener ) { + this.writeListener = writeListener; + } + }; + + /** + * 'True' if getWriter() was called; false otherwise. + */ + private boolean isWriterUsed; + + /** + * 'True if getOutputStream() was called; false otherwise. + */ + private boolean isStreamUsed; + + /** + * The HTTP status set by the target. + */ + private int status = 200; + + //************************************************************ + // Constructor and methods + + /** + * Constructs a new ImportResponseWrapper. + */ + public ImportResponseWrapper(HttpServletResponse response) { + super(response); + } + + /** + * Returns a Writer designed to buffer the output. + */ + @Override + public PrintWriter getWriter() { + if (isStreamUsed) { + throw new IllegalStateException( + Resources.getMessage("IMPORT_ILLEGAL_STREAM")); + } + isWriterUsed = true; + return new PrintWriter(sw); + } + + /** + * Returns a ServletOutputStream designed to buffer the output. + */ + @Override + public ServletOutputStream getOutputStream() { + if (isWriterUsed) { + throw new IllegalStateException( + Resources.getMessage("IMPORT_ILLEGAL_WRITER")); + } + isStreamUsed = true; + return sos; + } + + /** + * Has no effect. + */ + @Override + public void setContentType(String x) { + // ignore + } + + /** + * Has no effect. + */ + @Override + public void setLocale(Locale x) { + // ignore + } + + @Override + public void setStatus(int status) { + this.status = status; + } + + public int getStatus() { + return status; + } + + /** + * Retrieves the buffered output, using the containing tag's + * 'charEncoding' attribute, or the tag's default encoding, + * if necessary. + */ + // not simply toString() because we need to throw + // UnsupportedEncodingException + public String getString() throws UnsupportedEncodingException { + if (isWriterUsed) { + return sw.toString(); + } else if (isStreamUsed) { + if (charEncoding != null && !charEncoding.equals("")) { + return bos.toString(charEncoding); + } else { + return bos.toString(DEFAULT_ENCODING); + } + } else { + return ""; + } // target didn't write anything + } + } + + //********************************************************************* + // Some private utility methods + + /** + * Returns our URL (potentially with parameters) + */ + private String targetUrl() { + if (urlWithParams == null) { + urlWithParams = params.aggregateParams(url); + } + return urlWithParams; + } + + + //********************************************************************* + // Public utility methods + + /** + * Strips a servlet session ID from url. The session ID + * is encoded as a URL "path parameter" beginning with "jsessionid=". + * We thus remove anything we find between ";jsessionid=" (inclusive) + * and either EOS or a subsequent ';' (exclusive). + */ + public static String stripSession(String url) { + StringBuilder u = new StringBuilder(url); + int sessionStart; + while ((sessionStart = u.toString().indexOf(";jsessionid=")) != -1) { + int sessionEnd = u.toString().indexOf(";", sessionStart + 1); + if (sessionEnd == -1) { + sessionEnd = u.toString().indexOf("?", sessionStart + 1); + } + if (sessionEnd == -1) // still + { + sessionEnd = u.length(); + } + u.delete(sessionStart, sessionEnd); + } + return u.toString(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/NullAttributeException.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/NullAttributeException.java new file mode 100644 index 000000000..e487435e1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/NullAttributeException.java @@ -0,0 +1,43 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

NullAttributeException is a JspTagException that will be thrown + * by the JSTL RI handlers when a tag attribute illegally evaluates + * to 'null'.

+ * + * @author Shawn Bayern + */ + +public class NullAttributeException extends JspTagException { + + /** + * Constructs a NullAttributeException with appropriate information. + * + * @param tag The name of the tag in which the error occurred. + * @param att The attribute value for which the error occurred. + */ + public NullAttributeException(String tag, String att) { + super(Resources.getMessage("TAG_NULL_ATTRIBUTE", att, tag)); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OtherwiseTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OtherwiseTag.java new file mode 100644 index 000000000..3dab1db10 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OtherwiseTag.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.tag.common.core; + + +/** + *

Tag handler for <otherwise> in JSTL.

+ * + * @author Shawn Bayern + */ + +public class OtherwiseTag extends WhenTagSupport { + + /* + * is just a that always tries to evaluate its body + * if it has permission from its parent tag. + */ + + // Don't let the condition stop us... :-) + + @Override + protected boolean condition() { + return true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OutSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OutSupport.java new file mode 100644 index 000000000..411b897b8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/OutSupport.java @@ -0,0 +1,138 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.io.IOException; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.util.EscapeXML; + +/** + *

Support for handlers of the <out> tag, which simply evalutes and + * prints the result of the expression it's passed. If the result is + * null, we print the value of the 'default' attribute's expression or + * our body (which two are mutually exclusive, although this constraint + * is enforced outside this handler, in our TagLibraryValidator).

+ * + * @author Shawn Bayern + */ +public abstract class OutSupport extends BodyTagSupport { + + /* + * (One almost wishes XML and JSP could support "anonymous tags," + * given the amount of trouble we had naming this one!) :-) - sb + */ + + //********************************************************************* + // Internal state + + private Object output; + + //********************************************************************* + // Construction and initialization + + /** + * Constructs a new handler. As with TagSupport, subclasses should + * not provide other constructors and are expected to call the + * superclass constructor. + */ + public OutSupport() { + super(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + output = null; + super.release(); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + + this.bodyContent = null; // clean-up body (just in case container is pooling tag handlers) + + // output value if not null + output = evalValue(); + if (output != null) { + return SKIP_BODY; + } + + // output default if supplied + output = evalDefault(); + if (output != null) { + return SKIP_BODY; + } + + // output body as default + output = ""; // need to reset as doAfterBody will not be called with an empty tag + // TODO: to avoid buffering, can we wrap out in a filter that performs escaping and use EVAL_BODY_INCLUDE? + return EVAL_BODY_BUFFERED; + } + + /** + * Evaluates the "value" attribute. + * + * @return the actual value of the "value" attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract Object evalValue() throws JspException; + + /** + * Evaluates the "default" attribute. + * + * @return the actual value of the "default" attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract String evalDefault() throws JspException; + + /** + * Evaluates the "escapeXml" attribute. + * + * @return the actual value of the "escapeXml" attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract boolean evalEscapeXml() throws JspException; + + @Override + public int doAfterBody() throws JspException { + output = bodyContent.getString().trim(); + return SKIP_BODY; + } + + @Override + public int doEndTag() throws JspException { + try { + boolean escapeXml = evalEscapeXml(); + EscapeXML.emit(output, escapeXml, pageContext.getOut()); + } catch (IOException e) { + throw new JspTagException(e); + } finally { + output = null; + } + return EVAL_PAGE; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamParent.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamParent.java new file mode 100644 index 000000000..2c6abc973 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamParent.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.tag.common.core; + +/** + *

Interface for tag handlers implementing valid parent tags for + * <c:param>.

+ * + * @author Shawn Bayern + */ + +public interface ParamParent { + + /** + * Adds a parameter to this tag's URL. The intent is that the + * <param> subtag will call this to register URL parameters. + * Assumes that 'name' and 'value' are appropriately encoded and do + * not contain any meaningful metacharacters; in order words, escaping + * is the responsibility of the caller. + * + * @see ParamSupport + */ + void addParameter(String name, String value); + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamSupport.java new file mode 100644 index 000000000..83923ad4b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/ParamSupport.java @@ -0,0 +1,196 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.LinkedList; +import java.util.List; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Support for tag handlers for <param>, the URL parameter + * subtag for <import> in JSTL 1.0.

+ * + * @author Shawn Bayern + * @see ParamParent + * @see ImportSupport + */ + +public abstract class ParamSupport extends BodyTagSupport { + + //********************************************************************* + // Protected state + + protected String name; // 'name' attribute + protected String value; // 'value' attribute + + /** + * There used to be an 'encode' attribute; I've left this as a + * vestige in case custom subclasses want to use our functionality + * but NOT encode parameters. + */ + protected boolean encode = true; + + //********************************************************************* + // Constructor and initialization + + public ParamSupport() { + super(); + init(); + } + + private void init() { + name = value = null; + } + + //********************************************************************* + // Tag logic + + // simply send our name and value to our appropriate ancestor + + @Override + public int doEndTag() throws JspException { + Tag t = findAncestorWithClass(this, ParamParent.class); + if (t == null) { + throw new JspTagException( + Resources.getMessage("PARAM_OUTSIDE_PARENT")); + } + + // take no action for null or empty names + if (name == null || name.equals("")) { + return EVAL_PAGE; + } + + // send the parameter to the appropriate ancestor + ParamParent parent = (ParamParent) t; + String value = this.value; + if (value == null) { + if (bodyContent == null || bodyContent.getString() == null) { + value = ""; + } else { + value = bodyContent.getString().trim(); + } + } + if (encode) { + String enc = pageContext.getResponse().getCharacterEncoding(); + try { + parent.addParameter(URLEncoder.encode(name, enc), URLEncoder.encode(value, enc)); + } catch (UnsupportedEncodingException e) { + throw new JspTagException(e); + } + } else { + parent.addParameter(name, value); + } + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + //********************************************************************* + // Support for parameter management + + /** + * Provides support for aggregating query parameters in URLs. + * Specifically, accepts a series of parameters, ensuring that + * - newer parameters will precede older ones in the output URL + * - all supplied parameters precede those in the input URL + */ + public static class ParamManager { + + //********************************* + // Private state + + private List names = new LinkedList(); + private List values = new LinkedList(); + private boolean done = false; + + //********************************* + // Public interface + + /** + * Adds a new parameter to the list. + */ + public void addParameter(String name, String value) { + if (done) { + throw new IllegalStateException(); + } + if (name != null) { + names.add(name); + if (value != null) { + values.add(value); + } else { + values.add(""); + } + } + } + + /** + * Produces a new URL with the stored parameters, in the appropriate + * order. + */ + public String aggregateParams(String url) { + /* + * Since for efficiency we're destructive to the param lists, + * we don't want to run multiple times. + */ + if (done) { + throw new IllegalStateException(); + } + done = true; + + //// reverse the order of our two lists + // Collections.reverse(this.names); + // Collections.reverse(this.values); + + // build a string from the parameter list + StringBuilder newParams = new StringBuilder(); + for (int i = 0; i < names.size(); i++) { + newParams.append(names.get(i)).append('=').append(values.get(i)); + if (i < (names.size() - 1)) { + newParams.append("&"); + } + } + + // insert these parameters into the URL as appropriate + if (newParams.length() > 0) { + int questionMark = url.indexOf('?'); + if (questionMark == -1) { + return (url + "?" + newParams); + } else { + StringBuilder workingUrl = new StringBuilder(url); + workingUrl.insert(questionMark + 1, (newParams + "&")); + return workingUrl.toString(); + } + } else { + return url; + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RedirectSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RedirectSupport.java new file mode 100644 index 000000000..1de44a29e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RedirectSupport.java @@ -0,0 +1,133 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.util.UrlUtil; + +/** + *

Support for tag handlers for <redirect>, JSTL 1.0's tag + * for redirecting to a new URL (with optional query parameters).

+ * + * @author Shawn Bayern + */ + +public abstract class RedirectSupport extends BodyTagSupport + implements ParamParent { + + //********************************************************************* + // Protected state + + protected String url; // 'url' attribute + protected String context; // 'context' attribute + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // processed 'scope' attr + private ParamSupport.ParamManager params; // added parameters + + //********************************************************************* + // Constructor and initialization + + public RedirectSupport() { + super(); + init(); + } + + private void init() { + url = var = null; + params = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Collaboration with subtags + + // inherit Javadoc + + public void addParameter(String name, String value) { + params.addParameter(name, value); + } + + + //********************************************************************* + // Tag logic + + // resets any parameters that might be sent + + @Override + public int doStartTag() throws JspException { + params = new ParamSupport.ParamManager(); + return EVAL_BODY_BUFFERED; + } + + + // gets the right value, encodes it, and prints or stores it + + @Override + public int doEndTag() throws JspException { + String result; // the eventual result + + // add (already encoded) parameters + String baseUrl = UrlSupport.resolveUrl(url, context, pageContext); + result = params.aggregateParams(baseUrl); + + // if the URL is relative, rewrite it with 'redirect' encoding rules + HttpServletResponse response = + ((HttpServletResponse) pageContext.getResponse()); + if (!UrlUtil.isAbsoluteUrl(result)) { + result = response.encodeRedirectURL(result); + } + + // redirect! + try { + response.sendRedirect(result); + } catch (java.io.IOException ex) { + throw new JspTagException(ex.toString(), ex); + } + + return SKIP_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RemoveTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RemoveTag.java new file mode 100644 index 000000000..8528e1b85 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/RemoveTag.java @@ -0,0 +1,101 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

A handler for the <remove> tag, which removes the variable + * identified by 'var' (and 'scope', if present). + * + * @author Shawn Bayern + */ +public class RemoveTag extends TagSupport { + + //********************************************************************* + // Internal state + + private int scope; // tag attribute + private boolean scopeSpecified; // ... by tag attribute + private String var; // tag attribute + + + //********************************************************************* + // Construction and initialization + + /** + * Constructs a new handler. As with TagSupport, subclasses should + * not provide other constructors and are expected to call the + * superclass constructor. + */ + public RemoveTag() { + super(); + init(); + } + + // resets local state + + private void init() { + var = null; + scope = PageContext.PAGE_SCOPE; + scopeSpecified = false; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Tag logic + + // removes the variable (from a specific scope, if specified) + + @Override + public int doEndTag() throws JspException { + if (!scopeSpecified) { + pageContext.removeAttribute(var); + } else { + pageContext.removeAttribute(var, scope); + } + return EVAL_PAGE; + } + + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setVar(String var) { + this.var = var; + } + + // for tag attribute + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + scopeSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/SetSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/SetSupport.java new file mode 100644 index 000000000..7f4c0a806 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/SetSupport.java @@ -0,0 +1,287 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +import jakarta.el.ELContext; +import jakarta.el.ELException; +import jakarta.el.ExpressionFactory; +import jakarta.el.ValueExpression; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.JspApplicationContext; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspFactory; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Support for handlers of the <set> tag.

+ * + * @author Shawn Bayern + */ +public abstract class SetSupport extends BodyTagSupport { + + //********************************************************************* + // Internal state + + private String var; // tag attribute + private String scope; // tag attribute + + //********************************************************************* + // Construction and initialization + + /** + * Constructs a new handler. As with TagSupport, subclasses should + * not provide other constructors and are expected to call the + * superclass constructor. + */ + protected SetSupport() { + super(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + var = null; + scope = null; + super.release(); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + + // decide what to do with the result + if (var != null) { + exportToVariable(getResult()); + } else { + Object target = evalTarget(); + if (target == null) { + // can happen if target evaluates to null + throw new JspTagException(Resources.getMessage("SET_INVALID_TARGET")); + } + + String property = evalProperty(); + if (target instanceof Map) { + exportToMapProperty(target, property, getResult()); + } else { + exportToBeanProperty(target, property, getResult()); + } + } + + return EVAL_PAGE; + } + + Object getResult() throws JspException { + if (isValueSpecified()) { + return evalValue(); + } else if (bodyContent == null) { + return ""; + } else { + String content = bodyContent.getString(); + if (content == null) { + return ""; + } else { + return content.trim(); + } + } + } + + /** + * Indicates that the value attribute was specified. + * If no value attribute is supplied then the value is taken from the tag's body content. + * + * @return true if the value attribute was specified + */ + protected abstract boolean isValueSpecified(); + + /** + * Evaluate the value attribute. + * + * @return the result of evaluating the value attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract Object evalValue() throws JspException; + + /** + * Evaluate the target attribute. + * + * @return the result of evaluating the target attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract Object evalTarget() throws JspException; + + /** + * Evaluate the property attribute. + * + * @return the result of evaluating the property attribute + * @throws JspException if there was a problem evaluating the expression + */ + protected abstract String evalProperty() throws JspException; + + /** + * Export the result into a scoped variable. + * + * @param result the value to export + * @throws JspTagException if there was a problem exporting the result + */ + void exportToVariable(Object result) throws JspTagException { + /* + * Store the result, letting an IllegalArgumentException + * propagate back if the scope is invalid (e.g., if an attempt + * is made to store something in the session without any + * HttpSession existing). + */ + int scopeValue = Util.getScope(scope); + ELContext myELContext = pageContext.getELContext(); + VariableMapper vm = myELContext.getVariableMapper(); + if (result != null) { + // if the result is a ValueExpression we just export to the mapper + if (result instanceof ValueExpression) { + if (scopeValue != PageContext.PAGE_SCOPE) { + throw new JspTagException(Resources.getMessage("SET_BAD_DEFERRED_SCOPE", scope)); + } + vm.setVariable(var, (ValueExpression) result); + } else { + // make sure to remove it from the VariableMapper if we will be setting into page scope + if (scopeValue == PageContext.PAGE_SCOPE && vm.resolveVariable(var) != null) { + vm.setVariable(var, null); + } + pageContext.setAttribute(var, result, scopeValue); + } + } else { + //make sure to remove it from the Var mapper + if (vm.resolveVariable(var) != null) { + vm.setVariable(var, null); + } + if (scope != null) { + pageContext.removeAttribute(var, Util.getScope(scope)); + } else { + pageContext.removeAttribute(var); + } + } + } + + /** + * Export the result into a Map. + * + * @param target the Map to export into + * @param property the key to export into + * @param result the value to export + */ + void exportToMapProperty(Object target, String property, Object result) { + @SuppressWarnings("unchecked") + Map map = (Map) target; + if (result == null) { + map.remove(property); + } else { + map.put(property, result); + } + } + + /** + * Export the result into a bean property. + * + * @param target the bean to export into + * @param property the bean property to set + * @param result the value to export + * @throws JspTagException if there was a problem exporting the result + */ + void exportToBeanProperty(Object target, String property, Object result) throws JspTagException { + PropertyDescriptor[] descriptors; + try { + descriptors = Introspector.getBeanInfo(target.getClass()).getPropertyDescriptors(); + } catch (IntrospectionException ex) { + throw new JspTagException(ex); + } + + for (PropertyDescriptor pd : descriptors) { + if (pd.getName().equals(property)) { + Method m = pd.getWriteMethod(); + if (m == null) { + throw new JspTagException(Resources.getMessage("SET_NO_SETTER_METHOD", property)); + } + try { + m.invoke(target, convertToExpectedType(result, m)); + } catch (ELException|IllegalAccessException|InvocationTargetException ex) { + throw new JspTagException(ex); + } + return; + } + } + throw new JspTagException(Resources.getMessage("SET_INVALID_PROPERTY", property)); + } + + /** + * Convert an object to an expected type of the method parameter according to the conversion + * rules of the Expression Language. + * + * @param value the value to convert + * @param m the setter method + * @return value converted to an instance of the expected type; will be null if value was null + * @throws javax.el.ELException if there was a problem coercing the value + */ + private Object convertToExpectedType(final Object value, Method m) throws ELException { + if (value == null) { + return null; + } + Class expectedType = m.getParameterTypes()[0]; + return getExpressionFactory().coerceToType(value, expectedType); + } + + protected ExpressionFactory getExpressionFactory() { + JspApplicationContext appContext = JspFactory.getDefaultFactory().getJspApplicationContext(pageContext.getServletContext()); + return appContext.getExpressionFactory(); + } + + //********************************************************************* + // Accessor methods + + /** + * 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. + * + * @param var name of the exported scoped variable + */ + public void setVar(String var) { + this.var = var; + } + + /** + * Scope for var. + * Values are verified by TLV. + * + * @param scope the variable scope + */ + public void setScope(String scope) { + this.scope = scope; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/UrlSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/UrlSupport.java new file mode 100644 index 000000000..3ea2bcbbc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/UrlSupport.java @@ -0,0 +1,180 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.util.UrlUtil; + +import java.io.IOException; + +/** + *

Support for tag handlers for <url>, the URL creation + * and rewriting tag in JSTL 1.0.

+ * + * @author Shawn Bayern + */ + +public abstract class UrlSupport extends BodyTagSupport + implements ParamParent { + + //********************************************************************* + // Protected state + + protected String value; // 'value' attribute + protected String context; // 'context' attribute + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // processed 'scope' attr + private ParamSupport.ParamManager params; // added parameters + + //********************************************************************* + // Constructor and initialization + + public UrlSupport() { + super(); + init(); + } + + private void init() { + value = var = null; + params = null; + context = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Collaboration with subtags + + // inherit Javadoc + + public void addParameter(String name, String value) { + params.addParameter(name, value); + } + + + //********************************************************************* + // Tag logic + + // resets any parameters that might be sent + + @Override + public int doStartTag() throws JspException { + params = new ParamSupport.ParamManager(); + return EVAL_BODY_BUFFERED; + } + + + // gets the right value, encodes it, and prints or stores it + + @Override + public int doEndTag() throws JspException { + String result; // the eventual result + + // add (already encoded) parameters + String baseUrl = resolveUrl(value, context, pageContext); + result = params.aggregateParams(baseUrl); + + // if the URL is relative, rewrite it + if (!UrlUtil.isAbsoluteUrl(result)) { + HttpServletResponse response = + ((HttpServletResponse) pageContext.getResponse()); + result = response.encodeURL(result); + } + + // store or print the output + if (var != null) { + pageContext.setAttribute(var, result, scope); + } else { + try { + pageContext.getOut().print(result); + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + //********************************************************************* + // Utility methods + + public static String resolveUrl( + String url, String context, PageContext pageContext) + throws JspException { + // don't touch absolute URLs + if (UrlUtil.isAbsoluteUrl(url)) { + return url; + } + + // normalize relative URLs against a context root + HttpServletRequest request = + (HttpServletRequest) pageContext.getRequest(); + if (context == null) { + if (url.startsWith("/")) { + return (request.getContextPath() + url); + } else { + return url; + } + } else { + if (!context.startsWith("/") || !url.startsWith("/")) { + throw new JspTagException( + Resources.getMessage("IMPORT_BAD_RELATIVE")); + } + if (context.endsWith("/") && url.startsWith("/")) { + // Don't produce string starting with '//', many + // browsers interpret this as host name, not as + // path on same host. Bug 22860 + // Also avoid // inside the url. Bug 34109 + return (context.substring(0, context.length() - 1) + url); + } else { + return (context + url); + } + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/Util.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/Util.java new file mode 100644 index 000000000..25b54ecb3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/Util.java @@ -0,0 +1,176 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.text.DateFormat; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Vector; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Utilities in support of tag-handler classes.

+ * + * @author Jan Luehe + */ +public class Util { + + private static final String REQUEST = "request"; + private static final String SESSION = "session"; + private static final String APPLICATION = "application"; + private static final String DEFAULT = "default"; + private static final String SHORT = "short"; + private static final String MEDIUM = "medium"; + private static final String LONG = "long"; + private static final String FULL = "full"; + + /* + * Converts the given string description of a scope to the corresponding + * PageContext constant. + * + * The validity of the given scope has already been checked by the + * appropriate TLV. + * + * @param scope String description of scope + * + * @return PageContext constant corresponding to given scope description + */ + + public static int getScope(String scope) { + int ret = PageContext.PAGE_SCOPE; // default + + if (REQUEST.equalsIgnoreCase(scope)) { + ret = PageContext.REQUEST_SCOPE; + } else if (SESSION.equalsIgnoreCase(scope)) { + ret = PageContext.SESSION_SCOPE; + } else if (APPLICATION.equalsIgnoreCase(scope)) { + ret = PageContext.APPLICATION_SCOPE; + } + + return ret; + } + + /* + * Converts the given string description of a formatting style for + * dates and times to the corresponding java.util.DateFormat constant. + * + * @param style String description of formatting style for dates and times + * @param errCode Error code to throw if given style is invalid + * + * @return java.util.DateFormat constant corresponding to given style + * + * @throws JspException if the given style is invalid + */ + + public static int getStyle(String style, String errCode) + throws JspException { + int ret = DateFormat.DEFAULT; + + if (style != null) { + if (DEFAULT.equalsIgnoreCase(style)) { + ret = DateFormat.DEFAULT; + } else if (SHORT.equalsIgnoreCase(style)) { + ret = DateFormat.SHORT; + } else if (MEDIUM.equalsIgnoreCase(style)) { + ret = DateFormat.MEDIUM; + } else if (LONG.equalsIgnoreCase(style)) { + ret = DateFormat.LONG; + } else if (FULL.equalsIgnoreCase(style)) { + ret = DateFormat.FULL; + } else { + throw new JspException(Resources.getMessage(errCode, style)); + } + } + + return ret; + } + + + /** + * Get the value associated with a content-type attribute. + * Syntax defined in RFC 2045, section 5.1. + */ + public static String getContentTypeAttribute(String input, String name) { + int begin; + int end; + int index = input.toUpperCase().indexOf(name.toUpperCase()); + if (index == -1) { + return null; + } + index = index + name.length(); // positioned after the attribute name + index = input.indexOf('=', index); // positioned at the '=' + if (index == -1) { + return null; + } + index += 1; // positioned after the '=' + input = input.substring(index).trim(); + + if (input.charAt(0) == '"') { + // attribute value is a quoted string + begin = 1; + end = input.indexOf('"', begin); + if (end == -1) { + return null; + } + } else { + begin = 0; + end = input.indexOf(';'); + if (end == -1) { + end = input.indexOf(' '); + } + if (end == -1) { + end = input.length(); + } + } + return input.substring(begin, end).trim(); + } + + /** + * HttpServletRequest.getLocales() returns the server's default locale + * if the request did not specify a preferred language. + * We do not want this behavior, because it prevents us from using + * the fallback locale. + * We therefore need to return an empty Enumeration if no preferred + * locale has been specified. This way, the logic for the fallback + * locale will be able to kick in. + */ + public static Enumeration getRequestLocales(HttpServletRequest request) { + Enumeration values = request.getHeaders("accept-language"); + if (values == null) { + // No header for "accept-language". Simply return + // a new empty enumeration. + // System.out.println("Null accept-language"); + return Collections.emptyEnumeration(); + } else if (values.hasMoreElements()) { + // At least one "accept-language". Simply return + // the enumeration returned by request.getLocales(). + // System.out.println("At least one accept-language"); + return request.getLocales(); + } else { + // No header for "accept-language". Simply return + // the empty enumeration. + // System.out.println("No accept-language"); + return values; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/WhenTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/WhenTagSupport.java new file mode 100644 index 000000000..3f2ca36fb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/core/WhenTagSupport.java @@ -0,0 +1,74 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

WhenTagSupport is an abstract class that facilitates + * implementation of <when>-style tags in both the rtexprvalue + * and expression-evaluating libraries. It also supports + * <otherwise>.

+ *

In particular, this base class does the following:

+ *
    + *
  • overrides ConditionalTagSupport.doStartTag() to implement the + * appropriate semantics of subtags of <choose>
  • + *
+ * + * @author Shawn Bayern + */ +public abstract class WhenTagSupport extends ConditionalTagSupport { + //********************************************************************* + // Implementation of exclusive-conditional behavior + + /* + * Includes its body if condition() evalutes to true AND its parent + * ChooseTag wants it to do so. The condition will not even be + * evaluated if ChooseTag instructs us not to run. + */ + + @Override + public int doStartTag() throws JspException { + + Tag parent; + + // make sure we're contained properly + if (!((parent = getParent()) instanceof ChooseTag)) { + throw new JspTagException( + Resources.getMessage("WHEN_OUTSIDE_CHOOSE")); + } + + // make sure our parent wants us to continue + if (!((ChooseTag) parent).gainPermission()) { + return SKIP_BODY; + } // we've been reeled in + + // handle conditional behavior + if (condition()) { + ((ChooseTag) parent).subtagSucceeded(); + return EVAL_BODY_INCLUDE; + } else { + return SKIP_BODY; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java new file mode 100644 index 000000000..a6b2bd3f3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java @@ -0,0 +1,325 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <bundle>, the resource bundle loading + * tag in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class BundleSupport extends BodyTagSupport { + + + //********************************************************************* + // Private constants + + private static final Locale EMPTY_LOCALE = new Locale("", ""); + + + //********************************************************************* + // Protected state + + protected String basename; // 'basename' attribute + protected String prefix; // 'prefix' attribute + + + //********************************************************************* + // Private state + + private LocalizationContext locCtxt; + + + //********************************************************************* + // Constructor and initialization + + public BundleSupport() { + super(); + init(); + } + + private void init() { + basename = prefix = null; + locCtxt = null; + } + + + //********************************************************************* + // Collaboration with subtags + + public LocalizationContext getLocalizationContext() { + return locCtxt; + } + + public String getPrefix() { + return prefix; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + locCtxt = getLocalizationContext(pageContext, basename); + return EVAL_BODY_INCLUDE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Public utility methods + + /** + * Gets the default I18N localization context. + * + * @param pc Page in which to look up the default I18N localization context + */ + public static LocalizationContext getLocalizationContext(PageContext pc) { + + Object obj = Config.find(pc, Config.FMT_LOCALIZATION_CONTEXT); + if (obj == null) { + return null; + } + + if (obj instanceof LocalizationContext) { + return (LocalizationContext) obj; + } + // localization context is a bundle basename + return getLocalizationContext(pc, (String) obj); + + } + + /** + * Gets the resource bundle with the given base name, whose locale is + * determined as follows: + *

Check if a match exists between the ordered set of preferred + * locales and the available locales, for the given base name. + * The set of preferred locales consists of a single locale + * (if the jakarta.servlet.jsp.jstl.fmt.locale configuration + * setting is present) or is equal to the client's preferred locales + * determined from the client's browser settings. + *

If no match was found in the previous step, check if a match + * exists between the fallback locale (given by the + * jakarta.servlet.jsp.jstl.fmt.fallbackLocale configuration + * setting) and the available locales, for the given base name. + * + * @param pc Page in which the resource bundle with the + * given base name is requested + * @param basename Resource bundle base name + * @return Localization context containing the resource bundle with the + * given base name and the locale that led to the resource bundle match, + * or the empty localization context if no resource bundle match was found + */ + public static LocalizationContext getLocalizationContext(PageContext pc, + String basename) { + LocalizationContext locCtxt = null; + ResourceBundle bundle = null; + + if ((basename == null) || basename.equals("")) { + return new LocalizationContext(); + } + + // Try preferred locales + Locale pref = SetLocaleSupport.getLocale(pc, Config.FMT_LOCALE); + if (pref != null) { + // Preferred locale is application-based + bundle = findMatch(basename, pref); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, pref); + } + } else { + // Preferred locales are browser-based + locCtxt = findMatch(pc, basename); + } + + if (locCtxt == null) { + // No match found with preferred locales, try using fallback locale + pref = SetLocaleSupport.getLocale(pc, Config.FMT_FALLBACK_LOCALE); + if (pref != null) { + bundle = findMatch(basename, pref); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, pref); + } + } + } + + if (locCtxt == null) { + // try using the root resource bundle with the given basename + try { + ClassLoader cl = getClassLoaderCheckingPrivilege(); + bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE, cl); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, null); + } + } catch (MissingResourceException mre) { + // do nothing + } + } + + if (locCtxt != null) { + // set response locale + if (locCtxt.getLocale() != null) { + SetLocaleSupport.setResponseLocale(pc, locCtxt.getLocale()); + } + } else { + // create empty localization context + locCtxt = new LocalizationContext(); + } + + return locCtxt; + } + + + //********************************************************************* + // Private utility methods + + /* + * Determines the client's preferred locales from the request, and compares + * each of the locales (in order of preference) against the available + * locales in order to determine the best matching locale. + * + * @param pageContext the page in which the resource bundle with the + * given base name is requested + * @param basename the resource bundle's base name + * + * @return the localization context containing the resource bundle with + * the given base name and best matching locale, or null if no + * resource bundle match was found + */ + + private static LocalizationContext findMatch(PageContext pageContext, + String basename) { + + // Determine locale from client's browser settings. + + for (Enumeration enum_ = Util.getRequestLocales((HttpServletRequest) pageContext.getRequest()); + enum_.hasMoreElements();) { + Locale pref = (Locale) enum_.nextElement(); + ResourceBundle match = findMatch(basename, pref); + if (match != null) { + return new LocalizationContext(match, pref); + } + } + + return null; + } + + /* + * Gets the resource bundle with the given base name and preferred locale. + * + * This method calls java.util.ResourceBundle.getBundle(), but ignores + * its return value unless its locale represents an exact or language match + * with the given preferred locale. + * + * @param basename the resource bundle base name + * @param pref the preferred locale + * + * @return the requested resource bundle, or null if no resource + * bundle with the given base name exists or if there is no exact- or + * language-match between the preferred locale and the locale of + * the bundle returned by java.util.ResourceBundle.getBundle(). + */ + + private static ResourceBundle findMatch(String basename, Locale pref) { + ResourceBundle match = null; + + try { + ClassLoader cl = getClassLoaderCheckingPrivilege(); + ResourceBundle bundle = ResourceBundle.getBundle(basename, pref, cl); + Locale avail = bundle.getLocale(); + if (pref.equals(avail)) { + // Exact match + match = bundle; + } else { + /* + * We have to make sure that the match we got is for + * the specified locale. The way ResourceBundle.getBundle() + * works, if a match is not found with (1) the specified locale, + * it tries to match with (2) the current default locale as + * returned by Locale.getDefault() or (3) the root resource + * bundle (basename). + * We must ignore any match that could have worked with (2) or (3). + * So if an exact match is not found, we make the following extra + * tests: + * - avail locale must be equal to preferred locale + * - avail country must be empty or equal to preferred country + * (the equality match might have failed on the variant) + */ + if (pref.getLanguage().equals(avail.getLanguage()) + && ("".equals(avail.getCountry()) || pref.getCountry().equals(avail.getCountry()))) { + /* + * Language match. + * By making sure the available locale does not have a + * country and matches the preferred locale's language, we + * rule out "matches" based on the container's default + * locale. For example, if the preferred locale is + * "en-US", the container's default locale is "en-UK", and + * there is a resource bundle (with the requested base + * name) available for "en-UK", ResourceBundle.getBundle() + * will return it, but even though its language matches + * that of the preferred locale, we must ignore it, + * because matches based on the container's default locale + * are not portable across different containers with + * different default locales. + */ + match = bundle; + } + } + } catch (MissingResourceException mre) { + } + + return match; + } + + private static ClassLoader getClassLoaderCheckingPrivilege() { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return Thread.currentThread().getContextClassLoader(); + } + return java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java new file mode 100644 index 000000000..816e0409d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatDateSupport.java @@ -0,0 +1,198 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <formatDate>, the date and time + * formatting tag in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class FormatDateSupport extends TagSupport { + + //********************************************************************* + // Private constants + + private static final String DATE = "date"; + private static final String TIME = "time"; + private static final String DATETIME = "both"; + + //********************************************************************* + // Protected state + + protected Date value; // 'value' attribute + protected String type; // 'type' attribute + protected String pattern; // 'pattern' attribute + protected Object timeZone; // 'timeZone' attribute + protected String dateStyle; // 'dateStyle' attribute + protected String timeStyle; // 'timeStyle' attribute + + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // 'scope' attribute + + + //********************************************************************* + // Constructor and initialization + + public FormatDateSupport() { + super(); + init(); + } + + private void init() { + type = dateStyle = timeStyle = null; + pattern = var = null; + value = null; + timeZone = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + /* + * Formats the given date and time. + */ + + @Override + public int doEndTag() throws JspException { + + String formatted = null; + + if (value == null) { + if (var != null) { + pageContext.removeAttribute(var, scope); + } + return EVAL_PAGE; + } + + // Create formatter + Locale locale = SetLocaleSupport.getFormattingLocale( + pageContext, + this, + true, + DateFormat.getAvailableLocales()); + + if (locale != null) { + DateFormat formatter = createFormatter(locale, pattern); + + // Set time zone + TimeZone tz = null; + if ((timeZone instanceof String) + && timeZone.equals("")) { + timeZone = null; + } + if (timeZone != null) { + if (timeZone instanceof String) { + tz = TimeZone.getTimeZone((String) timeZone); + } else if (timeZone instanceof TimeZone) { + tz = (TimeZone) timeZone; + } else { + throw new JspTagException( + Resources.getMessage("FORMAT_DATE_BAD_TIMEZONE")); + } + } else { + tz = TimeZoneSupport.getTimeZone(pageContext, this); + } + if (tz != null) { + formatter.setTimeZone(tz); + } + formatted = formatter.format(value); + } else { + // no formatting locale available, use Date.toString() + formatted = value.toString(); + } + + if (var != null) { + pageContext.setAttribute(var, formatted, scope); + } else { + try { + pageContext.getOut().print(formatted); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Private utility methods + + private DateFormat createFormatter(Locale loc, String pattern) throws JspException { + // Apply pattern, if present + if (pattern != null) { + return new SimpleDateFormat(pattern, loc); + } + + if ((type == null) || DATE.equalsIgnoreCase(type)) { + int style = Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"); + return DateFormat.getDateInstance(style, loc); + } else if (TIME.equalsIgnoreCase(type)) { + int style = Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"); + return DateFormat.getTimeInstance(style, loc); + } else if (DATETIME.equalsIgnoreCase(type)) { + int style1 = Util.getStyle(dateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"); + int style2 = Util.getStyle(timeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"); + return DateFormat.getDateTimeInstance(style1, style2, loc); + } else { + throw new JspException(Resources.getMessage("FORMAT_DATE_INVALID_TYPE", type)); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatNumberSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatNumberSupport.java new file mode 100644 index 000000000..09b76d639 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/FormatNumberSupport.java @@ -0,0 +1,337 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Currency; +import java.util.Locale; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <formatNumber>, the number + * formatting tag in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class FormatNumberSupport extends BodyTagSupport { + + //********************************************************************* + // Private constants + + private static final Class[] GET_INSTANCE_PARAM_TYPES = + new Class[]{String.class}; + private static final String NUMBER = "number"; + private static final String CURRENCY = "currency"; + private static final String PERCENT = "percent"; + + + //********************************************************************* + // Protected state + + protected Object value; // 'value' attribute + protected boolean valueSpecified; // status + protected String type; // 'type' attribute + protected String pattern; // 'pattern' attribute + protected String currencyCode; // 'currencyCode' attribute + protected String currencySymbol; // 'currencySymbol' attribute + protected boolean isGroupingUsed; // 'groupingUsed' attribute + protected boolean groupingUsedSpecified; + protected int maxIntegerDigits; // 'maxIntegerDigits' attribute + protected boolean maxIntegerDigitsSpecified; + protected int minIntegerDigits; // 'minIntegerDigits' attribute + protected boolean minIntegerDigitsSpecified; + protected int maxFractionDigits; // 'maxFractionDigits' attribute + protected boolean maxFractionDigitsSpecified; + protected int minFractionDigits; // 'minFractionDigits' attribute + protected boolean minFractionDigitsSpecified; + + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // 'scope' attribute + private static Class currencyClass; + + + //********************************************************************* + // Constructor and initialization + + static { + try { + currencyClass = Class.forName("java.util.Currency"); + // container's runtime is J2SE 1.4 or greater + } catch (Exception cnfe) { + } + } + + public FormatNumberSupport() { + super(); + init(); + } + + private void init() { + value = type = null; + valueSpecified = false; + pattern = var = currencyCode = currencySymbol = null; + groupingUsedSpecified = false; + maxIntegerDigitsSpecified = minIntegerDigitsSpecified = false; + maxFractionDigitsSpecified = minFractionDigitsSpecified = false; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + String formatted = null; + Object input = null; + + // determine the input by... + if (valueSpecified) { + // ... reading 'value' attribute + input = value; + } else { + // ... retrieving and trimming our body + if (bodyContent != null && bodyContent.getString() != null) { + input = bodyContent.getString().trim(); + } + } + + if ((input == null) || input.equals("")) { + // Spec says: + // If value is null or empty, remove the scoped variable + // if it is specified (see attributes var and scope). + if (var != null) { + pageContext.removeAttribute(var, scope); + } + return EVAL_PAGE; + } + + /* + * If 'value' is a String, it is first parsed into an instance of + * java.lang.Number + */ + if (input instanceof String) { + try { + if (((String) input).indexOf('.') != -1) { + input = Double.valueOf((String) input); + } else { + input = Long.valueOf((String) input); + } + } catch (NumberFormatException nfe) { + throw new JspException( + Resources.getMessage("FORMAT_NUMBER_PARSE_ERROR", input), + nfe); + } + } + + // Determine formatting locale + Locale loc = SetLocaleSupport.getFormattingLocale( + pageContext, + this, + true, + NumberFormat.getAvailableLocales()); + + if (loc != null) { + // Create formatter + NumberFormat formatter = null; + if ((pattern != null) && !pattern.equals("")) { + // if 'pattern' is specified, 'type' is ignored + DecimalFormatSymbols symbols = new DecimalFormatSymbols(loc); + formatter = new DecimalFormat(pattern, symbols); + } else { + formatter = createFormatter(loc); + } + if (((pattern != null) && !pattern.equals("")) + || CURRENCY.equalsIgnoreCase(type)) { + try { + setCurrency(formatter); + } catch (Exception e) { + throw new JspException( + Resources.getMessage("FORMAT_NUMBER_CURRENCY_ERROR"), + e); + } + } + configureFormatter(formatter); + formatted = formatter.format(input); + } else { + // no formatting locale available, use toString() + formatted = input.toString(); + } + + if (var != null) { + pageContext.setAttribute(var, formatted, scope); + } else { + try { + pageContext.getOut().print(formatted); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Private utility methods + + private NumberFormat createFormatter(Locale loc) throws JspException { + NumberFormat formatter = null; + + if ((type == null) || NUMBER.equalsIgnoreCase(type)) { + formatter = NumberFormat.getNumberInstance(loc); + } else if (CURRENCY.equalsIgnoreCase(type)) { + formatter = NumberFormat.getCurrencyInstance(loc); + } else if (PERCENT.equalsIgnoreCase(type)) { + formatter = NumberFormat.getPercentInstance(loc); + } else { + throw new JspException( + Resources.getMessage("FORMAT_NUMBER_INVALID_TYPE", type)); + } + + return formatter; + } + + /* + * Applies the 'groupingUsed', 'maxIntegerDigits', 'minIntegerDigits', + * 'maxFractionDigits', and 'minFractionDigits' attributes to the given + * formatter. + */ + + private void configureFormatter(NumberFormat formatter) { + if (groupingUsedSpecified) { + formatter.setGroupingUsed(isGroupingUsed); + } + if (maxIntegerDigitsSpecified) { + formatter.setMaximumIntegerDigits(maxIntegerDigits); + } + if (minIntegerDigitsSpecified) { + formatter.setMinimumIntegerDigits(minIntegerDigits); + } + if (maxFractionDigitsSpecified) { + formatter.setMaximumFractionDigits(maxFractionDigits); + } + if (minFractionDigitsSpecified) { + formatter.setMinimumFractionDigits(minFractionDigits); + } + } + + /* + * Override the formatting locale's default currency symbol with the + * specified currency code (specified via the "currencyCode" attribute) or + * currency symbol (specified via the "currencySymbol" attribute). + * + * If both "currencyCode" and "currencySymbol" are present, + * "currencyCode" takes precedence over "currencySymbol" if the + * java.util.Currency class is defined in the container's runtime (that + * is, if the container's runtime is J2SE 1.4 or greater), and + * "currencySymbol" takes precendence over "currencyCode" otherwise. + * + * If only "currencyCode" is given, it is used as a currency symbol if + * java.util.Currency is not defined. + * + * Example: + * + * JDK "currencyCode" "currencySymbol" Currency symbol being displayed + * ----------------------------------------------------------------------- + * all --- --- Locale's default currency symbol + * + * <1.4 EUR --- EUR + * >=1.4 EUR --- Locale's currency symbol for Euro + * + * all --- \u20AC \u20AC + * + * <1.4 EUR \u20AC \u20AC + * >=1.4 EUR \u20AC Locale's currency symbol for Euro + */ + + private void setCurrency(NumberFormat formatter) throws Exception { + String code = null; + String symbol = null; + + if ((currencyCode == null) && (currencySymbol == null)) { + return; + } + + if ((currencyCode != null) && (currencySymbol != null)) { + if (currencyClass != null) { + code = currencyCode; + } else { + symbol = currencySymbol; + } + } else if (currencyCode == null) { + symbol = currencySymbol; + } else { + if (currencyClass != null) { + code = currencyCode; + } else { + symbol = currencyCode; + } + } + + if (code != null) { + Currency currency = Currency.getInstance( code ); + formatter.setCurrency( currency ); + + } else { + /* + * Let potential ClassCastException propagate up (will almost + * never happen) + */ + DecimalFormat df = (DecimalFormat) formatter; + DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); + dfs.setCurrencySymbol(symbol); + df.setDecimalFormatSymbols(dfs); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtil.java new file mode 100644 index 000000000..f857764df --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtil.java @@ -0,0 +1,103 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.util.Locale; + +import org.apache.taglibs.standard.resources.Resources; + +/** + * Utility functions for working with Locales. + * + * This implementation sticks with the Locale parsing rules defined by the JSTL Specification. + * When permitted, this should be updated to use the richer Locale parsing rules provided + * in Java 7 and later. + * + */ +public class LocaleUtil { + private static final char HYPHEN = '-'; + private static final char UNDERSCORE = '_'; + + /** + * Handles Locales that can be passed to tags as instances of String or Locale. + * If the parameter is an instance of Locale, it is simply returned. + * If the parameter is a String and is not empty, then it is parsed to a Locale + * using {@link LocaleUtil#parseLocale(String)}. + * Otherwise null will be returned. + * + * @param stringOrLocale locale represented as an instance of Locale or as a String + * @return the locale represented by the parameter, or null if the parameter is undefined + */ + public static Locale parseLocaleAttributeValue(Object stringOrLocale) { + if (stringOrLocale instanceof Locale) { + return (Locale) stringOrLocale; + } else if (stringOrLocale instanceof String) { + String string = (String) stringOrLocale; + if (string.length() == 0) { + return null; + } else { + return parseLocale(string.trim()); + } + } else { + return null; + } + } + + /** + * See parseLocale(String, String) for details. + */ + public static Locale parseLocale(String locale) { + return parseLocale(locale, null); + } + + /** + * Parses the given locale string into its language and (optionally) + * country components, and returns the corresponding {@link Locale} object. + * + * @param locale the locale string to parse; must not be null or empty + * @param variant the variant + * @return the specified Locale + * @throws IllegalArgumentException if the given locale does not have a + * language component or has an empty country component + */ + public static Locale parseLocale(String locale, String variant) { + + String language; + String country; + int index; + + if (((index = locale.indexOf(HYPHEN)) > -1) || ((index = locale.indexOf(UNDERSCORE)) > -1)) { + if (index == 0) { + throw new IllegalArgumentException(Resources.getMessage("LOCALE_NO_LANGUAGE")); + } else if (index == locale.length() - 1) { + throw new IllegalArgumentException(Resources.getMessage("LOCALE_EMPTY_COUNTRY")); + } + language = locale.substring(0, index); + country = locale.substring(index + 1); + } else { + language = locale; + country = ""; + } + + if (variant != null) { + return new Locale(language, country, variant); + } else { + return new Locale(language, country); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/MessageSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/MessageSupport.java new file mode 100644 index 000000000..4959e894e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/MessageSupport.java @@ -0,0 +1,223 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <message>, the message formatting tag + * in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class MessageSupport extends BodyTagSupport { + + //********************************************************************* + // Public constants + + public static final String UNDEFINED_KEY = "???"; + + + //********************************************************************* + // Protected state + + protected String keyAttrValue; // 'key' attribute value + protected boolean keySpecified; // 'key' attribute specified + protected LocalizationContext bundleAttrValue; // 'bundle' attribute value + protected boolean bundleSpecified; // 'bundle' attribute specified? + + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // 'scope' attribute + private List params; + + + //********************************************************************* + // Constructor and initialization + + public MessageSupport() { + super(); + params = new ArrayList(); + init(); + } + + private void init() { + var = null; + scope = PageContext.PAGE_SCOPE; + keyAttrValue = null; + keySpecified = false; + bundleAttrValue = null; + bundleSpecified = false; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Collaboration with subtags + + /** + * Adds an argument (for parametric replacement) to this tag's message. + * + * @see ParamSupport + */ + public void addParam(Object arg) { + params.add(arg); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + params.clear(); + return EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + + String key = null; + LocalizationContext locCtxt = null; + + // determine the message key by... + if (keySpecified) { + // ... reading 'key' attribute + key = keyAttrValue; + } else { + // ... retrieving and trimming our body + if (bodyContent != null && bodyContent.getString() != null) { + key = bodyContent.getString().trim(); + } + } + + if ((key == null) || key.equals("")) { + try { + pageContext.getOut().print("??????"); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + return EVAL_PAGE; + } + + String prefix = null; + if (!bundleSpecified) { + Tag t = findAncestorWithClass(this, BundleSupport.class); + if (t != null) { + // use resource bundle from parent tag + BundleSupport parent = (BundleSupport) t; + locCtxt = parent.getLocalizationContext(); + prefix = parent.getPrefix(); + } else { + locCtxt = BundleSupport.getLocalizationContext(pageContext); + } + } else { + // localization context taken from 'bundle' attribute + locCtxt = bundleAttrValue; + if (locCtxt.getLocale() != null) { + SetLocaleSupport.setResponseLocale(pageContext, + locCtxt.getLocale()); + } + } + + String message = UNDEFINED_KEY + key + UNDEFINED_KEY; + if (locCtxt != null) { + ResourceBundle bundle = locCtxt.getResourceBundle(); + if (bundle != null) { + try { + // prepend 'prefix' attribute from parent bundle + if (prefix != null) { + key = prefix + key; + } + message = bundle.getString(key); + // Perform parametric replacement if required + if (!params.isEmpty()) { + Object[] messageArgs = params.toArray(); + MessageFormat formatter = new MessageFormat(""); // empty pattern, default Locale + if (locCtxt.getLocale() != null) { + formatter.setLocale(locCtxt.getLocale()); + } else { + // For consistency with the actions, + // we try to get a locale that matches the user's preferences + // as well as the locales supported by 'date' and 'number'. + //System.out.println("LOCALE-LESS LOCCTXT: GETTING FORMATTING LOCALE"); + Locale locale = SetLocaleSupport.getFormattingLocale(pageContext); + //System.out.println("LOCALE: " + locale); + if (locale != null) { + formatter.setLocale(locale); + } + } + formatter.applyPattern(message); + message = formatter.format(messageArgs); + } + } catch (MissingResourceException mre) { + message = UNDEFINED_KEY + key + UNDEFINED_KEY; + } + } + } + + if (var != null) { + pageContext.setAttribute(var, message, scope); + } else { + try { + pageContext.getOut().print(message); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParamSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParamSupport.java new file mode 100644 index 000000000..2543373af --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParamSupport.java @@ -0,0 +1,99 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.resources.Resources; + +/** + * Support for tag handlers for <param>, the message argument + * subtag in JSTL 1.0 which supplies an argument for parametric replacement + * to its parent <message> tag. + * + * @author Jan Luehe + * @see MessageSupport + */ + +public abstract class ParamSupport extends BodyTagSupport { + + //********************************************************************* + // Protected state + + protected Object value; // 'value' attribute + protected boolean valueSpecified; // status + + + //********************************************************************* + // Constructor and initialization + + public ParamSupport() { + super(); + init(); + } + + private void init() { + value = null; + valueSpecified = false; + } + + + //********************************************************************* + // Tag logic + + // Supply our value to our parent tag + + @Override + public int doEndTag() throws JspException { + Tag t = findAncestorWithClass(this, MessageSupport.class); + if (t == null) { + throw new JspTagException(Resources.getMessage( + "PARAM_OUTSIDE_MESSAGE")); + } + MessageSupport parent = (MessageSupport) t; + + /* + * Get argument from 'value' attribute or body, as appropriate, and + * add it to enclosing tag, even if it is null or equal + * to "". + */ + Object input = null; + // determine the input by... + if (valueSpecified) { + // ... reading 'value' attribute + input = value; + } else { + // ... retrieving and trimming our body (TLV has ensured that it's + // non-empty) + input = bodyContent.getString().trim(); + } + parent.addParam(input); + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseDateSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseDateSupport.java new file mode 100644 index 000000000..ff0b9e54c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseDateSupport.java @@ -0,0 +1,238 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <parseDate>, the date and time + * parsing tag in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class ParseDateSupport extends BodyTagSupport { + + //********************************************************************* + // Private constants + + private static final String DATE = "date"; + private static final String TIME = "time"; + private static final String DATETIME = "both"; + + + //********************************************************************* + // Protected state + + protected String value; // 'value' attribute + protected boolean valueSpecified; // status + protected String type; // 'type' attribute + protected String pattern; // 'pattern' attribute + protected Object timeZone; // 'timeZone' attribute + protected Locale parseLocale; // 'parseLocale' attribute + protected String dateStyle; // 'dateStyle' attribute + protected String timeStyle; // 'timeStyle' attribute + + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // 'scope' attribute + + + //********************************************************************* + // Constructor and initialization + + public ParseDateSupport() { + super(); + init(); + } + + private void init() { + type = dateStyle = timeStyle = null; + value = pattern = var = null; + valueSpecified = false; + timeZone = null; + scope = PageContext.PAGE_SCOPE; + parseLocale = null; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + + String input = null; + + // determine the input by... + if (valueSpecified) { + // ... reading 'value' attribute + input = value; + } else { + // ... retrieving and trimming our body + if (bodyContent != null && bodyContent.getString() != null) { + input = bodyContent.getString().trim(); + } + } + + if ((input == null) || input.equals("")) { + if (var != null) { + pageContext.removeAttribute(var, scope); + } + return EVAL_PAGE; + } + + /* + * Set up parsing locale: Use locale specified via the 'parseLocale' + * attribute (if present), or else determine page's locale. + */ + Locale locale = parseLocale; + if (locale == null) { + locale = SetLocaleSupport.getFormattingLocale( + pageContext, + this, + false, + DateFormat.getAvailableLocales()); + } + if (locale == null) { + throw new JspException( + Resources.getMessage("PARSE_DATE_NO_PARSE_LOCALE")); + } + + // Create parser + DateFormat parser = createParser(locale); + + // Apply pattern, if present + if (pattern != null) { + try { + ((SimpleDateFormat) parser).applyPattern(pattern); + } catch (ClassCastException cce) { + parser = new SimpleDateFormat(pattern, locale); + } + } + + // Set time zone + TimeZone tz = null; + if ((timeZone instanceof String) && ((String) timeZone).equals("")) { + timeZone = null; + } + if (timeZone != null) { + if (timeZone instanceof String) { + tz = TimeZone.getTimeZone((String) timeZone); + } else if (timeZone instanceof TimeZone) { + tz = (TimeZone) timeZone; + } else { + throw new JspException( + Resources.getMessage("PARSE_DATE_BAD_TIMEZONE")); + } + } else { + tz = TimeZoneSupport.getTimeZone(pageContext, this); + } + if (tz != null) { + parser.setTimeZone(tz); + } + + // Parse date + Date parsed = null; + try { + parsed = parser.parse(input); + } catch (ParseException pe) { + throw new JspException( + Resources.getMessage("PARSE_DATE_PARSE_ERROR", input), + pe); + } + + if (var != null) { + pageContext.setAttribute(var, parsed, scope); + } else { + try { + pageContext.getOut().print(parsed); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Private utility methods + + private DateFormat createParser(Locale loc) throws JspException { + DateFormat parser = null; + + if ((type == null) || DATE.equalsIgnoreCase(type)) { + parser = DateFormat.getDateInstance( + Util.getStyle(dateStyle, "PARSE_DATE_INVALID_DATE_STYLE"), + loc); + } else if (TIME.equalsIgnoreCase(type)) { + parser = DateFormat.getTimeInstance( + Util.getStyle(timeStyle, "PARSE_DATE_INVALID_TIME_STYLE"), + loc); + } else if (DATETIME.equalsIgnoreCase(type)) { + parser = DateFormat.getDateTimeInstance( + Util.getStyle(dateStyle, "PARSE_DATE_INVALID_DATE_STYLE"), + Util.getStyle(timeStyle, "PARSE_DATE_INVALID_TIME_STYLE"), + loc); + } else { + throw new JspException( + Resources.getMessage("PARSE_DATE_INVALID_TYPE", type)); + } + + parser.setLenient(false); + + return parser; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseNumberSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseNumberSupport.java new file mode 100644 index 000000000..641ae1af8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/ParseNumberSupport.java @@ -0,0 +1,208 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Locale; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <parseNumber>, the number parsing tag + * in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class ParseNumberSupport extends BodyTagSupport { + + //********************************************************************* + // Private constants + + private static final String NUMBER = "number"; + private static final String CURRENCY = "currency"; + private static final String PERCENT = "percent"; + + + //********************************************************************* + // Protected state + + protected String value; // 'value' attribute + protected boolean valueSpecified; // status + protected String type; // 'type' attribute + protected String pattern; // 'pattern' attribute + protected Locale parseLocale; // 'parseLocale' attribute + protected boolean isIntegerOnly; // 'integerOnly' attribute + protected boolean integerOnlySpecified; + + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // 'scope' attribute + + + //********************************************************************* + // Constructor and initialization + + public ParseNumberSupport() { + super(); + init(); + } + + private void init() { + value = type = pattern = var = null; + valueSpecified = false; + parseLocale = null; + integerOnlySpecified = false; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + String input = null; + + // determine the input by... + if (valueSpecified) { + // ... reading 'value' attribute + input = value; + } else { + // ... retrieving and trimming our body + if (bodyContent != null && bodyContent.getString() != null) { + input = bodyContent.getString().trim(); + } + } + + if ((input == null) || input.equals("")) { + if (var != null) { + pageContext.removeAttribute(var, scope); + } + return EVAL_PAGE; + } + + /* + * Set up parsing locale: Use locale specified via the 'parseLocale' + * attribute (if present), or else determine page's locale. + */ + Locale loc = parseLocale; + if (loc == null) { + loc = SetLocaleSupport.getFormattingLocale( + pageContext, + this, + false, + NumberFormat.getAvailableLocales()); + } + if (loc == null) { + throw new JspException( + Resources.getMessage("PARSE_NUMBER_NO_PARSE_LOCALE")); + } + + // Create parser + NumberFormat parser = null; + if ((pattern != null) && !pattern.equals("")) { + // if 'pattern' is specified, 'type' is ignored + DecimalFormatSymbols symbols = new DecimalFormatSymbols(loc); + parser = new DecimalFormat(pattern, symbols); + } else { + parser = createParser(loc); + } + + // Configure parser + if (integerOnlySpecified) { + parser.setParseIntegerOnly(isIntegerOnly); + } + + // Parse number + Number parsed = null; + try { + parsed = parser.parse(input); + } catch (ParseException pe) { + throw new JspException( + Resources.getMessage("PARSE_NUMBER_PARSE_ERROR", input), + pe); + } + + if (var != null) { + pageContext.setAttribute(var, parsed, scope); + } else { + try { + pageContext.getOut().print(parsed); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Private utility methods + + private NumberFormat createParser(Locale loc) throws JspException { + NumberFormat parser = null; + + if ((type == null) || NUMBER.equalsIgnoreCase(type)) { + parser = NumberFormat.getNumberInstance(loc); + } else if (CURRENCY.equalsIgnoreCase(type)) { + parser = NumberFormat.getCurrencyInstance(loc); + } else if (PERCENT.equalsIgnoreCase(type)) { + parser = NumberFormat.getPercentInstance(loc); + } else { + throw new JspException( + Resources.getMessage("PARSE_NUMBER_INVALID_TYPE", + type)); + } + + return parser; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/RequestEncodingSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/RequestEncodingSupport.java new file mode 100644 index 000000000..fa931090e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/RequestEncodingSupport.java @@ -0,0 +1,114 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.UnsupportedEncodingException; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + * Support for tag handlers for <requestEncoding>, the tag for setting + * the request character encoding in JSTL 1.0. + * + * @author Jan Luehe + * @author Pierre Delisle + */ + +public abstract class RequestEncodingSupport extends TagSupport { + + //********************************************************************* + // Package-scoped constants + + static final String REQUEST_CHAR_SET = + "jakarta.servlet.jsp.jstl.fmt.request.charset"; + + + //********************************************************************* + // Private constants + + private static final String DEFAULT_ENCODING = "ISO-8859-1"; + + + //********************************************************************* + // Tag attributes + + protected String value; // 'value' attribute + + + //********************************************************************* + // Derived information + + protected String charEncoding; // derived from 'value' attribute + + + //********************************************************************* + // Constructor and initialization + + public RequestEncodingSupport() { + super(); + init(); + } + + private void init() { + value = null; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + charEncoding = value; + if ((charEncoding == null) + && (pageContext.getRequest().getCharacterEncoding() == null)) { + // Use charset from session-scoped attribute + charEncoding = (String) + pageContext.getAttribute(REQUEST_CHAR_SET, + PageContext.SESSION_SCOPE); + if (charEncoding == null) { + // Use default encoding + charEncoding = DEFAULT_ENCODING; + } + } + + /* + * If char encoding was already set in the request, we don't need to + * set it again. + */ + if (charEncoding != null) { + try { + pageContext.getRequest().setCharacterEncoding(charEncoding); + } catch (UnsupportedEncodingException uee) { + throw new JspTagException(uee.toString(), uee); + } + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetBundleSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetBundleSupport.java new file mode 100644 index 000000000..63b480473 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetBundleSupport.java @@ -0,0 +1,101 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <setBundle>, the JSTL 1.0 tag that loads + * a resource bundle and stores it in a scoped variable. + * + * @author Jan Luehe + */ + +public abstract class SetBundleSupport extends TagSupport { + + + //********************************************************************* + // Protected state + + protected String basename; // 'basename' attribute + + + //********************************************************************* + // Private state + + private int scope; // 'scope' attribute + private String var; // 'var' attribute + + + //********************************************************************* + // Constructor and initialization + + public SetBundleSupport() { + super(); + init(); + } + + private void init() { + basename = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + LocalizationContext locCtxt = + BundleSupport.getLocalizationContext(pageContext, basename); + + if (var != null) { + pageContext.setAttribute(var, locCtxt, scope); + } else { + Config.set(pageContext, Config.FMT_LOCALIZATION_CONTEXT, locCtxt, + scope); + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetLocaleSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetLocaleSupport.java new file mode 100644 index 000000000..fe1f2d774 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetLocaleSupport.java @@ -0,0 +1,401 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; + +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; +import jakarta.servlet.jsp.tagext.Tag; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <setLocale>, the locale setting tag in + * JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class SetLocaleSupport extends TagSupport { + + + //********************************************************************* + // Private constants + + + //********************************************************************* + // Protected state + + protected Object value; // 'value' attribute + protected String variant; // 'variant' attribute + + + //********************************************************************* + // Private state + + private int scope; // 'scope' attribute + + + //********************************************************************* + // Constructor and initialization + + public SetLocaleSupport() { + super(); + init(); + } + + private void init() { + value = variant = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + Locale locale; + + if (value instanceof Locale) { + locale = (Locale) value; + } else if (value instanceof String && !"".equals(((String)value).trim())) { + locale = LocaleUtil.parseLocale((String) value, variant); + } else { + locale = Locale.getDefault(); + } + + Config.set(pageContext, Config.FMT_LOCALE, locale, scope); + setResponseLocale(pageContext, locale); + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Public utility methods + + + //********************************************************************* + // Package-scoped utility methods + + /* + * Stores the given locale in the response object of the given page + * context, and stores the locale's associated charset in the + * jakarta.servlet.jsp.jstl.fmt.request.charset session attribute, which + * may be used by the action in a page invoked by a + * form included in the response to set the request charset to the same as + * the response charset (this makes it possible for the container to + * decode the form parameter values properly, since browsers typically + * encode form field values using the response's charset). + * + * @param pageContext the page context whose response object is assigned + * the given locale + * @param locale the response locale + */ + + static void setResponseLocale(PageContext pc, Locale locale) { + // set response locale + ServletResponse response = pc.getResponse(); + response.setLocale(locale); + + // get response character encoding and store it in session attribute + if (pc.getSession() != null) { + try { + pc.setAttribute(RequestEncodingSupport.REQUEST_CHAR_SET, + response.getCharacterEncoding(), + PageContext.SESSION_SCOPE); + } catch (IllegalStateException ex) { + } // invalidated session ignored + } + } + + /* + * Returns the formatting locale to use with the given formatting action + * in the given page. + * + * @param pc The page context containing the formatting action + * @param fromTag The formatting action + * @param format true if the formatting action is of type + * (as opposed to ), and false otherwise + * (if set to true, the formatting locale that is returned by + * this method is used to set the response locale). + * + * @param avail the array of available locales + * + * @return the formatting locale to use + */ + + static Locale getFormattingLocale(PageContext pc, + Tag fromTag, + boolean format, + Locale[] avail) { + + LocalizationContext locCtxt; + + // Get formatting locale from enclosing + Tag parent = findAncestorWithClass(fromTag, BundleSupport.class); + if (parent != null) { + /* + * use locale from localization context established by parent + * action, unless that locale is null + */ + locCtxt = ((BundleSupport) parent).getLocalizationContext(); + if (locCtxt.getLocale() != null) { + if (format) { + setResponseLocale(pc, locCtxt.getLocale()); + } + return locCtxt.getLocale(); + } + } + + // Use locale from default I18N localization context, unless it is null + if ((locCtxt = BundleSupport.getLocalizationContext(pc)) != null) { + if (locCtxt.getLocale() != null) { + if (format) { + setResponseLocale(pc, locCtxt.getLocale()); + } + return locCtxt.getLocale(); + } + } + + /* + * Establish formatting locale by comparing the preferred locales + * (in order of preference) against the available formatting + * locales, and determining the best matching locale. + */ + Locale match; + Locale pref = getLocale(pc, Config.FMT_LOCALE); + if (pref != null) { + // Preferred locale is application-based + match = findFormattingMatch(pref, avail); + } else { + // Preferred locales are browser-based + match = findFormattingMatch(pc, avail); + } + if (match == null) { + //Use fallback locale. + pref = getLocale(pc, Config.FMT_FALLBACK_LOCALE); + if (pref != null) { + match = findFormattingMatch(pref, avail); + } + } + if (format && (match != null)) { + setResponseLocale(pc, match); + } + + return match; + } + + /** + * Setup the available formatting locales that will be used + * by getFormattingLocale(PageContext). + */ + static Locale[] availableFormattingLocales; + + static { + Locale[] dateLocales = DateFormat.getAvailableLocales(); + Locale[] numberLocales = NumberFormat.getAvailableLocales(); + List locales = new ArrayList(dateLocales.length); + for (Locale dateLocale : dateLocales) { + for (Locale numberLocale : numberLocales) { + if (dateLocale.equals(numberLocale)) { + locales.add(dateLocale); + break; + } + } + } + availableFormattingLocales = locales.toArray(new Locale[locales.size()]); + } + + /* + * Returns the formatting locale to use when is used + * with a locale-less localization context. + * + * @param pc The page context containing the formatting action + * @return the formatting locale to use + */ + + static Locale getFormattingLocale(PageContext pc) { + /* + * Establish formatting locale by comparing the preferred locales + * (in order of preference) against the available formatting + * locales, and determining the best matching locale. + */ + Locale match; + Locale pref = getLocale(pc, Config.FMT_LOCALE); + if (pref != null) { + // Preferred locale is application-based + match = findFormattingMatch(pref, availableFormattingLocales); + } else { + // Preferred locales are browser-based + match = findFormattingMatch(pc, availableFormattingLocales); + } + if (match == null) { + //Use fallback locale. + pref = getLocale(pc, Config.FMT_FALLBACK_LOCALE); + if (pref != null) { + match = findFormattingMatch(pref, availableFormattingLocales); + } + } + if (match != null) { + setResponseLocale(pc, match); + } + + return match; + } + + /* + * Returns the locale specified by the named scoped attribute or context + * configuration parameter. + * + *

The named scoped attribute is searched in the page, request, + * session (if valid), and application scope(s) (in this order). If no such + * attribute exists in any of the scopes, the locale is taken from the + * named context configuration parameter. + * + * @param pageContext the page in which to search for the named scoped + * attribute or context configuration parameter + * @param name the name of the scoped attribute or context configuration + * parameter + * + * @return the locale specified by the named scoped attribute or context + * configuration parameter, or null if no scoped attribute or + * configuration parameter with the given name exists + */ + + static Locale getLocale(PageContext pageContext, String name) { + Locale loc = null; + + Object obj = Config.find(pageContext, name); + if (obj != null) { + if (obj instanceof Locale) { + loc = (Locale) obj; + } else { + loc = LocaleUtil.parseLocale((String) obj); + } + } + + return loc; + } + + + //********************************************************************* + // Private utility methods + + /* + * Determines the client's preferred locales from the request, and compares + * each of the locales (in order of preference) against the available + * locales in order to determine the best matching locale. + * + * @param pageContext Page containing the formatting action + * @param avail Available formatting locales + * + * @return Best matching locale, or null if no match was found + */ + + private static Locale findFormattingMatch(PageContext pageContext, + Locale[] avail) { + Locale match = null; + for (Enumeration enum_ = Util.getRequestLocales((HttpServletRequest) pageContext.getRequest()); + enum_.hasMoreElements();) { + Locale locale = (Locale) enum_.nextElement(); + match = findFormattingMatch(locale, avail); + if (match != null) { + break; + } + } + + return match; + } + + /* + * Returns the best match between the given preferred locale and the + * given available locales. + * + * The best match is given as the first available locale that exactly + * matches the given preferred locale ("exact match"). If no exact match + * exists, the best match is given to an available locale that meets + * the following criteria (in order of priority): + * - available locale's variant is empty and exact match for both + * language and country + * - available locale's variant and country are empty, and exact match + * for language. + * + * @param pref the preferred locale + * @param avail the available formatting locales + * + * @return Available locale that best matches the given preferred locale, + * or null if no match exists + */ + + private static Locale findFormattingMatch(Locale pref, Locale[] avail) { + Locale match = null; + boolean langAndCountryMatch = false; + for (Locale locale : avail) { + if (pref.equals(locale)) { + // Exact match + match = locale; + break; + } else if ( + !"".equals(pref.getVariant()) && + "".equals(locale.getVariant()) && + pref.getLanguage().equals(locale.getLanguage()) && + pref.getCountry().equals(locale.getCountry())) { + // Language and country match; different variant + match = locale; + langAndCountryMatch = true; + } else if ( + !langAndCountryMatch && + pref.getLanguage().equals(locale.getLanguage()) && + ("".equals(locale.getCountry()))) { + // Language match + if (match == null) { + match = locale; + } + } + } + return match; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetTimeZoneSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetTimeZoneSupport.java new file mode 100644 index 000000000..8d39c3585 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/SetTimeZoneSupport.java @@ -0,0 +1,114 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.util.TimeZone; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + * Support for tag handlers for <setTimeZone>, the time zone setting tag + * in JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class SetTimeZoneSupport extends TagSupport { + + + //********************************************************************* + // Protected state + + protected Object value; // 'value' attribute + + + //********************************************************************* + // Private state + + private int scope; // 'scope' attribute + private String var; // 'var' attribute + + + //********************************************************************* + // Constructor and initialization + + public SetTimeZoneSupport() { + super(); + init(); + } + + // resets local state + + private void init() { + value = var = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag attributes known at translation time + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + public void setVar(String var) { + this.var = var; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + TimeZone timeZone = null; + + if (value == null) { + timeZone = TimeZone.getTimeZone("GMT"); + } else if (value instanceof String) { + if (((String) value).trim().equals("")) { + timeZone = TimeZone.getTimeZone("GMT"); + } else { + timeZone = TimeZone.getTimeZone((String) value); + } + } else { + timeZone = (TimeZone) value; + } + + if (var != null) { + pageContext.setAttribute(var, timeZone, scope); + } else { + Config.set(pageContext, Config.FMT_TIME_ZONE, timeZone, scope); + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/TimeZoneSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/TimeZoneSupport.java new file mode 100644 index 000000000..87216476e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/TimeZoneSupport.java @@ -0,0 +1,158 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import java.io.IOException; +import java.util.TimeZone; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +/** + * Support for tag handlers for <timeZone>, the time zone tag in + * JSTL 1.0. + * + * @author Jan Luehe + */ + +public abstract class TimeZoneSupport extends BodyTagSupport { + + + //********************************************************************* + // Protected state + + protected Object value; // 'value' attribute + + + //********************************************************************* + // Private state + + private TimeZone timeZone; + + + //********************************************************************* + // Constructor and initialization + + public TimeZoneSupport() { + super(); + init(); + } + + private void init() { + value = null; + } + + + //********************************************************************* + // Collaboration with subtags + + public TimeZone getTimeZone() { + return timeZone; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + + if (value == null) { + timeZone = TimeZone.getTimeZone("GMT"); + } else if (value instanceof String) { + if (((String) value).trim().equals("")) { + timeZone = TimeZone.getTimeZone("GMT"); + } else { + timeZone = TimeZone.getTimeZone((String) value); + } + } else { + timeZone = (TimeZone) value; + } + + return EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + try { + pageContext.getOut().print(bodyContent.getString()); + } catch (IOException ioe) { + throw new JspTagException(ioe.toString(), ioe); + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Package-scoped utility methods + + /* + * Determines and returns the time zone to be used by the given action. + * + *

If the given action is nested inside a <timeZone> action, + * the time zone is taken from the enclosing <timeZone> action. + * + *

Otherwise, the time zone configuration setting + * jakarta.servlet.jsp.jstl.core.Config.FMT_TIME_ZONE + * is used. + * + * @param pageContext the page containing the action for which the + * time zone needs to be determined + * @param fromTag the action for which the time zone needs to be + * determined + * + * @return the time zone, or null if the given action is not + * nested inside a <timeZone> action and no time zone configuration + * setting exists + */ + + static TimeZone getTimeZone(PageContext pc, Tag fromTag) { + TimeZone tz = null; + + Tag t = findAncestorWithClass(fromTag, TimeZoneSupport.class); + if (t != null) { + // use time zone from parent tag + TimeZoneSupport parent = (TimeZoneSupport) t; + tz = parent.getTimeZone(); + } else { + // get time zone from configuration setting + Object obj = Config.find(pc, Config.FMT_TIME_ZONE); + if (obj != null) { + if (obj instanceof TimeZone) { + tz = (TimeZone) obj; + } else { + tz = TimeZone.getTimeZone((String) obj); + } + } + } + + return tz; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceUtil.java new file mode 100644 index 000000000..d4b67881c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceUtil.java @@ -0,0 +1,139 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; + + +/** + *

A simple DataSource utility for the standard + * DriverManager class. + *

TODO: need to cache DataSource + * + * @author Justyna Horwat + */ +public class DataSourceUtil { + + private static final String ESCAPE = "\\"; + private static final String TOKEN = ","; + + /** + * If dataSource is a String first do JNDI lookup. + * If lookup fails parse String like it was a set of JDBC parameters + * Otherwise check to see if dataSource is a DataSource object and use as + * is + */ + static DataSource getDataSource(Object rawDataSource, PageContext pc) + throws JspException { + DataSource dataSource = null; + + if (rawDataSource == null) { + rawDataSource = Config.find(pc, Config.SQL_DATA_SOURCE); + } + + if (rawDataSource == null) { + return null; + } + + /* + * If the 'dataSource' attribute's value resolves to a String + * after rtexpr/EL evaluation, use the string as JNDI path to + * a DataSource + */ + if (rawDataSource instanceof String) { + try { + Context ctx = new InitialContext(); + // relative to standard JNDI root for J2EE app + Context envCtx = (Context) ctx.lookup("java:comp/env"); + dataSource = (DataSource) envCtx.lookup((String) rawDataSource); + } catch (NamingException ex) { + dataSource = getDataSource((String) rawDataSource); + } + } else if (rawDataSource instanceof DataSource) { + dataSource = (DataSource) rawDataSource; + } else { + throw new JspException( + Resources.getMessage("SQL_DATASOURCE_INVALID_TYPE")); + } + + return dataSource; + } + + /** + * Parse JDBC parameters and setup dataSource appropriately + */ + private static DataSource getDataSource(String params) + throws JspException { + DataSourceWrapper dataSource = new DataSourceWrapper(); + + String[] paramString = new String[4]; + int escCount = 0; + int aryCount = 0; + int begin = 0; + + for (int index = 0; index < params.length(); index++) { + char nextChar = params.charAt(index); + if (TOKEN.indexOf(nextChar) != -1) { + if (escCount == 0) { + paramString[aryCount] = params.substring(begin, index).trim(); + begin = index + 1; + if (++aryCount > 4) { + throw new JspTagException( + Resources.getMessage("JDBC_PARAM_COUNT")); + } + } + } + if (ESCAPE.indexOf(nextChar) != -1) { + escCount++; + } else { + escCount = 0; + } + } + paramString[aryCount] = params.substring(begin).trim(); + + // use the JDBC URL from the parameter string + dataSource.setJdbcURL(paramString[0]); + + // try to load a driver if it's present + if (paramString[1] != null) { + try { + dataSource.setDriverClassName(paramString[1]); + } catch (Exception ex) { + throw new JspTagException( + Resources.getMessage("DRIVER_INVALID_CLASS", + ex.toString()), ex); + } + } + + // set the username and password + dataSource.setUserName(paramString[2]); + dataSource.setPassword(paramString[3]); + + return dataSource; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java new file mode 100644 index 000000000..48aa61629 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DataSourceWrapper.java @@ -0,0 +1,157 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import java.util.logging.Logger; + +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; + + +/** + *

A simple DataSource wrapper for the standard + * DriverManager class. + * + * @author Hans Bergsten + */ +public class DataSourceWrapper implements DataSource { + private Driver driver; + private String jdbcURL; + private String userName; + private String password; + + public void setDriverClassName(String driverClassName) + throws ClassNotFoundException, InstantiationException, + IllegalAccessException { + + //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() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + //done getting classloader + + Object instance = Class.forName(driverClassName, true, cl).newInstance(); + if (instance instanceof Driver) { + driver = (Driver) instance; + } + } + + public void setJdbcURL(String jdbcURL) { + this.jdbcURL = jdbcURL; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public void setPassword(String password) { + this.password = password; + } + + /** + * Returns a Connection using the DriverManager and all + * set properties. + */ + public Connection getConnection() throws SQLException { + Connection conn = null; + if (driver != null) { + Properties props = new Properties(); + if (userName != null) { + props.put("user", userName); + } + if (password != null) { + props.put("password", password); + } + conn = driver.connect(jdbcURL, props); + } + if (conn == null) { + if (userName != null) { + conn = DriverManager.getConnection(jdbcURL, userName, password); + } else { + conn = DriverManager.getConnection(jdbcURL); + } + } + return conn; + } + + /** + * Always throws a SQLException. Username and password are set + * in the constructor and can not be changed. + */ + public Connection getConnection(String username, String password) + throws SQLException { + throw new SQLException(Resources.getMessage("NOT_SUPPORTED")); + } + + /** + * Always throws a SQLException. Not supported. + */ + public int getLoginTimeout() throws SQLException { + throw new SQLException(Resources.getMessage("NOT_SUPPORTED")); + } + + public Logger getParentLogger() { + throw new UnsupportedOperationException(Resources.getMessage("NOT_SUPPORTED")); + } + + /** + * Always throws a SQLException. Not supported. + */ + public PrintWriter getLogWriter() throws SQLException { + throw new SQLException(Resources.getMessage("NOT_SUPPORTED")); + } + + /** + * Always throws a SQLException. Not supported. + */ + public void setLoginTimeout(int seconds) throws SQLException { + throw new SQLException(Resources.getMessage("NOT_SUPPORTED")); + } + + /** + * Always throws a SQLException. Not supported. + */ + 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/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DateParamTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DateParamTagSupport.java new file mode 100644 index 000000000..846aded55 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/DateParamTagSupport.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.sql.SQLExecutionTag; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.resources.Resources; + + +/** + *

Tag handler for <Param> in JSTL, used to set + * parameter values for a SQL statement.

+ * + * @author Justyna Horwat + */ + +public abstract class DateParamTagSupport extends TagSupport { + + //********************************************************************* + // Private constants + + private static final String TIMESTAMP_TYPE = "timestamp"; + private static final String TIME_TYPE = "time"; + private static final String DATE_TYPE = "date"; + + + //********************************************************************* + // Protected state + + protected String type; + protected java.util.Date value; + + + //********************************************************************* + // Constructor + + public DateParamTagSupport() { + super(); + init(); + } + + private void init() { + value = null; + type = null; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + SQLExecutionTag parent = (SQLExecutionTag) + findAncestorWithClass(this, SQLExecutionTag.class); + if (parent == null) { + throw new JspTagException( + Resources.getMessage("SQL_PARAM_OUTSIDE_PARENT")); + } + + if (value != null) { + convertValue(); + } + + parent.addSQLParameter(value); + return EVAL_PAGE; + } + + + //********************************************************************* + // Private utility methods + + private void convertValue() throws JspException { + + if ((type == null) || (type.equalsIgnoreCase(TIMESTAMP_TYPE))) { + if (!(value instanceof java.sql.Timestamp)) { + value = new java.sql.Timestamp(value.getTime()); + } + } else if (type.equalsIgnoreCase(TIME_TYPE)) { + if (!(value instanceof java.sql.Time)) { + value = new java.sql.Time(value.getTime()); + } + } else if (type.equalsIgnoreCase(DATE_TYPE)) { + if (!(value instanceof java.sql.Date)) { + value = new java.sql.Date(value.getTime()); + } + } else { + throw new JspException( + Resources.getMessage("SQL_DATE_PARAM_INVALID_TYPE", type)); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ParamTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ParamTagSupport.java new file mode 100644 index 000000000..1fb7995d2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ParamTagSupport.java @@ -0,0 +1,62 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.sql.SQLExecutionTag; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.resources.Resources; + + +/** + *

Tag handler for <Param> in JSTL, used to set + * parameter values for a SQL statement.

+ * + * @author Hans Bergsten + */ + +public abstract class ParamTagSupport extends BodyTagSupport { + protected Object value; + + //********************************************************************* + // Tag logic + + @Override + public int doEndTag() throws JspException { + SQLExecutionTag parent = (SQLExecutionTag) + findAncestorWithClass(this, SQLExecutionTag.class); + if (parent == null) { + throw new JspTagException( + Resources.getMessage("SQL_PARAM_OUTSIDE_PARENT")); + } + + Object paramValue = null; + if (value != null) { + paramValue = value; + } else if (bodyContent != null) { + paramValue = bodyContent.getString().trim(); + if (((String) paramValue).trim().length() == 0) { + paramValue = null; + } + } + + parent.addSQLParameter(paramValue); + return EVAL_PAGE; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/QueryTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/QueryTagSupport.java new file mode 100644 index 000000000..3641c9567 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/QueryTagSupport.java @@ -0,0 +1,325 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.jstl.sql.Result; +import jakarta.servlet.jsp.jstl.sql.SQLExecutionTag; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + *

Tag handler for <Query> in JSTL. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public abstract class QueryTagSupport extends BodyTagSupport + implements TryCatchFinally, SQLExecutionTag { + + private String var; + private int scope; + + /* + * The following properties take expression values, so the + * setter methods are implemented by the expression type + * specific subclasses. + */ + protected Object rawDataSource; + protected boolean dataSourceSpecified; + protected String sql; + protected int maxRows; + protected boolean maxRowsSpecified; + protected int startRow; + + /* + * Instance variables that are not for attributes + */ + private Connection conn; + private List parameters; + private boolean isPartOfTransaction; + + + //********************************************************************* + // Constructor and initialization + + public QueryTagSupport() { + super(); + init(); + } + + private void init() { + startRow = 0; + maxRows = -1; + maxRowsSpecified = dataSourceSpecified = false; + isPartOfTransaction = false; + conn = null; + rawDataSource = null; + parameters = null; + sql = null; + var = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Accessor methods + + /** + * Setter method for the name of the variable to hold the + * result. + */ + public void setVar(String var) { + this.var = var; + } + + /** + * Setter method for the scope of the variable to hold the + * result. + */ + public void setScope(String scopeName) { + scope = Util.getScope(scopeName); + } + + //********************************************************************* + // Public utility methods + + /** + * Called by nested parameter elements to add PreparedStatement + * parameter values. + */ + public void addSQLParameter(Object o) { + if (parameters == null) { + parameters = new ArrayList(); + } + parameters.add(o); + } + + //********************************************************************* + // Tag logic + + /** + * Prepares for execution by setting the initial state, such as + * getting the Connection + */ + @Override + public int doStartTag() throws JspException { + + if (!maxRowsSpecified) { + Object obj = Config.find(pageContext, Config.SQL_MAX_ROWS); + if (obj != null) { + if (obj instanceof Integer) { + maxRows = ((Integer) obj).intValue(); + } else if (obj instanceof String) { + try { + maxRows = Integer.parseInt((String) obj); + } catch (NumberFormatException nfe) { + throw new JspException(Resources.getMessage("SQL_MAXROWS_PARSE_ERROR", + (String) obj), + nfe); + } + } else { + throw new JspException(Resources.getMessage("SQL_MAXROWS_INVALID")); + } + } + } + + try { + conn = getConnection(); + } catch (SQLException e) { + throw new JspException(sql + ": " + e.getMessage(), e); + } + + return EVAL_BODY_BUFFERED; + } + + /** + *

Execute the SQL statement, set either through the sql + * attribute or as the body, and save the result as a variable + * named by the var attribute in the scope specified + * by the scope attribute, as an object that implements + * the Result interface. + *

The connection used to execute the statement comes either + * from the DataSource specified by the + * dataSource attribute, provided by a parent action + * element, or is retrieved from a JSP scope attribute + * named jakarta.servlet.jstl.sql.dataSource. + */ + @Override + public int doEndTag() throws JspException { + /* + * Use the SQL statement specified by the sql attribute, if any, + * otherwise use the body as the statement. + */ + String sqlStatement = null; + if (sql != null) { + sqlStatement = sql; + } else if (bodyContent != null) { + sqlStatement = bodyContent.getString(); + } + if (sqlStatement == null || sqlStatement.trim().length() == 0) { + throw new JspTagException(Resources.getMessage("SQL_NO_STATEMENT")); + } + /* + * We shouldn't have a negative startRow or illegal maxrows + */ + if ((startRow < 0) || (maxRows < -1)) { + throw new JspException(Resources.getMessage("PARAM_BAD_VALUE")); + } + + Result result = null; + /* + * Note! We must not use the setMaxRows() method on the + * the statement to limit the number of rows, since the + * Result factory must be able to figure out the correct + * value for isLimitedByMaxRows(); there's no way to check + * if it was from the ResultSet. + */ + PreparedStatement ps = null; + ResultSet rs = null; + Throwable queryError = null; + try { + ps = conn.prepareStatement(sqlStatement); + setParameters(ps, parameters); + rs = ps.executeQuery(); + result = new ResultImpl(rs, startRow, maxRows); + } catch (Throwable e) { + queryError = e; + } finally { + // don't blindly throw wrapped rsCloseExc or psCloseExc from + // this block since both close methods must be called and they + // may also "hide" queryError + // it's still possible that some random Throwable (Error or RuntimeException) + // could "escape" and hide queryError + SQLException rsCloseExc = null; + SQLException psCloseExc = null; + if (rs != null) { + try { + rs.close(); + } catch (SQLException sqe) { + rsCloseExc = sqe; + } + } + if (ps != null) { + try { + ps.close(); + } catch (SQLException sqe) { + psCloseExc = sqe; + } + } + + // need to capture info about the possible exceptions + // all exceptions have been saved, so this logic can be easily changed + if (queryError != null) { + // ignore rsCloseExc and psCloseExc + throw new JspException(sqlStatement + ": " + queryError.getMessage(), queryError); + } else if (rsCloseExc != null) { + // ignore psCloseExc (could add psCloseExec to end of "chain") + throw new JspException(rsCloseExc.getMessage(), rsCloseExc); + } else if (psCloseExc != null) { + throw new JspException(psCloseExc.getMessage(), psCloseExc); + } + } + pageContext.setAttribute(var, result, scope); + return EVAL_PAGE; + } + + /** + * Just rethrows the Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + /** + * Close the Connection, unless this action is used + * as part of a transaction. + */ + public void doFinally() { + if (conn != null && !isPartOfTransaction) { + try { + conn.close(); + } catch (SQLException e) { + } // Not much we can do + } + + conn = null; + parameters = null; + } + + + //********************************************************************* + // Private utility methods + + private Connection getConnection() throws JspException, SQLException { + // Fix: Add all other mechanisms + Connection conn = null; + isPartOfTransaction = false; + + TransactionTagSupport parent = (TransactionTagSupport) findAncestorWithClass(this, TransactionTagSupport.class); + if (parent != null) { + if (dataSourceSpecified) { + throw new JspTagException(Resources.getMessage("ERROR_NESTED_DATASOURCE")); + } + conn = parent.getSharedConnection(); + isPartOfTransaction = true; + } else { + if ((rawDataSource == null) && dataSourceSpecified) { + throw new JspException(Resources.getMessage("SQL_DATASOURCE_NULL")); + } + DataSource dataSource = DataSourceUtil.getDataSource(rawDataSource, + pageContext); + try { + conn = dataSource.getConnection(); + } catch (Exception ex) { + throw new JspException(Resources.getMessage("DATASOURCE_INVALID", + ex.toString())); + } + } + + return conn; + } + + private void setParameters(PreparedStatement ps, List parameters) + throws SQLException { + if (parameters != null) { + for (int i = 0; i < parameters.size(); i++) { + /* The first parameter has index 1. If a null + * is passed to setObject the parameter will be + * set to JDBC null so an explicit call to + * ps.setNull is not required. + */ + ps.setObject(i + 1, parameters.get(i)); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ResultImpl.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ResultImpl.java new file mode 100644 index 000000000..4e68dd206 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/ResultImpl.java @@ -0,0 +1,193 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +import jakarta.servlet.jsp.jstl.sql.Result; + +/** + *

This class creates a cached version of a ResultSet. + * It's represented as a Result implementation, capable of + * returing an array of Row objects containing a Column + * instance for each column in the row.

+ *

Note -- this is a private copy for the RI to avoid making the + * corresponding class in jakarta.servlet.* public.

+ * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public class ResultImpl implements Result { + private List rowMap; + private List rowByIndex; + private String[] columnNames; + private boolean isLimited; + + /** + * Build a Result object from a ResultSet object. + * + * @param rs an open ResultSet, positioned before the first row + * @throws SQLException if a database error occurs + */ + public ResultImpl(ResultSet rs) throws SQLException { + this(rs, -1, -1); + } + + /** + * Build a Result object from a ResultSet object. + * + * @param rs an open ResultSet, positioned before the first row + * @param maxRows query maximum rows limit + * @throws SQLException if a database error occurs + */ + public ResultImpl(ResultSet rs, int maxRows) throws SQLException { + // Matching API in ResultSupport - apologies for the bad + // order of default parameters + this(rs, -1, maxRows); + } + + /** + * This constructor reads the ResultSet and saves a cached + * copy. + * + * @param rs an open ResultSet, positioned before the first + * row + * @param startRow beginning row to be cached + * @param maxRows query maximum rows limit + * @throws SQLException if a database error occurs + */ + public ResultImpl(ResultSet rs, int startRow, int maxRows) + throws SQLException { + rowMap = new ArrayList(); + rowByIndex = new ArrayList(); + + ResultSetMetaData rsmd = rs.getMetaData(); + int noOfColumns = rsmd.getColumnCount(); + + // Create the column name array + columnNames = new String[noOfColumns]; + for (int i = 1; i <= noOfColumns; i++) { + columnNames[i - 1] = rsmd.getColumnName(i); + } + + // Throw away all rows upto startRow + for (int i = 0; i < startRow; i++) { + rs.next(); + } + + // Process the remaining rows upto maxRows + int processedRows = 0; + while (rs.next()) { + if ((maxRows != -1) && (processedRows == maxRows)) { + isLimited = true; + break; + } + Object[] columns = new Object[noOfColumns]; + SortedMap columnMap = + new TreeMap(String.CASE_INSENSITIVE_ORDER); + + // JDBC uses 1 as the lowest index! + for (int i = 1; i <= noOfColumns; i++) { + Object value = rs.getObject(i); + if (rs.wasNull()) { + value = null; + } + columns[i - 1] = value; + columnMap.put(columnNames[i - 1], value); + } + rowMap.add(columnMap); + rowByIndex.add(columns); + processedRows++; + } + } + + /** + * Returns an array of SortedMap objects. The SortedMap + * object key is the ColumnName and the value is the ColumnValue. + * SortedMap was created using the CASE_INSENSITIVE_ORDER + * Comparator so the key is the case insensitive representation + * of the ColumnName. + * + * @return an array of Map, or null if there are no rows + */ + public SortedMap[] getRows() { + if (rowMap == null) { + return null; + } + + //should just be able to return SortedMap[] object + return (SortedMap[]) rowMap.toArray(new SortedMap[0]); + } + + + /** + * Returns an array of Object[] objects. The first index + * designates the Row, the second the Column. The array + * stores the value at the specified row and column. + * + * @return an array of Object[], or null if there are no rows + */ + public Object[][] getRowsByIndex() { + if (rowByIndex == null) { + return null; + } + + //should just be able to return Object[][] object + return (Object[][]) rowByIndex.toArray(new Object[0][0]); + } + + /** + * Returns an array of String objects. The array represents + * the names of the columns arranged in the same order as in + * the getRowsByIndex() method. + * + * @return an array of String[] + */ + public String[] getColumnNames() { + return columnNames; + } + + /** + * Returns the number of rows in the cached ResultSet + * + * @return the number of cached rows, or -1 if the Result could + * not be initialized due to SQLExceptions + */ + public int getRowCount() { + if (rowMap == null) { + return -1; + } + return rowMap.size(); + } + + /** + * Returns true of the query was limited by a maximum row setting + * + * @return true if the query was limited by a MaxRows attribute + */ + public boolean isLimitedByMaxRows() { + return isLimited; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/SetDataSourceTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/SetDataSourceTagSupport.java new file mode 100644 index 000000000..2a179e892 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/SetDataSourceTagSupport.java @@ -0,0 +1,132 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; +import jakarta.servlet.jsp.tagext.TagSupport; +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + + +/** + *

Tag handler for <SetDataSource> in JSTL, used to create + * a simple DataSource for prototyping.

+ * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public class SetDataSourceTagSupport extends TagSupport { + + protected Object dataSource; + protected boolean dataSourceSpecified; + protected String jdbcURL; + protected String driverClassName; + protected String userName; + protected String password; + + private int scope; + private String var; + + + //********************************************************************* + // Constructor and initialization + + public SetDataSourceTagSupport() { + super(); + init(); + } + + private void init() { + dataSource = null; + dataSourceSpecified = false; + jdbcURL = driverClassName = userName = password = null; + var = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Accessor methods + + /** + * Setter method for the scope of the variable to hold the + * result. + */ + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + public void setVar(String var) { + this.var = var; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + DataSource ds; + + if (dataSource != null) { + ds = DataSourceUtil.getDataSource(dataSource, pageContext); + } else { + if (dataSourceSpecified) { + throw new JspException( + Resources.getMessage("SQL_DATASOURCE_NULL")); + } + + DataSourceWrapper dsw = new DataSourceWrapper(); + try { + // set driver class iff provided by the tag + if (driverClassName != null) { + dsw.setDriverClassName(driverClassName); + } + } + catch (Exception e) { + throw new JspTagException( + Resources.getMessage("DRIVER_INVALID_CLASS", + e.toString()), e); + } + dsw.setJdbcURL(jdbcURL); + dsw.setUserName(userName); + dsw.setPassword(password); + ds = (DataSource) dsw; + } + + if (var != null) { + pageContext.setAttribute(var, ds, scope); + } else { + Config.set(pageContext, Config.SQL_DATA_SOURCE, ds, scope); + } + + return SKIP_BODY; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/TransactionTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/TransactionTagSupport.java new file mode 100644 index 000000000..40d58fa9f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/TransactionTagSupport.java @@ -0,0 +1,209 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import java.sql.Connection; +import java.sql.SQLException; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.TagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; + + +/** + *

Tag handler for <Transaction> in JSTL. + * + * @author Hans Bergsten + */ + +public abstract class TransactionTagSupport extends TagSupport + implements TryCatchFinally { + + //********************************************************************* + // Private constants + + private static final String TRANSACTION_READ_COMMITTED + = "read_committed"; + private static final String TRANSACTION_READ_UNCOMMITTED + = "read_uncommitted"; + private static final String TRANSACTION_REPEATABLE_READ + = "repeatable_read"; + private static final String TRANSACTION_SERIALIZABLE + = "serializable"; + + + //********************************************************************* + // Protected state + + protected Object rawDataSource; + protected boolean dataSourceSpecified; + + + //********************************************************************* + // Private state + + private Connection conn; + private int isolation; + private int origIsolation; + + + //********************************************************************* + // Constructor and initialization + + public TransactionTagSupport() { + super(); + conn = null; + dataSourceSpecified = false; + rawDataSource = null; + isolation = Connection.TRANSACTION_NONE; + } + + + //********************************************************************* + // Tag logic + + /** + * Prepares for execution by setting the initial state, such as + * getting the Connection and preparing it for + * the transaction. + */ + @Override + public int doStartTag() throws JspException { + + if ((rawDataSource == null) && dataSourceSpecified) { + throw new JspException( + Resources.getMessage("SQL_DATASOURCE_NULL")); + } + + DataSource dataSource = DataSourceUtil.getDataSource(rawDataSource, + pageContext); + + try { + conn = dataSource.getConnection(); + origIsolation = conn.getTransactionIsolation(); + if (origIsolation == Connection.TRANSACTION_NONE) { + throw new JspTagException( + Resources.getMessage("TRANSACTION_NO_SUPPORT")); + } + if ((isolation != Connection.TRANSACTION_NONE) + && (isolation != origIsolation)) { + conn.setTransactionIsolation(isolation); + } + conn.setAutoCommit(false); + } catch (SQLException e) { + throw new JspTagException( + Resources.getMessage("ERROR_GET_CONNECTION", + e.toString()), e); + } + + return EVAL_BODY_INCLUDE; + } + + /** + * Commits the transaction. + */ + @Override + public int doEndTag() throws JspException { + try { + conn.commit(); + } catch (SQLException e) { + throw new JspTagException( + Resources.getMessage("TRANSACTION_COMMIT_ERROR", + e.toString()), e); + } + return EVAL_PAGE; + } + + /** + * Rollbacks the transaction and rethrows the Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + if (conn != null) { + try { + conn.rollback(); + } catch (SQLException e) { + // Ignore to not hide orignal exception + } + } + throw t; + } + + /** + * Restores the Connection to its initial state and + * closes it. + */ + public void doFinally() { + if (conn != null) { + try { + if ((isolation != Connection.TRANSACTION_NONE) + && (isolation != origIsolation)) { + conn.setTransactionIsolation(origIsolation); + } + conn.setAutoCommit(true); + conn.close(); + } catch (SQLException e) { + // Not much we can do + } + } + conn = null; + isolation = Connection.TRANSACTION_NONE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + dataSourceSpecified = false; + rawDataSource = null; + } + + + //********************************************************************* + // Public utility methods + + /** + * Setter method for the transaction isolation level. + */ + public void setIsolation(String iso) throws JspTagException { + + if (TRANSACTION_READ_COMMITTED.equals(iso)) { + isolation = Connection.TRANSACTION_READ_COMMITTED; + } else if (TRANSACTION_READ_UNCOMMITTED.equals(iso)) { + isolation = Connection.TRANSACTION_READ_UNCOMMITTED; + } else if (TRANSACTION_REPEATABLE_READ.equals(iso)) { + isolation = Connection.TRANSACTION_REPEATABLE_READ; + } else if (TRANSACTION_SERIALIZABLE.equals(iso)) { + isolation = Connection.TRANSACTION_SERIALIZABLE; + } else { + throw new JspTagException( + Resources.getMessage("TRANSACTION_INVALID_ISOLATION")); + } + } + + /** + * Called by nested parameter elements to get a reference to + * the Connection. + */ + public Connection getSharedConnection() { + return conn; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/UpdateTagSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/UpdateTagSupport.java new file mode 100644 index 000000000..8d9e9007a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/sql/UpdateTagSupport.java @@ -0,0 +1,257 @@ +/* + * 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.taglibs.standard.tag.common.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.sql.SQLExecutionTag; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; +import javax.sql.DataSource; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; + +/** + *

Tag handler for <Update> in JSTL. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ + +public abstract class UpdateTagSupport extends BodyTagSupport + implements TryCatchFinally, SQLExecutionTag { + + private String var; + private int scope; + + /* + * The following properties take expression values, so the + * setter methods are implemented by the expression type + * specific subclasses. + */ + protected Object rawDataSource; + protected boolean dataSourceSpecified; + protected String sql; + + /* + * Instance variables that are not for attributes + */ + private Connection conn; + private List parameters; + private boolean isPartOfTransaction; + + + //********************************************************************* + // Constructor and initialization + + public UpdateTagSupport() { + super(); + init(); + } + + private void init() { + rawDataSource = null; + sql = null; + conn = null; + parameters = null; + isPartOfTransaction = dataSourceSpecified = false; + scope = PageContext.PAGE_SCOPE; + var = null; + } + + + //********************************************************************* + // Accessor methods + + /** + * Setter method for the name of the variable to hold the + * result. + */ + public void setVar(String var) { + this.var = var; + } + + /** + * Setter method for the scope of the variable to hold the + * result. + */ + public void setScope(String scopeName) { + scope = Util.getScope(scopeName); + } + + + //********************************************************************* + // Tag logic + + /** + * Prepares for execution by setting the initial state, such as + * getting the Connection + */ + @Override + public int doStartTag() throws JspException { + + try { + conn = getConnection(); + } catch (SQLException e) { + throw new JspException(sql + ": " + e.getMessage(), e); + } + + return EVAL_BODY_BUFFERED; + } + + /** + *

Execute the SQL statement, set either through the sql + * attribute or as the body, and save the result as a variable + * named by the var attribute in the scope specified + * by the scope attribute, as an object that implements + * the Result interface. + *

The connection used to execute the statement comes either + * from the DataSource specified by the + * dataSource attribute, provided by a parent action + * element, or is retrieved from a JSP scope attribute + * named jakarta.servlet.jsp.jstl.sql.dataSource. + */ + @Override + public int doEndTag() throws JspException { + /* + * Use the SQL statement specified by the sql attribute, if any, + * otherwise use the body as the statement. + */ + String sqlStatement = null; + if (sql != null) { + sqlStatement = sql; + } else if (bodyContent != null) { + sqlStatement = bodyContent.getString(); + } + if (sqlStatement == null || sqlStatement.trim().length() == 0) { + throw new JspTagException( + Resources.getMessage("SQL_NO_STATEMENT")); + } + + int result = 0; + try (PreparedStatement ps = conn.prepareStatement(sqlStatement)) { + setParameters(ps, parameters); + result = ps.executeUpdate(); + } + catch (Throwable e) { + throw new JspException(sqlStatement + ": " + e.getMessage(), e); + } + if (var != null) { + pageContext.setAttribute(var, new Integer(result), scope); + } + return EVAL_PAGE; + } + + /** + * Just rethrows the Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + /** + * Close the Connection, unless this action is used + * as part of a transaction. + */ + public void doFinally() { + if (conn != null && !isPartOfTransaction) { + try { + conn.close(); + } catch (SQLException e) { + // Not much we can do + } + } + + parameters = null; + conn = null; + } + + + //********************************************************************* + // Public utility methods + + /** + * Called by nested parameter elements to add PreparedStatement + * parameter values. + */ + public void addSQLParameter(Object o) { + if (parameters == null) { + parameters = new ArrayList(); + } + parameters.add(o); + } + + + //********************************************************************* + // Private utility methods + + private Connection getConnection() throws JspException, SQLException { + // Fix: Add all other mechanisms + Connection conn = null; + isPartOfTransaction = false; + + TransactionTagSupport parent = (TransactionTagSupport) + findAncestorWithClass(this, TransactionTagSupport.class); + if (parent != null) { + if (dataSourceSpecified) { + throw new JspTagException( + Resources.getMessage("ERROR_NESTED_DATASOURCE")); + } + conn = parent.getSharedConnection(); + isPartOfTransaction = true; + } else { + if ((rawDataSource == null) && dataSourceSpecified) { + throw new JspException( + Resources.getMessage("SQL_DATASOURCE_NULL")); + } + DataSource dataSource = DataSourceUtil.getDataSource(rawDataSource, + pageContext); + try { + conn = dataSource.getConnection(); + } catch (Exception ex) { + throw new JspException( + Resources.getMessage("DATASOURCE_INVALID", + ex.toString())); + } + } + + return conn; + } + + private void setParameters(PreparedStatement ps, List parameters) + throws SQLException { + if (parameters != null) { + for (int i = 0; i < parameters.size(); i++) { + /* The first parameter has index 1. If a null + * is passed to setObject the parameter will be + * set to JDBC null so an explicit call to + * ps.setNull is not required. + */ + ps.setObject(i + 1, parameters.get(i)); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java new file mode 100644 index 000000000..445ead226 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ExprSupport.java @@ -0,0 +1,73 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import java.io.IOException; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.TagSupport; +import javax.xml.transform.TransformerException; + +import org.apache.taglibs.standard.util.EscapeXML; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; + +/** + * Tag handler for <out> in JSTL's XML library. + * TODO: should we rename this to OutSupport to match the tag name? + * + * @author Shawn Bayern + */ +public abstract class ExprSupport extends TagSupport { + + private XPath select; + protected boolean escapeXml = true; // tag attribute + + @Override + public void release() { + super.release(); + select = null; + } + + //********************************************************************* + // Tag logic + + // applies XPath expression from 'select' and prints the result + @Override + public int doStartTag() throws JspException { + try { + XPathContext context = XalanUtil.getContext(this, pageContext); + String result = select.execute(context, context.getCurrentNode(), null).str(); + EscapeXML.emit(result, escapeXml, pageContext.getOut()); + return SKIP_BODY; + } catch (IOException ex) { + throw new JspTagException(ex.toString(), ex); + } catch (TransformerException e) { + throw new JspTagException(e); + } + } + + public void setSelect(String select) { + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java new file mode 100644 index 000000000..cc009d29c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ForEachTag.java @@ -0,0 +1,129 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.LoopTagSupport; +import javax.xml.transform.TransformerException; + +import org.apache.xml.dtm.DTMIterator; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XObject; + +/** + * Implementation of <x:forEach> tag using low-level Xalan API. + * + * @author Shawn Bayern + * @see jakarta.servlet.jsp.jstl.core.LoopTagSupport + */ +public class ForEachTag extends LoopTagSupport { + + private XPath select; + private XPathContext context; + + @Override + public void release() { + super.release(); + select = null; + context = null; + } + + @Override + protected void prepare() throws JspTagException { + context = XalanUtil.getContext(this, pageContext); + try { + XObject nodes = select.execute(context, context.getCurrentNode(), null); + + // create an iterator over the returned nodes and push into the context + DTMIterator iterator = nodes.iter(); + context.pushContextNodeList(iterator); + } catch (TransformerException e) { + throw new JspTagException(e); + } + } + + @Override + protected boolean hasNext() throws JspTagException { + DTMIterator iterator = context.getContextNodeList(); + return iterator.getCurrentPos() < iterator.getLength(); + } + + @Override + protected Object next() throws JspTagException { + DTMIterator iterator = context.getContextNodeList(); + int next = iterator.nextNode(); + context.pushCurrentNode(next); + return iterator.getDTM(next).getNode(next); + } + + @Override + public int doAfterBody() throws JspException { + // pop the context node after executing the body + context.popCurrentNode(); + return super.doAfterBody(); + } + + @Override + public void doFinally() { + // context might be null as prepare is not called if end < begin + if (context != null) { + // pop the list of nodes being iterated + context.popContextNodeList(); + context = null; + } + super.doFinally(); + } + + public void setSelect(String select) { + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } + } + + public void setBegin(int begin) throws JspTagException { + this.beginSpecified = true; + this.begin = begin; + validateBegin(); + } + + public void setEnd(int end) throws JspTagException { + this.endSpecified = true; + this.end = end; + validateEnd(); + } + + public void setStep(int step) throws JspTagException { + this.stepSpecified = true; + this.step = step; + validateStep(); + } + + /** + * Return the current XPath context to support expression evaluation in nested tags. + * + * @return the current XPath context + */ + XPathContext getContext() { + return context; + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java new file mode 100644 index 000000000..e4490d4e6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/IfTag.java @@ -0,0 +1,61 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; +import javax.xml.transform.TransformerException; + +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; + +/** + *

Tag handler for <if> in JSTL's XML library.

+ * + * @author Shawn Bayern + */ + +public class IfTag extends ConditionalTagSupport { + + private XPath select; + + + @Override + public void release() { + super.release(); + select = null; + } + + @Override + protected boolean condition() throws JspTagException { + XPathContext context = XalanUtil.getContext(this, pageContext); + try { + return select.bool(context, context.getCurrentNode(), null); + } catch (TransformerException e) { + throw new JspTagException(e); + } + } + + public void setSelect(String select) { + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java new file mode 100644 index 000000000..b9a3121e8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStack.java @@ -0,0 +1,132 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import java.util.HashMap; +import java.util.Map; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.PageContext; +import javax.xml.transform.TransformerException; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.xml.utils.QName; +import org.apache.xpath.VariableStack; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XObject; +import org.apache.xpath.objects.XObjectFactory; + +/** + */ +public class JSTLVariableStack extends VariableStack { + + private static enum Scope { + PARAM, + HEADER, + COOKIE, + INITPARAM, + PAGE, + REQUEST, + SESSION, + APPLICATION + } + + // Prefixes for JSTL implicit variables + private static final String PARAM_PREFIX = "param"; + private static final String HEADER_PREFIX = "header"; + private static final String COOKIE_PREFIX = "cookie"; + private static final String INITPARAM_PREFIX = "initParam"; + private static final String PAGE_PREFIX = "pageScope"; + private static final String REQUEST_PREFIX = "requestScope"; + private static final String SESSION_PREFIX = "sessionScope"; + private static final String APP_PREFIX = "applicationScope"; + + // map prefixes to scopes + private static final Map SCOPES; + static { + SCOPES = new HashMap<>(8); + SCOPES.put(PARAM_PREFIX, Scope.PARAM); + SCOPES.put(HEADER_PREFIX, Scope.HEADER); + SCOPES.put(COOKIE_PREFIX, Scope.COOKIE); + SCOPES.put(INITPARAM_PREFIX, Scope.INITPARAM); + SCOPES.put(PAGE_PREFIX, Scope.PAGE); + SCOPES.put(REQUEST_PREFIX, Scope.REQUEST); + SCOPES.put(SESSION_PREFIX, Scope.SESSION); + SCOPES.put(APP_PREFIX, Scope.APPLICATION); + } + + private final PageContext pageContext; + + public JSTLVariableStack(PageContext pageContext) { + super(2); + this.pageContext = pageContext; + } + + @Override + public XObject getVariableOrParam(XPathContext xctxt, QName qname) throws TransformerException { + String prefix = qname.getNamespaceURI(); + String name = qname.getLocalPart(); + Object value = getValue(prefix, name); + if (value == null) { + StringBuilder var = new StringBuilder(); + var.append('$'); + if (prefix != null) { + var.append(prefix); + var.append(':'); + } + var.append(name); + throw new TransformerException(Resources.getMessage("XPATH_UNABLE_TO_RESOLVE_VARIABLE", var.toString())); + } + return XObjectFactory.create(value, xctxt); + } + + private Object getValue(String prefix, String name) { + if (prefix == null) { + return pageContext.findAttribute(name); + } + Scope scope = SCOPES.get(prefix); + switch (scope) { + case PARAM: + return pageContext.getRequest().getParameter(name); + case HEADER: + return ((HttpServletRequest) pageContext.getRequest()).getHeader(name); + case COOKIE: + Cookie[] cookies = ((HttpServletRequest) pageContext.getRequest()).getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(name)) { + return cookie.getValue(); + } + } + } + return null; + case INITPARAM: + return pageContext.getServletContext().getInitParameter(name); + case PAGE: + return pageContext.getAttribute(name, PageContext.PAGE_SCOPE); + case REQUEST: + return pageContext.getAttribute(name, PageContext.REQUEST_SCOPE); + case SESSION: + return pageContext.getAttribute(name, PageContext.SESSION_SCOPE); + case APPLICATION: + return pageContext.getAttribute(name, PageContext.APPLICATION_SCOPE); + default: + throw new AssertionError(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java new file mode 100644 index 000000000..01eaefc83 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParamSupport.java @@ -0,0 +1,89 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.resources.Resources; + +/** + *

Support for tag handlers for <param>, the XML parameter + * subtag for <transformt<.

+ * + * @author Shawn Bayern + * @see TransformSupport + */ + +public abstract class ParamSupport extends BodyTagSupport { + + //********************************************************************* + // Protected state + + protected String name; // 'name' attribute + protected Object value; // 'value' attribute + + //********************************************************************* + // Constructor and initialization + + public ParamSupport() { + super(); + init(); + } + + private void init() { + name = null; + value = null; + } + + + //********************************************************************* + // Tag logic + + // simply send our name and value to our parent tag + + @Override + public int doEndTag() throws JspException { + Tag t = findAncestorWithClass(this, TransformSupport.class); + if (t == null) { + throw new JspTagException( + Resources.getMessage("PARAM_OUTSIDE_TRANSFORM")); + } + TransformSupport parent = (TransformSupport) t; + + Object value = this.value; + if (value == null) { + if (bodyContent == null || bodyContent.getString() == null) { + value = ""; + } else { + value = bodyContent.getString().trim(); + } + } + parent.addParameter(name, value); + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java new file mode 100644 index 000000000..d3203144a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/ParseSupport.java @@ -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.taglibs.standard.tag.common.xml; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.TransformerHandler; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; +import org.apache.taglibs.standard.util.XmlUtil; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLFilter; +import org.xml.sax.XMLReader; + +/** + *

Support for tag handlers for <parse>, the XML parsing tag.

+ * + * @author Shawn Bayern + */ +public abstract class ParseSupport extends BodyTagSupport { + + //********************************************************************* + // Protected state + + protected Object xml; // 'xml' attribute + protected String systemId; // 'systemId' attribute + protected XMLFilter filter; // 'filter' attribute + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private String varDom; // 'varDom' attribute + private int scope; // processed 'scope' attr + private int scopeDom; // processed 'scopeDom' attr + private XmlUtil.JstlEntityResolver entityResolver; + + + //********************************************************************* + // Constructor and initialization + + public ParseSupport() { + super(); + init(); + } + + private void init() { + var = varDom = null; + xml = null; + systemId = null; + filter = null; + scope = PageContext.PAGE_SCOPE; + scopeDom = PageContext.PAGE_SCOPE; + } + + //********************************************************************* + // Tag logic + + // parse 'source' or body, storing result in 'var' + + @Override + public int doEndTag() throws JspException { + // produce a Document by parsing whatever the attributes tell us to use + Object xmlText = this.xml; + if (xmlText == null) { + // if the attribute was specified, use the body as 'xml' + if (bodyContent != null && bodyContent.getString() != null) { + xmlText = bodyContent.getString().trim(); + } else { + xmlText = ""; + } + } + if (xmlText instanceof String) { + xmlText = new StringReader((String) xmlText); + } + if (!(xmlText instanceof Reader)) { + throw new JspTagException(Resources.getMessage("PARSE_INVALID_SOURCE")); + } + InputSource source = XmlUtil.newInputSource(((Reader) xmlText), systemId); + + Document d; + if (filter != null) { + d = parseInputSourceWithFilter(source, filter); + } else { + d = parseInputSource(source); + } + + // we've got a Document object; store it out as appropriate + // (let any exclusivity or other constraints be enforced by TEI/TLV) + if (var != null) { + pageContext.setAttribute(var, d, scope); + } + if (varDom != null) { + pageContext.setAttribute(varDom, d, scopeDom); + } + + return EVAL_PAGE; + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + init(); + } + + + //********************************************************************* + // Private utility methods + + /** + * Parses the given InputSource after, applying the given XMLFilter. + */ + private Document parseInputSourceWithFilter(InputSource s, XMLFilter f) throws JspException { + try { + XMLReader xr = XmlUtil.newXMLReader(entityResolver); + // (note that we overwrite the filter's parent. this seems + // to be expected usage. we could cache and reset the old + // parent, but you can't setParent(null), so this wouldn't + // be perfect.) + f.setParent(xr); + + TransformerHandler th = XmlUtil.newTransformerHandler(); + Document o = XmlUtil.newEmptyDocument(); + th.setResult(new DOMResult(o)); + f.setContentHandler(th); + + f.parse(s); + return o; + } catch (IOException e) { + throw new JspException(e); + } catch (SAXException|TransformerConfigurationException|ParserConfigurationException e) { + throw new JspException(e); + } + } + + /** + * Parses the given InputSource into a Document. + */ + private Document parseInputSource(InputSource s) throws JspException { + try { + DocumentBuilder db = XmlUtil.newDocumentBuilder(); + db.setEntityResolver(entityResolver); + return db.parse(s); + } catch (SAXException|IOException e) { + throw new JspException(e); + } + } + + @Override + public void setPageContext(PageContext pageContext) { + super.setPageContext(pageContext); + entityResolver = pageContext == null ? null: new XmlUtil.JstlEntityResolver(pageContext); + } + + //********************************************************************* + // Tag attributes + + public void setVar(String var) { + this.var = var; + } + + public void setVarDom(String varDom) { + this.varDom = varDom; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } + + public void setScopeDom(String scopeDom) { + this.scopeDom = Util.getScope(scopeDom); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java new file mode 100644 index 000000000..553ec7f27 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/SetTag.java @@ -0,0 +1,87 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; +import javax.xml.transform.TransformerException; + +import org.apache.taglibs.standard.tag.common.core.Util; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XObject; + +/** + *

Tag handler for <set> in JSTL's XML library.

+ * + * @author Shawn Bayern + */ +public class SetTag extends TagSupport { + + private XPath select; + private String var; + private int scope = PageContext.PAGE_SCOPE; + + //********************************************************************* + // Construction and initialization + + @Override + public void release() { + super.release(); + select = null; + var = null; + } + + //********************************************************************* + // Tag logic + + // applies XPath expression from 'select' and stores the result in 'var' + + @Override + public int doStartTag() throws JspException { + try { + XPathContext context = XalanUtil.getContext(this, pageContext); + XObject result = select.execute(context, context.getCurrentNode(), null); + pageContext.setAttribute(var, XalanUtil.coerceToJava(result), scope); + return SKIP_BODY; + } catch (TransformerException e) { + throw new JspTagException(e); + } + } + + //********************************************************************* + // Attribute accessors + + public void setSelect(String select) { + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } + } + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java new file mode 100644 index 000000000..aeae91b5d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/TransformSupport.java @@ -0,0 +1,262 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import java.io.Reader; +import java.io.StringReader; +import java.util.List; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyTagSupport; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.tag.common.core.Util; +import org.apache.taglibs.standard.util.UnclosableWriter; +import org.apache.taglibs.standard.util.XmlUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +/** + *

Support for tag handlers for <transform>, the XML transformation + * tag.

+ * + * @author Shawn Bayern + */ +public abstract class TransformSupport extends BodyTagSupport { + + //********************************************************************* + // Protected state + + protected Object xml; // attribute + protected boolean xmlSpecified; // true if xml attribute was specified + protected String xmlSystemId; // attribute + protected Object xslt; // attribute + protected String xsltSystemId; // attribute + protected Result result; // attribute + + //********************************************************************* + // Private state + + private String var; // 'var' attribute + private int scope; // processed 'scope' attr + private Transformer t; // actual Transformer + private XmlUtil.JstlEntityResolver entityResolver; + private XmlUtil.JstlUriResolver uriResolver; + + + //********************************************************************* + // Constructor and initialization + + public TransformSupport() { + init(); + } + + private void init() { + xml = xslt = null; + xmlSpecified = false; + xmlSystemId = xsltSystemId = null; + var = null; + result = null; + scope = PageContext.PAGE_SCOPE; + } + + + //********************************************************************* + // Tag logic + + @Override + public int doStartTag() throws JspException { + // set up transformer in the start tag so that nested tags can set parameters directly + if (xslt == null) { + throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_IS_NULL")); + } + + Source source; + try { + if (xslt instanceof Source) { + source = (Source) xslt; + } else if (xslt instanceof String) { + String s = (String) xslt; + s = s.trim(); + if (s.length() == 0) { + throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_IS_EMPTY")); + } + source = XmlUtil.newSAXSource(new StringReader(s), xsltSystemId, entityResolver); + } else if (xslt instanceof Reader) { + source = XmlUtil.newSAXSource((Reader) xslt, xsltSystemId, entityResolver); + } else { + throw new JspTagException(Resources.getMessage("TRANSFORM_XSLT_UNSUPPORTED_TYPE", xslt.getClass())); + } + } catch (SAXException|ParserConfigurationException e) { + throw new JspException(e); + } + + try { + t = XmlUtil.newTransformer(source, uriResolver); + t.setURIResolver(uriResolver); + } catch (TransformerConfigurationException e) { + throw new JspTagException(e); + } + return EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + + try { + Source source = xmlSpecified ? getSourceFromXmlAttribute() : getSourceFromBodyContent(); + + // Conduct the transformation + if (var != null) { + // Save the result to var. + Document d = XmlUtil.newEmptyDocument(); + Result doc = new DOMResult(d); + t.transform(source, doc); + pageContext.setAttribute(var, d, scope); + } else { + // Write to out if result is not specified. + Result out = result; + if (out == null) { + out = new StreamResult(new UnclosableWriter(pageContext.getOut())); + } + t.transform(source, out); + } + return EVAL_PAGE; + } catch (TransformerException|SAXException|ParserConfigurationException e) { + throw new JspException(e); + } finally { + t = null; + } + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + @Override + public void setPageContext(PageContext pageContext) { + super.setPageContext(pageContext); + uriResolver = pageContext == null ? null : new XmlUtil.JstlUriResolver(pageContext); + entityResolver = pageContext == null ? null : new XmlUtil.JstlEntityResolver(pageContext); + } + + + //********************************************************************* + // Public methods for subtags + + /** + * Sets (adds) a transformation parameter on our transformer. + */ + public void addParameter(String name, Object value) { + t.setParameter(name, value); + } + + + //********************************************************************* + // Utility methods + + /** + * Return the Source for a document specified in the "doc" or "xml" attribute. + * + * @return the document Source + * @throws JspTagException if there is a problem with the attribute + */ + Source getSourceFromXmlAttribute() throws JspTagException, SAXException, ParserConfigurationException { + Object xml = this.xml; + if (xml == null) { + throw new JspTagException(Resources.getMessage("TRANSFORM_XML_IS_NULL")); + } + + // other JSTL XML tags may produce a list + if (xml instanceof List) { + List list = (List) xml; + if (list.size() != 1) { + throw new JspTagException(Resources.getMessage("TRANSFORM_XML_LIST_SIZE")); + } + xml = list.get(0); + } + + if (xml instanceof Source) { + return (Source) xml; + } + if (xml instanceof String) { + String s = (String) xml; + s = s.trim(); + if (s.length() == 0) { + throw new JspTagException(Resources.getMessage("TRANSFORM_XML_IS_EMPTY")); + } + return XmlUtil.newSAXSource(new StringReader(s), xmlSystemId, entityResolver); + } + if (xml instanceof Reader) { + return XmlUtil.newSAXSource((Reader) xml, xmlSystemId, entityResolver); + } + if (xml instanceof Node) { + return new DOMSource((Node) xml, xmlSystemId); + } + throw new JspTagException(Resources.getMessage("TRANSFORM_XML_UNSUPPORTED_TYPE", xml.getClass())); + } + + /** + * Return the Source for a document specified as body content. + * + * @return the document Source + * @throws JspTagException if there is a problem with the body content + */ + Source getSourceFromBodyContent() throws JspTagException, SAXException, ParserConfigurationException { + if (bodyContent == null) { + throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_IS_NULL")); + } + String s = bodyContent.getString(); + if (s == null) { + throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_CONTENT_IS_NULL")); + } + s = s.trim(); + if (s.length() == 0) { + throw new JspTagException(Resources.getMessage("TRANSFORM_BODY_IS_EMPTY")); + } + return XmlUtil.newSAXSource(new StringReader(s), xmlSystemId, entityResolver); + } + + + //********************************************************************* + // Tag attributes + + public void setVar(String var) { + this.var = var; + } + + public void setScope(String scope) { + this.scope = Util.getScope(scope); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java new file mode 100644 index 000000000..dd4f45efb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/WhenTag.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspTagException; +import javax.xml.transform.TransformerException; + +import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; + +/** + *

Tag handler for <if> in JSTL's XML library.

+ * + * @author Shawn Bayern + */ + +public class WhenTag extends WhenTagSupport { + + private XPath select; + + @Override + public void release() { + super.release(); + select = null; + } + + @Override + protected boolean condition() throws JspTagException { + XPathContext context = XalanUtil.getContext(this, pageContext); + try { + return select.bool(context, context.getCurrentNode(), null); + } catch (TransformerException e) { + throw new JspTagException(e); + } + } + + public void setSelect(String select) { + try { + this.select = new XPath(select, null, null, XPath.SELECT); + } catch (TransformerException e) { + throw new AssertionError(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java new file mode 100644 index 000000000..c0e3e6b5d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/common/xml/XalanUtil.java @@ -0,0 +1,90 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; +import jakarta.servlet.jsp.tagext.TagSupport; +import javax.xml.transform.TransformerException; + +import org.apache.taglibs.standard.util.XmlUtil; +import org.apache.xpath.VariableStack; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XBoolean; +import org.apache.xpath.objects.XNodeSet; +import org.apache.xpath.objects.XNumber; +import org.apache.xpath.objects.XObject; +import org.apache.xpath.objects.XString; +import org.w3c.dom.NodeList; + +/** + */ +public class XalanUtil { + /** + * Return the XPathContext to be used for evaluating expressions. + * + * If the child is nested withing a forEach tag its iteration context is used. + * Otherwise, a new context is created based on an empty Document. + * + * @param child the tag whose context should be returned + * @param pageContext the current page context + * @return the XPath evaluation context + */ + public static XPathContext getContext(Tag child, PageContext pageContext) { + // if within a forEach tag, use its context + ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class); + if (forEachTag != null) { + return forEachTag.getContext(); + } + + // otherwise, create a new context referring to an empty document + XPathContext context = new XPathContext(false); + VariableStack variableStack = new JSTLVariableStack(pageContext); + context.setVarStack(variableStack); + int dtm = context.getDTMHandleFromNode(XmlUtil.newEmptyDocument()); + context.pushCurrentNodeAndExpression(dtm, dtm); + return context; + } + + /** + * Return the Java value corresponding to an XPath result. + * + * @param xo the XPath type + * @return the corresponding Java value per the JSTL mapping rules + * @throws TransformerException if there was a problem converting the type + */ + static Object coerceToJava(XObject xo) throws TransformerException { + if (xo instanceof XBoolean) { + return xo.bool(); + } else if (xo instanceof XNumber) { + return xo.num(); + } else if (xo instanceof XString) { + return xo.str(); + } else if (xo instanceof XNodeSet) { + NodeList nodes = xo.nodelist(); + // if there is only one node in the nodeset return it rather than the list + if (nodes.getLength() == 1) { + return nodes.item(0); + } else { + return nodes; + } + } else { + // unexpected result type + throw new AssertionError(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForEachTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForEachTag.java new file mode 100644 index 000000000..d7c069abc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForEachTag.java @@ -0,0 +1,74 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import java.util.ArrayList; + +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.IterationTag; + +import org.apache.taglibs.standard.tag.common.core.ForEachSupport; + +/** + *

A handler for <forEach> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ForEachTag + extends ForEachSupport + implements LoopTag, IterationTag { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setBegin(int begin) throws JspTagException { + this.beginSpecified = true; + this.begin = begin; + validateBegin(); + } + + // for tag attribute + + public void setEnd(int end) throws JspTagException { + this.endSpecified = true; + this.end = end; + validateEnd(); + } + + // for tag attribute + + public void setStep(int step) throws JspTagException { + this.stepSpecified = true; + this.step = step; + validateStep(); + } + + public void setItems(Object o) throws JspTagException { + // for null items, simulate an empty list + if (o == null) { + rawItems = new ArrayList(); + } else { + rawItems = o; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java new file mode 100644 index 000000000..b51eababc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ForTokensTag.java @@ -0,0 +1,84 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.IterationTag; + +import org.apache.taglibs.standard.tag.common.core.ForTokensSupport; + +/** + *

A handler for <forTokens> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ForTokensTag + extends ForTokensSupport + implements LoopTag, IterationTag { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setBegin(int begin) throws JspTagException { + this.beginSpecified = true; + this.begin = begin; + validateBegin(); + } + + // for tag attribute + + public void setEnd(int end) throws JspTagException { + this.endSpecified = true; + this.end = end; + validateEnd(); + } + + // for tag attribute + + public void setStep(int step) throws JspTagException { + this.stepSpecified = true; + this.step = step; + validateStep(); + } + + // 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) { + items = ""; + } + } + + // stores the 'delims' String we're passed + + public void setDelims(String s) throws JspTagException { + delims = s; + // use the empty string to cause monolithic tokenization + if (s == null) { + delims = ""; + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/IfTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/IfTag.java new file mode 100644 index 000000000..0bef5547d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/IfTag.java @@ -0,0 +1,85 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; + +/** + *

Tag handler for <if> in JSTL's rtexprvalue library. Because + * of the support provided by the ConditionalTagSupport class, this + * tag is trivial enough not to require a separate base supporting class + * common to both libraries.

+ * + * @author Shawn Bayern + */ + +public class IfTag extends ConditionalTagSupport { + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public IfTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Supplied conditional logic + + @Override + protected boolean condition() { + return test; + } + + + //********************************************************************* + // Private state + + private boolean test; // the value of the 'test' attribute + + + //********************************************************************* + // Accessors + + // receives the tag's 'test' attribute + + public void setTest(boolean test) { + this.test = test; + } + + + //********************************************************************* + // Private utility methods + + // resets internal state + + private void init() { + test = false; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ImportTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ImportTag.java new file mode 100644 index 000000000..3e451f536 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ImportTag.java @@ -0,0 +1,54 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.core.ImportSupport; + +/** + *

A handler for <import> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ImportTag extends ImportSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setUrl(String url) throws JspTagException { + this.url = url; + } + + // for tag attribute + + public void setContext(String context) throws JspTagException { + this.context = context; + } + + // for tag attribute + + public void setCharEncoding(String charEncoding) throws JspTagException { + this.charEncoding = charEncoding; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/OutTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/OutTag.java new file mode 100644 index 000000000..053b9af96 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/OutTag.java @@ -0,0 +1,77 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import org.apache.taglibs.standard.tag.common.core.OutSupport; + +/** + *

Tag handler for <out> in JSTL's rtexprvalue library.

+ * + * @author Shawn Bayern + */ + +public class OutTag extends OutSupport { + + private Object value; + private String def; + private boolean escapeXml = true; + + //********************************************************************* + // Accessors + + @Override + public void release() { + value = null; + def = null; + escapeXml = false; + super.release(); + } + + // for tag attribute + + public void setValue(Object value) { + this.value = value; + } + + // for tag attribute + + public void setDefault(String def) { + this.def = def; + } + + // for tag attribute + + public void setEscapeXml(boolean escapeXml) { + this.escapeXml = escapeXml; + } + + @Override + protected Object evalValue() { + return value; + } + + @Override + protected String evalDefault() { + return def; + } + + @Override + protected boolean evalEscapeXml() { + return escapeXml; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ParamTag.java new file mode 100644 index 000000000..36c2fa39b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/ParamTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.core.ParamSupport; + +/** + *

A handler for <param> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setName(String name) throws JspTagException { + this.name = name; + } + + // for tag attribute + + public void setValue(String value) throws JspTagException { + this.value = value; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/RedirectTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/RedirectTag.java new file mode 100644 index 000000000..5a647aca1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/RedirectTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.core.RedirectSupport; + +/** + *

A handler for <redirect> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class RedirectTag extends RedirectSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setUrl(String url) throws JspTagException { + this.url = url; + } + + // for tag attribute + + public void setContext(String context) throws JspTagException { + this.context = context; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/SetTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/SetTag.java new file mode 100644 index 000000000..6951dc748 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/SetTag.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 org.apache.taglibs.standard.tag.rt.core; + +import org.apache.taglibs.standard.tag.common.core.SetSupport; + +/** + * JSTL 1.1 compatible version of <set> that accepts expression results for attribute values. + * + * @author Shawn Bayern + */ + +public class SetTag extends SetSupport { + private boolean valueSpecified; + private Object value; + private Object target; + private String property; + + public SetTag() { + } + + public void setValue(Object value) { + this.value = value; + this.valueSpecified = true; + } + + public void setTarget(Object target) { + this.target = target; + } + + public void setProperty(String property) { + this.property = property; + } + + @Override + public void release() { + value = null; + target = null; + property = null; + valueSpecified = false; + super.release(); + } + + @Override + protected boolean isValueSpecified() { + return valueSpecified; + } + + @Override + protected Object evalValue() { + return value; + } + + @Override + protected Object evalTarget() { + return target; + } + + @Override + protected String evalProperty() { + return property; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/UrlTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/UrlTag.java new file mode 100644 index 000000000..7632364ae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/UrlTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.core.UrlSupport; + +/** + *

A handler for <urlEncode> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class UrlTag extends UrlSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(String value) throws JspTagException { + this.value = value; + } + + // for tag attribute + + public void setContext(String context) throws JspTagException { + this.context = context; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/WhenTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/WhenTag.java new file mode 100644 index 000000000..3923c7317 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/core/WhenTag.java @@ -0,0 +1,82 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; + +/** + *

Tag handler for <when> in JSTL's rtexprvalue library.

+ * + * @author Shawn Bayern + */ + +public class WhenTag extends WhenTagSupport { + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public WhenTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Supplied conditional logic + + @Override + protected boolean condition() { + return test; + } + + + //********************************************************************* + // Private state + + private boolean test; // the value of the 'test' attribute + + + //********************************************************************* + // Accessors + + // receives the tag's 'test' attribute + + public void setTest(boolean test) { + this.test = test; + } + + + //********************************************************************* + // Private utility methods + + // resets internal state + + private void init() { + test = false; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/BundleTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/BundleTag.java new file mode 100644 index 000000000..73eecd222 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/BundleTag.java @@ -0,0 +1,47 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.BundleSupport; + +/** + *

A handler for <bundle> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class BundleTag extends BundleSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setBasename(String basename) throws JspTagException { + this.basename = basename; + } + + // for tag attribute + + public void setPrefix(String prefix) throws JspTagException { + this.prefix = prefix; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatDateTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatDateTag.java new file mode 100644 index 000000000..6f2b79afe --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatDateTag.java @@ -0,0 +1,73 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import java.util.Date; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.FormatDateSupport; + +/** + *

A handler for <formatDate> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class FormatDateTag extends FormatDateSupport { + + //********************************************************************* + // Accessor methods + + // 'value' attribute + + public void setValue(Date value) throws JspTagException { + this.value = value; + } + + // 'type' attribute + + public void setType(String type) throws JspTagException { + this.type = type; + } + + // 'dateStyle' attribute + + public void setDateStyle(String dateStyle) throws JspTagException { + this.dateStyle = dateStyle; + } + + // 'timeStyle' attribute + + public void setTimeStyle(String timeStyle) throws JspTagException { + this.timeStyle = timeStyle; + } + + // 'pattern' attribute + + public void setPattern(String pattern) throws JspTagException { + this.pattern = pattern; + } + + // 'timeZone' attribute + + public void setTimeZone(Object timeZone) throws JspTagException { + this.timeZone = timeZone; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatNumberTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatNumberTag.java new file mode 100644 index 000000000..2c0fd9e11 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/FormatNumberTag.java @@ -0,0 +1,103 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.FormatNumberSupport; + +/** + *

A handler for <formatNumber> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class FormatNumberTag extends FormatNumberSupport { + + //********************************************************************* + // Accessor methods + + // 'value' attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + this.valueSpecified = true; + } + + // 'type' attribute + + public void setType(String type) throws JspTagException { + this.type = type; + } + + // 'pattern' attribute + + public void setPattern(String pattern) throws JspTagException { + this.pattern = pattern; + } + + // 'currencyCode' attribute + + public void setCurrencyCode(String currencyCode) throws JspTagException { + this.currencyCode = currencyCode; + } + + // 'currencySymbol' attribute + + public void setCurrencySymbol(String currencySymbol) + throws JspTagException { + this.currencySymbol = currencySymbol; + } + + // 'groupingUsed' attribute + + public void setGroupingUsed(boolean isGroupingUsed) + throws JspTagException { + this.isGroupingUsed = isGroupingUsed; + this.groupingUsedSpecified = true; + } + + // 'maxIntegerDigits' attribute + + public void setMaxIntegerDigits(int maxDigits) throws JspTagException { + this.maxIntegerDigits = maxDigits; + this.maxIntegerDigitsSpecified = true; + } + + // 'minIntegerDigits' attribute + + public void setMinIntegerDigits(int minDigits) throws JspTagException { + this.minIntegerDigits = minDigits; + this.minIntegerDigitsSpecified = true; + } + + // 'maxFractionDigits' attribute + + public void setMaxFractionDigits(int maxDigits) throws JspTagException { + this.maxFractionDigits = maxDigits; + this.maxFractionDigitsSpecified = true; + } + + // 'minFractionDigits' attribute + + public void setMinFractionDigits(int minDigits) throws JspTagException { + this.minFractionDigits = minDigits; + this.minFractionDigitsSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/MessageTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/MessageTag.java new file mode 100644 index 000000000..fb8ca6f66 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/MessageTag.java @@ -0,0 +1,50 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; + +import org.apache.taglibs.standard.tag.common.fmt.MessageSupport; + +/** + *

A handler for <message> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class MessageTag extends MessageSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setKey(String key) throws JspTagException { + this.keyAttrValue = key; + this.keySpecified = true; + } + + // for tag attribute + + public void setBundle(LocalizationContext locCtxt) throws JspTagException { + this.bundleAttrValue = locCtxt; + this.bundleSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParamTag.java new file mode 100644 index 000000000..aecc0a3b9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParamTag.java @@ -0,0 +1,42 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.ParamSupport; + +/** + *

A handler for <param> that supports rtexprvalue-based + * message arguments.

+ * + * @author Jan Luehe + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + this.valueSpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseDateTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseDateTag.java new file mode 100644 index 000000000..787dd8203 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseDateTag.java @@ -0,0 +1,84 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseDateSupport; + +/** + *

A handler for <parseDate> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class ParseDateTag extends ParseDateSupport { + + //********************************************************************* + // Accessor methods + + // 'value' attribute + + public void setValue(String value) throws JspTagException { + this.value = value; + this.valueSpecified = true; + } + + // 'type' attribute + + public void setType(String type) throws JspTagException { + this.type = type; + } + + // 'dateStyle' attribute + + public void setDateStyle(String dateStyle) throws JspTagException { + this.dateStyle = dateStyle; + } + + // 'timeStyle' attribute + + public void setTimeStyle(String timeStyle) throws JspTagException { + this.timeStyle = timeStyle; + } + + // 'pattern' attribute + + public void setPattern(String pattern) throws JspTagException { + this.pattern = pattern; + } + + // 'timeZone' attribute + + public void setTimeZone(Object timeZone) throws JspTagException { + this.timeZone = timeZone; + } + + // 'parseLocale' attribute + + public void setParseLocale(Object loc) throws JspTagException { + Locale locale = LocaleUtil.parseLocaleAttributeValue(loc); + if (loc != null) { + this.parseLocale = locale; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseNumberTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseNumberTag.java new file mode 100644 index 000000000..4552f8036 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/ParseNumberTag.java @@ -0,0 +1,73 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseNumberSupport; + +/** + *

A handler for <parseNumber> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class ParseNumberTag extends ParseNumberSupport { + + //********************************************************************* + // Accessor methods + + // 'value' attribute + + public void setValue(String value) throws JspTagException { + this.value = value; + this.valueSpecified = true; + } + + // 'type' attribute + + public void setType(String type) throws JspTagException { + this.type = type; + } + + // 'pattern' attribute + + public void setPattern(String pattern) throws JspTagException { + this.pattern = pattern; + } + + // 'parseLocale' attribute + + public void setParseLocale(Object loc) throws JspTagException { + Locale locale = LocaleUtil.parseLocaleAttributeValue(loc); + if (loc != null) { + this.parseLocale = locale; + } + } + + // 'integerOnly' attribute + + public void setIntegerOnly(boolean isIntegerOnly) throws JspTagException { + this.isIntegerOnly = isIntegerOnly; + this.integerOnlySpecified = true; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/RequestEncodingTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/RequestEncodingTag.java new file mode 100644 index 000000000..0c3e51b17 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/RequestEncodingTag.java @@ -0,0 +1,41 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.RequestEncodingSupport; + +/** + *

A handler for <requestEncoding> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class RequestEncodingTag extends RequestEncodingSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(String value) throws JspTagException { + this.value = value; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetBundleTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetBundleTag.java new file mode 100644 index 000000000..38ebdf34c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetBundleTag.java @@ -0,0 +1,41 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.SetBundleSupport; + +/** + *

A handler for <setBundle> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class SetBundleTag extends SetBundleSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setBasename(String basename) throws JspTagException { + this.basename = basename; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetLocaleTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetLocaleTag.java new file mode 100644 index 000000000..7cb66cbad --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetLocaleTag.java @@ -0,0 +1,47 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.SetLocaleSupport; + +/** + *

A handler for <setLocale> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class SetLocaleTag extends SetLocaleSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + } + + // for tag attribute + + public void setVariant(String variant) throws JspTagException { + this.variant = variant; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetTimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetTimeZoneTag.java new file mode 100644 index 000000000..5c272c0c8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/SetTimeZoneTag.java @@ -0,0 +1,41 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.SetTimeZoneSupport; + +/** + *

A handler for <setTimeZone> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class SetTimeZoneTag extends SetTimeZoneSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/TimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/TimeZoneTag.java new file mode 100644 index 000000000..6328a790a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/fmt/TimeZoneTag.java @@ -0,0 +1,41 @@ +/* + * 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.taglibs.standard.tag.rt.fmt; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.fmt.TimeZoneSupport; + +/** + *

A handler for <timeZone> that supports rtexprvalue-based + * attributes.

+ * + * @author Jan Luehe + */ + +public class TimeZoneTag extends TimeZoneSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/DateParamTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/DateParamTag.java new file mode 100644 index 000000000..2af649c23 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/DateParamTag.java @@ -0,0 +1,37 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import java.util.Date; + +import org.apache.taglibs.standard.tag.common.sql.DateParamTagSupport; + +/** + * Subclass for the JSTL library with rtexprvalue support. + * + * @author Justyna Horwat + */ +public class DateParamTag extends DateParamTagSupport { + + public void setValue(Date value) { + this.value = value; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/ParamTag.java new file mode 100644 index 000000000..56389b699 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/ParamTag.java @@ -0,0 +1,31 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import org.apache.taglibs.standard.tag.common.sql.ParamTagSupport; + +/** + * Subclass for the JSTL library with rtexprvalue support. + * + * @author Hans Bergsten + */ +public class ParamTag extends ParamTagSupport { + + public void setValue(Object value) { + this.value = value; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/QueryTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/QueryTag.java new file mode 100644 index 000000000..1eebdca7b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/QueryTag.java @@ -0,0 +1,76 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import org.apache.taglibs.standard.tag.common.sql.QueryTagSupport; + +/** + * Subclass for the JSTL library with rtexprvalue support. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public class QueryTag extends QueryTagSupport { + + //********************************************************************* + // Constructor + + /** + * Constructs a new QueryTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public QueryTag() { + super(); + } + + //********************************************************************* + // Accessor methods + + public void setDataSource(Object dataSource) { + this.rawDataSource = dataSource; + this.dataSourceSpecified = true; + } + + /** + * The index of the first row returned can be + * specified using startRow. + */ + public void setStartRow(int startRow) { + this.startRow = startRow; + } + + /** + * Query result can be limited by specifying + * the maximum number of rows returned. + */ + public void setMaxRows(int maxRows) { + this.maxRows = maxRows; + this.maxRowsSpecified = true; + } + + /** + * Setter method for the SQL statement to use for the + * query. The statement may contain parameter markers + * (question marks, ?). If so, the parameter values must + * be set using nested value elements. + */ + public void setSql(String sql) { + this.sql = sql; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/SetDataSourceTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/SetDataSourceTag.java new file mode 100644 index 000000000..12ee572a6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/SetDataSourceTag.java @@ -0,0 +1,52 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import org.apache.taglibs.standard.tag.common.sql.SetDataSourceTagSupport; + +/** + *

Tag handler for <Driver> in JSTL, used to create + * a simple DataSource for prototyping.

+ */ +public class SetDataSourceTag extends SetDataSourceTagSupport { + + //********************************************************************* + // Accessor methods + + public void setDataSource(Object dataSource) { + this.dataSource = dataSource; + this.dataSourceSpecified = true; + } + + public void setDriver(String driverClassName) { + this.driverClassName = driverClassName; + } + + public void setUrl(String jdbcURL) { + this.jdbcURL = jdbcURL; + } + + public void setUser(String userName) { + this.userName = userName; + } + + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/TransactionTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/TransactionTag.java new file mode 100644 index 000000000..64dfeb24d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/TransactionTag.java @@ -0,0 +1,59 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.sql.TransactionTagSupport; + +/** + * Subclass for the JSTL library with rtexprvalue support. + * + * @author Hans Bergsten + */ +public class TransactionTag extends TransactionTagSupport { + private String isolationRT; + + //********************************************************************* + // Accessor methods + + + /** + * Setter method for the SQL DataSource. DataSource can be + * a String or a DataSource object. + */ + public void setDataSource(Object dataSource) { + this.rawDataSource = dataSource; + this.dataSourceSpecified = true; + } + + /** + * Setter method for the Transaction Isolation level. + */ + @Override + public void setIsolation(String isolation) { + this.isolationRT = isolation; + } + + @Override + public int doStartTag() throws JspException { + if (isolationRT != null) { + super.setIsolation(isolationRT); + } + return super.doStartTag(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/UpdateTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/UpdateTag.java new file mode 100644 index 000000000..8e8acc413 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/sql/UpdateTag.java @@ -0,0 +1,50 @@ +/* + * 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.taglibs.standard.tag.rt.sql; + +import org.apache.taglibs.standard.tag.common.sql.UpdateTagSupport; + +/** + * Subclass for the JSTL library with rtexprvalue support. + * + * @author Hans Bergsten + */ +public class UpdateTag extends UpdateTagSupport { + + //********************************************************************* + // Accessor methods + + + /** + * Setter method for the SQL DataSource. DataSource can be + * a String or a DataSource object. + */ + public void setDataSource(Object dataSource) { + this.rawDataSource = dataSource; + this.dataSourceSpecified = true; + } + + /** + * Setter method for the SQL statement to use for the + * query. The statement may contain parameter markers + * (question marks, ?). If so, the parameter values must + * be set using nested value elements. + */ + public void setSql(String sql) { + this.sql = sql; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java new file mode 100644 index 000000000..2b004e9b2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ExprTag.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.tag.rt.xml; + +import org.apache.taglibs.standard.tag.common.xml.ExprSupport; + +/** + *

A handler for <out> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ExprTag extends ExprSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setEscapeXml(boolean escapeXml) { + this.escapeXml = escapeXml; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParamTag.java new file mode 100644 index 000000000..e06556980 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParamTag.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.rt.xml; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.xml.ParamSupport; + +/** + *

A handler for <param> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // Accessor methods + + // for tag attribute + + public void setName(String name) throws JspTagException { + this.name = name; + } + + // for tag attribute + + public void setValue(Object value) throws JspTagException { + this.value = value; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParseTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParseTag.java new file mode 100644 index 000000000..71dc7d404 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/ParseTag.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.tag.rt.xml; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.tag.common.xml.ParseSupport; +import org.xml.sax.XMLFilter; + +/** + *

A handler for <parse> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class ParseTag extends ParseSupport { + + //********************************************************************* + // Accessor methods + + // Deprecated as of JSTL 1.1 + // for tag attribute + + public void setXml(Object xml) throws JspTagException { + this.xml = xml; + } + + // 'doc' replaces 'xml' as of JSTL 1.1 + + public void setDoc(Object xml) throws JspTagException { + this.xml = xml; + } + + public void setSystemId(String systemId) throws JspTagException { + this.systemId = systemId; + } + + // for tag attribute + + public void setFilter(XMLFilter filter) throws JspTagException { + this.filter = filter; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java new file mode 100644 index 000000000..455f733f5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tag/rt/xml/TransformTag.java @@ -0,0 +1,82 @@ +/* + * 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.taglibs.standard.tag.rt.xml; + +import jakarta.servlet.jsp.JspTagException; +import javax.xml.transform.Result; + +import org.apache.taglibs.standard.tag.common.xml.TransformSupport; + +/** + *

A handler for <transform> that supports rtexprvalue-based + * attributes.

+ * + * @author Shawn Bayern + */ + +public class TransformTag extends TransformSupport { + + //********************************************************************* + // Accessor methods + + // Deprecated as of JSTL 1.1 + // for tag attribute + + public void setXml(Object xml) throws JspTagException { + setDoc(xml); + } + + // 'doc' replaces 'xml' as of JSTL 1.1 + + public void setDoc(Object xml) throws JspTagException { + this.xml = xml; + this.xmlSpecified = true; + } + + // Deprecated as of JSTL 1.1 + // for tag attribute + + public void setXmlSystemId(String xmlSystemId) throws JspTagException { + this.xmlSystemId = xmlSystemId; + } + + // 'docSystemId' replaces 'xmlSystemId' as of JSTL 1.1 + + public void setDocSystemId(String xmlSystemId) throws JspTagException { + this.xmlSystemId = xmlSystemId; + } + + // for tag attribute + + public void setXslt(Object xslt) throws JspTagException { + this.xslt = xslt; + } + + // for tag attribute + + public void setXsltSystemId(String xsltSystemId) throws JspTagException { + this.xsltSystemId = xsltSystemId; + } + + // for tag attribute + + public void setResult(Result result) throws JspTagException { + this.result = result; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/DeclareTEI.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/DeclareTEI.java new file mode 100644 index 000000000..1a4a66f20 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/DeclareTEI.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagExtraInfo; +import jakarta.servlet.jsp.tagext.VariableInfo; + +/** + *

An implementation of TagExtraInfo provided for <declare>. + * We simply set up a scripting variable for the ID and value that + * <declare> already stored. For EA2, DefineTEI *always* declares + * the variable; no option is given via a tag attribute. Visibility is + * always AT_END.

+ * + * @author Shawn Bayern + */ +public class DeclareTEI extends TagExtraInfo { + + // purposely inherit JavaDoc and semantics from TagExtraInfo + + @Override + public VariableInfo[] getVariableInfo(TagData data) { + // construct the relevant VariableInfo object + VariableInfo id = new VariableInfo( + data.getAttributeString("id"), + data.getAttributeString("type") == null ? + "java.lang.Object" : data.getAttributeString("type"), + true, + VariableInfo.AT_END); + return new VariableInfo[]{id}; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ForEachTEI.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ForEachTEI.java new file mode 100644 index 000000000..9642c6746 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ForEachTEI.java @@ -0,0 +1,51 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagExtraInfo; + +/** + *

An implementation of TagExtraInfo that implements validation for + * ForEachTag's attributes

+ * + * @author Shawn Bayern + */ +public class ForEachTEI extends TagExtraInfo { + + final private static String ITEMS = "items"; + final private static String BEGIN = "begin"; + final private static String END = "end"; + + /* + * Currently implements the following rules: + * + * - If 'items' is not specified, 'begin' and 'end' must be + */ + + @Override + public boolean isValid(TagData us) { + if (!Util.isSpecified(us, ITEMS)) { + if (!Util.isSpecified(us, BEGIN) || !(Util.isSpecified(us, END))) { + return false; + } + } + return true; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ImportTEI.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ImportTEI.java new file mode 100644 index 000000000..d9143d481 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/ImportTEI.java @@ -0,0 +1,44 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagExtraInfo; + +/** + *

An implementation of TagExtraInfo that implements validation for + * <c:import>'s attributes

+ * + * @author Shawn Bayern + */ +public class ImportTEI extends TagExtraInfo { + + final private static String VAR = "var"; + final private static String VAR_READER = "varReader"; + + @Override + public boolean isValid(TagData us) { + // don't allow both VAR and VAR_READER, together + if (Util.isSpecified(us, VAR) && Util.isSpecified(us, VAR_READER)) { + return false; + } + + return true; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/Util.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/Util.java new file mode 100644 index 000000000..04a019151 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/Util.java @@ -0,0 +1,36 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; + +/** + *

Utilities in support of TagExtraInfo classes.

+ * + * @author Shawn Bayern + */ +public class Util { + + /** + * Returns true if the given attribute name is specified, false otherwise. + */ + public static boolean isSpecified(TagData data, String attributeName) { + return (data.getAttribute(attributeName) != null); + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlParseTEI.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlParseTEI.java new file mode 100644 index 000000000..e45103d20 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlParseTEI.java @@ -0,0 +1,59 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagExtraInfo; + +/** + *

An implementation of TagExtraInfo that implements validation for + * 's attributes

+ * + * @author Shawn Bayern + */ +public class XmlParseTEI extends TagExtraInfo { + + final private static String VAR = "var"; + final private static String VAR_DOM = "varDom"; + final private static String SCOPE = "scope"; + final private static String SCOPE_DOM = "scopeDom"; + + @Override + public boolean isValid(TagData us) { + // must have no more than one of VAR and VAR_DOM ... + if (Util.isSpecified(us, VAR) && Util.isSpecified(us, VAR_DOM)) { + return false; + } + + // ... and must have no less than one of VAR and VAR_DOM + if (!(Util.isSpecified(us, VAR) || Util.isSpecified(us, VAR_DOM))) { + return false; + } + + // When either 'scope' is specified, its 'var' must be specified + if (Util.isSpecified(us, SCOPE) && !Util.isSpecified(us, VAR)) { + return false; + } + if (Util.isSpecified(us, SCOPE_DOM) && !Util.isSpecified(us, VAR_DOM)) { + return false; + } + + return true; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlTransformTEI.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlTransformTEI.java new file mode 100644 index 000000000..41a3a378b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tei/XmlTransformTEI.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.tei; + +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagExtraInfo; + +/** + *

An implementation of TagExtraInfo that implements validation for + * <x:transform>'s attributes

+ * + * @author Shawn Bayern + */ +public class XmlTransformTEI extends TagExtraInfo { + + final private static String XSLT = "xslt"; + final private static String RESULT = "result"; + final private static String VAR = "var"; + + @Override + public boolean isValid(TagData us) { + // require XSLT + if (!Util.isSpecified(us, XSLT)) { + return false; + } + + // disallow both VAR and RESULT + if (Util.isSpecified(us, VAR) && Util.isSpecified(us, RESULT)) { + return false; + } + return true; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlBaseTLV.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlBaseTLV.java new file mode 100644 index 000000000..c51bc1626 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlBaseTLV.java @@ -0,0 +1,345 @@ +/* + * 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.taglibs.standard.tlv; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Vector; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.TagData; +import jakarta.servlet.jsp.tagext.TagLibraryValidator; +import jakarta.servlet.jsp.tagext.ValidationMessage; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.taglibs.standard.resources.Resources; +import org.apache.taglibs.standard.util.XmlUtil; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A base class to support SAX-based validation in JSTL.

+ * + * @author Shawn Bayern + */ +public abstract class JstlBaseTLV extends TagLibraryValidator { + + //********************************************************************* + // Implementation Overview + + /* + * We essentially just run the page through a SAX parser, handling + * the callbacks that interest us. The SAX parser is supplied by + * subclasses using the protected getHandler() method. + */ + + protected abstract DefaultHandler getHandler(); + + + //********************************************************************* + // Constants + + // parameter names + private static final String EXP_ATT_PARAM = "expressionAttributes"; + + // attributes + protected static final String VAR = "var"; + protected static final String SCOPE = "scope"; + + //scopes + protected static final String PAGE_SCOPE = "page"; + protected static final String REQUEST_SCOPE = "request"; + protected static final String SESSION_SCOPE = "session"; + protected static final String APPLICATION_SCOPE = "application"; + + // Relevant URIs + protected final String JSP = "http://java.sun.com/JSP/Page"; + + // types of sub-classes - used on method validate() + private static final int TYPE_UNDEFINED = 0; + protected static final int TYPE_CORE = 1; + protected static final int TYPE_FMT = 2; + protected static final int TYPE_SQL = 3; + protected static final int TYPE_XML = 4; + + // which tlv is being validated + private int tlvType = TYPE_UNDEFINED; + + //********************************************************************* + // Validation and configuration state (protected) + + protected String uri; // our taglib's uri (as passed by JSP container on XML View) + protected String prefix; // our taglib's prefix + protected Vector messageVector; // temporary error messages + protected Map config; // configuration (Map of Sets) + protected boolean failed; // have we failed >0 times? + protected String lastElementId; // the last element we've seen + + //********************************************************************* + // Constructor and lifecycle management + + public JstlBaseTLV() { + super(); + init(); + } + + private void init() { + messageVector = null; + prefix = null; + config = null; + } + + @Override + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Validation entry point - this method is called by the sub-classes to + // do the validation. + + public synchronized ValidationMessage[] validate( + int type, String prefix, String uri, PageData page) { + try { + this.tlvType = type; + this.uri = uri; + // initialize + messageVector = new Vector(); + + // save the prefix + this.prefix = prefix; + + // parse parameters if necessary + try { + if (config == null) { + configure((String) getInitParameters().get(EXP_ATT_PARAM)); + } + } catch (NoSuchElementException ex) { + // parsing error + return vmFromString( + Resources.getMessage("TLV_PARAMETER_ERROR", + EXP_ATT_PARAM)); + } + + // get a handler + DefaultHandler h = getHandler(); + + // parse the page + XMLReader xmlReader = XmlUtil.newXMLReader(null); + xmlReader.setContentHandler(h); + InputStream inputStream = page.getInputStream(); + try { + xmlReader.parse(new InputSource(inputStream)); + } finally { + try { + inputStream.close(); + } catch (IOException e) { + // Suppressed. + } + } + + if (messageVector.size() == 0) { + return null; + } else { + return vmFromVector(messageVector); + } + + } catch (SAXException|IOException|ParserConfigurationException ex) { + return vmFromString(ex.toString()); + } + } + + //********************************************************************* + // Protected utility functions + + // delegate validation to the appropriate expression language + // TODO refactor this into EL tag specific functionality + + @Deprecated + protected String validateExpression( + String elem, String att, String expr) { + + return null; + } + + // utility methods to help us match elements in our tagset + + protected boolean isTag(String tagUri, + String tagLn, + String matchUri, + String matchLn) { + if (tagUri == null + || tagUri.length() == 0 + || tagLn == null + || matchUri == null + || matchLn == null) { + return false; + } + // match beginning of URI since some suffix *_rt tags can + // be nested in EL enabled tags as defined by the spec + if (tagUri.length() > matchUri.length()) { + return (tagUri.startsWith(matchUri) && tagLn.equals(matchLn)); + } else { + return (matchUri.startsWith(tagUri) && tagLn.equals(matchLn)); + } + } + + protected boolean isJspTag(String tagUri, String tagLn, String target) { + return isTag(tagUri, tagLn, JSP, target); + } + + private boolean isTag(int type, String tagUri, String tagLn, String target) { + return (this.tlvType == type && isTag(tagUri, tagLn, this.uri, target)); + } + + protected boolean isCoreTag(String tagUri, String tagLn, String target) { + return isTag(TYPE_CORE, tagUri, tagLn, target); + } + + protected boolean isFmtTag(String tagUri, String tagLn, String target) { + return isTag(TYPE_FMT, tagUri, tagLn, target); + } + + protected boolean isSqlTag(String tagUri, String tagLn, String target) { + return isTag(TYPE_SQL, tagUri, tagLn, target); + } + + protected boolean isXmlTag(String tagUri, String tagLn, String target) { + return isTag(TYPE_XML, tagUri, tagLn, target); + } + + // utility method to determine if an attribute exists + + protected boolean hasAttribute(Attributes a, String att) { + return (a.getValue(att) != null); + } + + /* + * method to assist with failure [ as if it's not easy enough + * already :-) ] + */ + + protected void fail(String message) { + failed = true; + messageVector.add(new ValidationMessage(lastElementId, message)); + } + + // returns true if the given attribute name is specified, false otherwise + + protected boolean isSpecified(TagData data, String attributeName) { + return (data.getAttribute(attributeName) != null); + } + + // returns true if the 'scope' attribute is valid + + protected boolean hasNoInvalidScope(Attributes a) { + String scope = a.getValue(SCOPE); + + if ((scope != null) + && !scope.equals(PAGE_SCOPE) + && !scope.equals(REQUEST_SCOPE) + && !scope.equals(SESSION_SCOPE) + && !scope.equals(APPLICATION_SCOPE)) { + return false; + } + + return true; + } + + // returns true if the 'var' attribute is empty + + protected boolean hasEmptyVar(Attributes a) { + return "".equals(a.getValue(VAR)); + } + + // returns true if the 'scope' attribute is present without 'var' + + protected boolean hasDanglingScope(Attributes a) { + return (a.getValue(SCOPE) != null && a.getValue(VAR) == null); + } + + // retrieves the local part of a QName + + protected String getLocalPart(String qname) { + int colon = qname.indexOf(":"); + if (colon == -1) { + return qname; + } else { + return qname.substring(colon + 1); + } + } + + //********************************************************************* + // Miscellaneous utility functions + + // parses our configuration parameter for element:attribute pairs + + private void configure(String info) { + // construct our configuration map + config = new HashMap(); + + // leave the map empty if we have nothing to configure + if (info == null) { + return; + } + + // separate parameter into space-separated tokens and store them + StringTokenizer st = new StringTokenizer(info); + while (st.hasMoreTokens()) { + String pair = st.nextToken(); + StringTokenizer pairTokens = new StringTokenizer(pair, ":"); + String element = pairTokens.nextToken(); + String attribute = pairTokens.nextToken(); + Object atts = config.get(element); + if (atts == null) { + atts = new HashSet(); + config.put(element, atts); + } + ((Set) atts).add(attribute); + } + } + + // constructs a ValidationMessage[] from a single String and no ID + + static ValidationMessage[] vmFromString(String message) { + return new ValidationMessage[]{ + new ValidationMessage(null, message) + }; + } + + // constructs a ValidationMessage[] from a ValidationMessage Vector + + static ValidationMessage[] vmFromVector(Vector v) { + ValidationMessage[] vm = new ValidationMessage[v.size()]; + for (int i = 0; i < vm.length; i++) { + vm[i] = (ValidationMessage) v.get(i); + } + return vm; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlCoreTLV.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlCoreTLV.java new file mode 100644 index 000000000..b2a5590a0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlCoreTLV.java @@ -0,0 +1,355 @@ +/* + * 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.taglibs.standard.tlv; + +import java.util.Set; +import java.util.Stack; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.ValidationMessage; + +import org.apache.taglibs.standard.resources.Resources; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A SAX-based TagLibraryValidator for the core JSTL tag library. + * Currently implements the following checks:

+ *
    + *
  • Expression syntax validation. + *
  • Choose / when / otherwise constraints
  • + *
  • Tag bodies that must either be empty or non-empty given + * particular attributes. (E.g., cannot have a body when + * 'value' is specified; it *must* have a body otherwise.) For + * these purposes, "having a body" refers to non-whitespace + * content inside the tag.
  • + *
  • Other minor constraints.
  • + *
+ * + * @author Shawn Bayern + */ +public class JstlCoreTLV extends JstlBaseTLV { + + //********************************************************************* + // Implementation Overview + + /* + * We essentially just run the page through a SAX parser, handling + * the callbacks that interest us. We collapse elements + * into the text they contain, since this simplifies processing + * somewhat. Even a quick glance at the implementation shows its + * necessary, tree-oriented nature: multiple Stacks, an understanding + * of 'depth', and so on all are important as we recover necessary + * state upon each callback. This TLV demonstrates various techniques, + * from the general "how do I use a SAX parser for a TLV?" to + * "how do I read my init parameters and then validate?" But also, + * the specific SAX methodology was kept as general as possible to + * allow for experimentation and flexibility. + */ + + + //********************************************************************* + // Constants + + // tag names + private static final String CHOOSE = "choose"; + private static final String WHEN = "when"; + private static final String OTHERWISE = "otherwise"; + private static final String EXPR = "out"; + private static final String SET = "set"; + private static final String IMPORT = "import"; + private static final String URL = "url"; + private static final String REDIRECT = "redirect"; + private static final String PARAM = "param"; + private static final String TEXT = "text"; + + // attribute names + private static final String VALUE = "value"; + private static final String DEFAULT = "default"; + private static final String VAR_READER = "varReader"; + + // alternative identifiers for tags + private static final String IMPORT_WITH_READER = "import varReader=''"; + private static final String IMPORT_WITHOUT_READER = "import var=''"; + + + //********************************************************************* + // set its type and delegate validation to super-class + + @Override + public ValidationMessage[] validate( + String prefix, String uri, PageData page) { + return super.validate(TYPE_CORE, prefix, uri, page); + } + + + //********************************************************************* + // Contract fulfillment + + @Override + protected DefaultHandler getHandler() { + return new Handler(); + } + + + //********************************************************************* + // SAX event handler + + /** + * The handler that provides the base of our implementation. + */ + private class Handler extends DefaultHandler { + + // parser state + private int depth = 0; + private Stack chooseDepths = new Stack(); + private Stack chooseHasOtherwise = new Stack(); + private Stack chooseHasWhen = new Stack(); + private Stack urlTags = new Stack(); + private String lastElementName = null; + private boolean bodyNecessary = false; + private boolean bodyIllegal = false; + + // process under the existing context (state), then modify it + + @Override + public void startElement( + String ns, String ln, String qn, Attributes a) { + + // substitute our own parsed 'ln' if it's not provided + if (ln == null) { + ln = getLocalPart(qn); + } + + // for simplicity, we can ignore for our purposes + // (don't bother distinguishing between it and its characters) + if (isJspTag(ns, ln, TEXT)) { + return; + } + + // check body-related constraint + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + + // validate expression syntax if we need to + Set expAtts; + if (qn.startsWith(prefix + ":") + && (expAtts = (Set) config.get(ln)) != null) { + for (int i = 0; i < a.getLength(); i++) { + String attName = a.getLocalName(i); + if (expAtts.contains(attName)) { + String vMsg = + validateExpression( + ln, + attName, + a.getValue(i)); + if (vMsg != null) { + fail(vMsg); + } + } + } + } + + // validate attributes + if (qn.startsWith(prefix + ":") && !hasNoInvalidScope(a)) { + fail(Resources.getMessage("TLV_INVALID_ATTRIBUTE", + SCOPE, qn, a.getValue(SCOPE))); + } + if (qn.startsWith(prefix + ":") && hasEmptyVar(a)) { + fail(Resources.getMessage("TLV_EMPTY_VAR", qn)); + } + if (qn.startsWith(prefix + ":") && hasDanglingScope(a)) { + fail(Resources.getMessage("TLV_DANGLING_SCOPE", qn)); + } + + // check invariants for + if (chooseChild()) { + // mark for the first the first + if (isCoreTag(ns, ln, WHEN)) { + chooseHasWhen.pop(); + chooseHasWhen.push(Boolean.TRUE); + } + + // ensure has the right children + if (!isCoreTag(ns, ln, WHEN) && !isCoreTag(ns, ln, OTHERWISE)) { + fail(Resources.getMessage("TLV_ILLEGAL_CHILD_TAG", + prefix, CHOOSE, qn)); + } + + // make sure is the last tag + if (((Boolean) chooseHasOtherwise.peek()).booleanValue()) { + fail(Resources.getMessage("TLV_ILLEGAL_ORDER", + qn, prefix, OTHERWISE, CHOOSE)); + } + if (isCoreTag(ns, ln, OTHERWISE)) { + chooseHasOtherwise.pop(); + chooseHasOtherwise.push(Boolean.TRUE); + } + + } + + // check constraints for vis-a-vis URL-related tags + if (isCoreTag(ns, ln, PARAM)) { + // no outside URL tags. + if (urlTags.empty() || urlTags.peek().equals(PARAM)) { + fail(Resources.getMessage("TLV_ILLEGAL_ORPHAN", PARAM)); + } + + // no where the most recent has a reader + if (!urlTags.empty() && + urlTags.peek().equals(IMPORT_WITH_READER)) { + fail(Resources.getMessage("TLV_ILLEGAL_PARAM", + prefix, PARAM, IMPORT, VAR_READER)); + } + } else { + // tag ISN'T , so it's illegal under non-reader + if (!urlTags.empty() + && urlTags.peek().equals(IMPORT_WITHOUT_READER)) { + fail(Resources.getMessage("TLV_ILLEGAL_CHILD_TAG", + prefix, IMPORT, qn)); + } + } + + // now, modify state + + // we're a choose, so record new choose-specific state + if (isCoreTag(ns, ln, CHOOSE)) { + chooseDepths.push(new Integer(depth)); + chooseHasWhen.push(Boolean.FALSE); + chooseHasOtherwise.push(Boolean.FALSE); + } + + // if we're introducing a URL-related tag, record it + if (isCoreTag(ns, ln, IMPORT)) { + if (hasAttribute(a, VAR_READER)) { + urlTags.push(IMPORT_WITH_READER); + } else { + urlTags.push(IMPORT_WITHOUT_READER); + } + } else if (isCoreTag(ns, ln, PARAM)) { + urlTags.push(PARAM); + } else if (isCoreTag(ns, ln, REDIRECT)) { + urlTags.push(REDIRECT); + } else if (isCoreTag(ns, ln, URL)) { + urlTags.push(URL); + } + + // set up a check against illegal attribute/body combinations + bodyIllegal = false; + bodyNecessary = false; + if (isCoreTag(ns, ln, EXPR)) { + if (hasAttribute(a, DEFAULT)) { + bodyIllegal = true; + } + } else if (isCoreTag(ns, ln, SET)) { + if (hasAttribute(a, VALUE)) { + bodyIllegal = true; + } + // else + // bodyNecessary = true; + } + + // record the most recent tag (for error reporting) + lastElementName = qn; + lastElementId = a.getValue(JSP, "id"); + + // we're a new element, so increase depth + depth++; + } + + @Override + public void characters(char[] ch, int start, int length) { + + bodyNecessary = false; // body is no longer necessary! + + // ignore strings that are just whitespace + String s = new String(ch, start, length).trim(); + if (s.equals("")) { + return; + } + + // check and update body-related constraints + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + if (!urlTags.empty() + && urlTags.peek().equals(IMPORT_WITHOUT_READER)) { + // we're in an without a Reader; nothing but + // is allowed + fail(Resources.getMessage("TLV_ILLEGAL_BODY", + prefix + ":" + IMPORT)); + } + + // make sure has no non-whitespace text + if (chooseChild()) { + String msg = + Resources.getMessage("TLV_ILLEGAL_TEXT_BODY", + prefix, CHOOSE, + (s.length() < 7 ? s : s.substring(0, 7))); + fail(msg); + } + } + + @Override + public void endElement(String ns, String ln, String qn) { + + // consistently, we ignore JSP_TEXT + if (isJspTag(ns, ln, TEXT)) { + return; + } + + // handle body-related invariant + if (bodyNecessary) { + fail(Resources.getMessage("TLV_MISSING_BODY", + lastElementName)); + } + bodyIllegal = false; // reset: we've left the tag + + // update -related state + if (isCoreTag(ns, ln, CHOOSE)) { + Boolean b = (Boolean) chooseHasWhen.pop(); + if (!b.booleanValue()) { + fail(Resources.getMessage("TLV_PARENT_WITHOUT_SUBTAG", + CHOOSE, WHEN)); + } + chooseDepths.pop(); + chooseHasOtherwise.pop(); + } + + // update state related to URL tags + if (isCoreTag(ns, ln, IMPORT) + || isCoreTag(ns, ln, PARAM) + || isCoreTag(ns, ln, REDIRECT) + || isCoreTag(ns, ln, URL)) { + urlTags.pop(); + } + + // update our depth + depth--; + } + + // are we directly under a ? + + private boolean chooseChild() { + return (!chooseDepths.empty() + && (depth - 1) == ((Integer) chooseDepths.peek()).intValue()); + } + + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlFmtTLV.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlFmtTLV.java new file mode 100644 index 000000000..d6e001445 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlFmtTLV.java @@ -0,0 +1,275 @@ +/* + * 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.taglibs.standard.tlv; + +import java.util.Set; +import java.util.Stack; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.ValidationMessage; + +import org.apache.taglibs.standard.resources.Resources; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A SAX-based TagLibraryValidator for the JSTL i18n-capable formatting + * library. Currently implements the following checks:

+ *
    + *
  • Expression syntax validation. + *
  • Tag bodies that must either be empty or non-empty given + * particular attributes.
  • + *
+ * + * @author Shawn Bayern + * @author Jan Luehe + */ +public class JstlFmtTLV extends JstlBaseTLV { + + //********************************************************************* + // Implementation Overview + + /* + * We essentially just run the page through a SAX parser, handling + * the callbacks that interest us. We collapse elements + * into the text they contain, since this simplifies processing + * somewhat. Even a quick glance at the implementation shows its + * necessary, tree-oriented nature: multiple Stacks, an understanding + * of 'depth', and so on all are important as we recover necessary + * state upon each callback. This TLV demonstrates various techniques, + * from the general "how do I use a SAX parser for a TLV?" to + * "how do I read my init parameters and then validate?" But also, + * the specific SAX methodology was kept as general as possible to + * allow for experimentation and flexibility. + * + * Much of the code and structure is duplicated from JstlCoreTLV. + * An effort has been made to re-use code where unambiguously useful. + * However, splitting logic among parent/child classes isn't + * necessarily the cleanest approach when writing a parser like the + * one we need. I'd like to reorganize this somewhat, but it's not + * a priority. + */ + + + //********************************************************************* + // Constants + + // tag names + private static final String SETLOCALE = "setLocale"; + private static final String SETBUNDLE = "setBundle"; + private static final String SETTIMEZONE = "setTimeZone"; + private static final String BUNDLE = "bundle"; + private static final String MESSAGE = "message"; + private static final String MESSAGE_PARAM = "param"; + private static final String FORMAT_NUMBER = "formatNumber"; + private static final String PARSE_NUMBER = "parseNumber"; + private static final String PARSE_DATE = "parseDate"; + private static final String JSP_TEXT = "jsp:text"; + + // attribute names + private static final String EVAL = "evaluator"; + private static final String MESSAGE_KEY = "key"; + private static final String BUNDLE_PREFIX = "prefix"; + private static final String VALUE = "value"; + + + //********************************************************************* + // set its type and delegate validation to super-class + + @Override + public ValidationMessage[] validate( + String prefix, String uri, PageData page) { + return super.validate(TYPE_FMT, prefix, uri, page); + } + + + //********************************************************************* + // Contract fulfillment + + @Override + protected DefaultHandler getHandler() { + return new Handler(); + } + + + //********************************************************************* + // SAX event handler + + /** + * The handler that provides the base of our implementation. + */ + private class Handler extends DefaultHandler { + + // parser state + private int depth = 0; + private Stack messageDepths = new Stack(); + private String lastElementName = null; + private boolean bodyNecessary = false; + private boolean bodyIllegal = false; + + // process under the existing context (state), then modify it + + @Override + public void startElement( + String ns, String ln, String qn, Attributes a) { + + // substitute our own parsed 'ln' if it's not provided + if (ln == null) { + ln = getLocalPart(qn); + } + + // for simplicity, we can ignore for our purposes + // (don't bother distinguishing between it and its characters) + if (qn.equals(JSP_TEXT)) { + return; + } + + // check body-related constraint + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", + lastElementName)); + } + + // validate expression syntax if we need to + Set expAtts; + if (qn.startsWith(prefix + ":") + && (expAtts = (Set) config.get(ln)) != null) { + for (int i = 0; i < a.getLength(); i++) { + String attName = a.getLocalName(i); + if (expAtts.contains(attName)) { + String vMsg = + validateExpression( + ln, + attName, + a.getValue(i)); + if (vMsg != null) { + fail(vMsg); + } + } + } + } + + // validate attributes + if (qn.startsWith(prefix + ":") && !hasNoInvalidScope(a)) { + fail(Resources.getMessage("TLV_INVALID_ATTRIBUTE", + SCOPE, qn, a.getValue(SCOPE))); + } + if (qn.startsWith(prefix + ":") && hasEmptyVar(a)) { + fail(Resources.getMessage("TLV_EMPTY_VAR", qn)); + } + if (qn.startsWith(prefix + ":") + && !isFmtTag(ns, ln, SETLOCALE) + && !isFmtTag(ns, ln, SETBUNDLE) + && !isFmtTag(ns, ln, SETTIMEZONE) + && hasDanglingScope(a)) { + fail(Resources.getMessage("TLV_DANGLING_SCOPE", qn)); + } + + /* + * Make sure is nested inside . Note that + * does not need to be a direct child of . + * Otherwise, the following would not work: + * + * + * + * + * + * + */ + if (isFmtTag(ns, ln, MESSAGE_PARAM) && messageDepths.empty()) { + fail(Resources.getMessage("PARAM_OUTSIDE_MESSAGE")); + } + + // now, modify state + + // If we're in a , record relevant state + if (isFmtTag(ns, ln, MESSAGE)) { + messageDepths.push(new Integer(depth)); + } + + // set up a check against illegal attribute/body combinations + bodyIllegal = false; + bodyNecessary = false; + if (isFmtTag(ns, ln, MESSAGE_PARAM) + || isFmtTag(ns, ln, FORMAT_NUMBER) + || isFmtTag(ns, ln, PARSE_NUMBER) + || isFmtTag(ns, ln, PARSE_DATE)) { + if (hasAttribute(a, VALUE)) { + bodyIllegal = true; + } else { + bodyNecessary = true; + } + } else if (isFmtTag(ns, ln, MESSAGE) + && !hasAttribute(a, MESSAGE_KEY)) { + bodyNecessary = true; + } else if (isFmtTag(ns, ln, BUNDLE) + && hasAttribute(a, BUNDLE_PREFIX)) { + bodyNecessary = true; + } + + // record the most recent tag (for error reporting) + lastElementName = qn; + lastElementId = a.getValue(JSP, "id"); + + // we're a new element, so increase depth + depth++; + } + + @Override + public void characters(char[] ch, int start, int length) { + + bodyNecessary = false; // body is no longer necessary! + + // ignore strings that are just whitespace + String s = new String(ch, start, length).trim(); + if (s.equals("")) { + return; + } + + // check and update body-related constraints + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", + lastElementName)); + } + } + + @Override + public void endElement(String ns, String ln, String qn) { + + // consistently, we ignore JSP_TEXT + if (qn.equals(JSP_TEXT)) { + return; + } + + // handle body-related invariant + if (bodyNecessary) { + fail(Resources.getMessage("TLV_MISSING_BODY", + lastElementName)); + } + bodyIllegal = false; // reset: we've left the tag + + // update -related state + if (isFmtTag(ns, ln, MESSAGE)) { + messageDepths.pop(); + } + + // update our depth + depth--; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlSqlTLV.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlSqlTLV.java new file mode 100644 index 000000000..a27937c0f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlSqlTLV.java @@ -0,0 +1,251 @@ +/* + * 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.taglibs.standard.tlv; + +import java.util.Set; +import java.util.Stack; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.ValidationMessage; + +import org.apache.taglibs.standard.resources.Resources; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A SAX-based TagLibraryValidator for the JSTL SQL tag library. + * + * @author Shawn Bayern + */ +public class JstlSqlTLV extends JstlBaseTLV { + + //********************************************************************* + // Constants + + // tag names + private static final String SETDATASOURCE = "setDataSource"; + private static final String QUERY = "query"; + private static final String UPDATE = "update"; + private static final String TRANSACTION = "transaction"; + private static final String PARAM = "param"; + private static final String DATEPARAM = "dateParam"; + + private static final String JSP_TEXT = "jsp:text"; + + // attribute names + private static final String SQL = "sql"; + private static final String DATASOURCE = "dataSource"; + + + //********************************************************************* + // set its type and delegate validation to super-class + + @Override + public ValidationMessage[] validate( + String prefix, String uri, PageData page) { + return super.validate(TYPE_SQL, prefix, uri, page); + } + + + //********************************************************************* + // Contract fulfillment + + @Override + protected DefaultHandler getHandler() { + return new Handler(); + } + + + //********************************************************************* + // SAX event handler + + /** + * The handler that provides the base of our implementation. + */ + private class Handler extends DefaultHandler { + + // parser state + private int depth = 0; + private Stack queryDepths = new Stack(); + private Stack updateDepths = new Stack(); + private Stack transactionDepths = new Stack(); + private String lastElementName = null; + private boolean bodyNecessary = false; + private boolean bodyIllegal = false; + + // process under the existing context (state), then modify it + + @Override + public void startElement( + String ns, String ln, String qn, Attributes a) { + + // substitute our own parsed 'ln' if it's not provided + if (ln == null) { + ln = getLocalPart(qn); + } + + // for simplicity, we can ignore for our purposes + // (don't bother distinguishing between it and its characters) + if (qn.equals(JSP_TEXT)) { + return; + } + + // check body-related constraint + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + + // validate expression syntax if we need to + Set expAtts; + if (qn.startsWith(prefix + ":") + && (expAtts = (Set) config.get(ln)) != null) { + for (int i = 0; i < a.getLength(); i++) { + String attName = a.getLocalName(i); + if (expAtts.contains(attName)) { + String vMsg = + validateExpression( + ln, + attName, + a.getValue(i)); + if (vMsg != null) { + fail(vMsg); + } + } + } + } + + // validate attributes + if (qn.startsWith(prefix + ":") && !hasNoInvalidScope(a)) { + fail(Resources.getMessage("TLV_INVALID_ATTRIBUTE", + SCOPE, qn, a.getValue(SCOPE))); + } + if (qn.startsWith(prefix + ":") && hasEmptyVar(a)) { + fail(Resources.getMessage("TLV_EMPTY_VAR", qn)); + } + if (qn.startsWith(prefix + ":") && hasDanglingScope(a) && + !qn.startsWith(prefix + ":" + SETDATASOURCE)) { + fail(Resources.getMessage("TLV_DANGLING_SCOPE", qn)); + } + + // now, modify state + + /* + * Make sure is nested inside or + * . Note that does not need to + * be a direct child of or . + * Otherwise, the following would not work: + * + * + * + * + * + * + */ + if ((isSqlTag(ns, ln, PARAM) || isSqlTag(ns, ln, DATEPARAM)) + && (queryDepths.empty() && updateDepths.empty())) { + fail(Resources.getMessage("SQL_PARAM_OUTSIDE_PARENT")); + } + + // If we're in a , record relevant state + if (isSqlTag(ns, ln, QUERY)) { + queryDepths.push(new Integer(depth)); + } + // If we're in a , record relevant state + if (isSqlTag(ns, ln, UPDATE)) { + updateDepths.push(new Integer(depth)); + } + // If we're in a , record relevant state + if (isSqlTag(ns, ln, TRANSACTION)) { + transactionDepths.push(new Integer(depth)); + } + + // set up a check against illegal attribute/body combinations + bodyIllegal = false; + bodyNecessary = false; + + if (isSqlTag(ns, ln, QUERY) || isSqlTag(ns, ln, UPDATE)) { + if (!hasAttribute(a, SQL)) { + bodyNecessary = true; + } + if (hasAttribute(a, DATASOURCE) && !transactionDepths.empty()) { + fail(Resources.getMessage("ERROR_NESTED_DATASOURCE")); + } + } + + if (isSqlTag(ns, ln, DATEPARAM)) { + bodyIllegal = true; + } + + // record the most recent tag (for error reporting) + lastElementName = qn; + lastElementId = a.getValue("http://java.sun.com/JSP/Page", "id"); + + // we're a new element, so increase depth + depth++; + } + + @Override + public void characters(char[] ch, int start, int length) { + + bodyNecessary = false; // body is no longer necessary! + + // ignore strings that are just whitespace + String s = new String(ch, start, length).trim(); + if (s.equals("")) { + return; + } + + // check and update body-related constraints + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + } + + @Override + public void endElement(String ns, String ln, String qn) { + + // consistently, we ignore JSP_TEXT + if (qn.equals(JSP_TEXT)) { + return; + } + + // handle body-related invariant + if (bodyNecessary) { + fail(Resources.getMessage("TLV_MISSING_BODY", + lastElementName)); + } + bodyIllegal = false; // reset: we've left the tag + + // update -related state + if (isSqlTag(ns, ln, QUERY)) { + queryDepths.pop(); + } + // update -related state + if (isSqlTag(ns, ln, UPDATE)) { + updateDepths.pop(); + } + // update -related state + if (isSqlTag(ns, ln, TRANSACTION)) { + transactionDepths.pop(); + } + + // update our depth + depth--; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlXmlTLV.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlXmlTLV.java new file mode 100644 index 000000000..bb9c79eda --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/tlv/JstlXmlTLV.java @@ -0,0 +1,334 @@ +/* + * 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.taglibs.standard.tlv; + +import java.util.Set; +import java.util.Stack; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.ValidationMessage; + +import org.apache.taglibs.standard.resources.Resources; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A SAX-based TagLibraryValidator for the JSTL XML library. + * Currently implements the following checks:

+ *
    + *
  • Expression syntax validation. + *
  • Choose / when / otherwise constraints
  • + *
  • Tag bodies that must either be empty or non-empty given + * particular attributes.
  • + *
  • Other minor constraints.
  • + *
+ * + * @author Shawn Bayern + */ +public class JstlXmlTLV extends JstlBaseTLV { + + //********************************************************************* + // Implementation Overview + + /* + * We essentially just run the page through a SAX parser, handling + * the callbacks that interest us. We collapse elements + * into the text they contain, since this simplifies processing + * somewhat. Even a quick glance at the implementation shows its + * necessary, tree-oriented nature: multiple Stacks, an understanding + * of 'depth', and so on all are important as we recover necessary + * state upon each callback. This TLV demonstrates various techniques, + * from the general "how do I use a SAX parser for a TLV?" to + * "how do I read my init parameters and then validate?" But also, + * the specific SAX methodology was kept as general as possible to + * allow for experimentation and flexibility. + * + * Much of the code and structure is duplicated from JstlCoreTLV. + * An effort has been made to re-use code where unambiguously useful. + * However, splitting logic among parent/child classes isn't + * necessarily the cleanest approach when writing a parser like the + * one we need. I'd like to reorganize this somewhat, but it's not + * a priority. + */ + + + //********************************************************************* + // Constants + + // tag names + private static final String CHOOSE = "choose"; + private static final String WHEN = "when"; + private static final String OTHERWISE = "otherwise"; + private static final String PARSE = "parse"; + private static final String PARAM = "param"; + private static final String TRANSFORM = "transform"; + private static final String JSP_TEXT = "jsp:text"; + + // attribute names + private static final String VALUE = "value"; + private static final String SOURCE = "xml"; + + + //********************************************************************* + // set its type and delegate validation to super-class + + @Override + public ValidationMessage[] validate( + String prefix, String uri, PageData page) { + return super.validate(TYPE_XML, prefix, uri, page); + } + + + //********************************************************************* + // Contract fulfillment + + @Override + protected DefaultHandler getHandler() { + return new Handler(); + } + + + //********************************************************************* + // SAX event handler + + /** + * The handler that provides the base of our implementation. + */ + private class Handler extends DefaultHandler { + + // parser state + private int depth = 0; + private Stack chooseDepths = new Stack(); + private Stack chooseHasOtherwise = new Stack(); + private Stack chooseHasWhen = new Stack(); + private String lastElementName = null; + private boolean bodyNecessary = false; + private boolean bodyIllegal = false; + private Stack transformWithSource = new Stack(); + + // process under the existing context (state), then modify it + + @Override + public void startElement( + String ns, String ln, String qn, Attributes a) { + + // substitute our own parsed 'ln' if it's not provided + if (ln == null) { + ln = getLocalPart(qn); + } + + // for simplicity, we can ignore for our purposes + // (don't bother distinguishing between it and its characters) + if (qn.equals(JSP_TEXT)) { + return; + } + + // check body-related constraint + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + + // validate expression syntax if we need to + Set expAtts; + if (qn.startsWith(prefix + ":") + && (expAtts = (Set) config.get(ln)) != null) { + for (int i = 0; i < a.getLength(); i++) { + String attName = a.getLocalName(i); + if (expAtts.contains(attName)) { + String vMsg = + validateExpression( + ln, + attName, + a.getValue(i)); + if (vMsg != null) { + fail(vMsg); + } + } + } + } + + // validate attributes + if (qn.startsWith(prefix + ":") && !hasNoInvalidScope(a)) { + fail(Resources.getMessage("TLV_INVALID_ATTRIBUTE", + SCOPE, qn, a.getValue(SCOPE))); + } + if (qn.startsWith(prefix + ":") && hasEmptyVar(a)) { + fail(Resources.getMessage("TLV_EMPTY_VAR", qn)); + } + if (qn.startsWith(prefix + ":") && hasDanglingScope(a)) { + fail(Resources.getMessage("TLV_DANGLING_SCOPE", qn)); + } + + // check invariants for + if (chooseChild()) { + // mark for the first the first + if (isXmlTag(ns, ln, WHEN)) { + chooseHasWhen.pop(); + chooseHasWhen.push(Boolean.TRUE); + } + + // ensure has the right children + if (!isXmlTag(ns, ln, WHEN) && !isXmlTag(ns, ln, OTHERWISE)) { + fail(Resources.getMessage("TLV_ILLEGAL_CHILD_TAG", + prefix, CHOOSE, qn)); + } + + // make sure is the last tag + if (((Boolean) chooseHasOtherwise.peek()).booleanValue()) { + fail(Resources.getMessage("TLV_ILLEGAL_ORDER", + qn, prefix, OTHERWISE, CHOOSE)); + } + if (isXmlTag(ns, ln, OTHERWISE)) { + chooseHasOtherwise.pop(); + chooseHasOtherwise.push(Boolean.TRUE); + } + + } + + // Specific check, directly inside + if (!transformWithSource.empty() && + topDepth(transformWithSource) == (depth - 1)) { + // only allow + if (!isXmlTag(ns, ln, PARAM)) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", + prefix + ":" + TRANSFORM)); + } + + // thus, if we get the opportunity to hit depth++, + // we know we've got a subtag + } + + // now, modify state + + // we're a choose, so record new choose-specific state + if (isXmlTag(ns, ln, CHOOSE)) { + chooseDepths.push(new Integer(depth)); + chooseHasWhen.push(Boolean.FALSE); + chooseHasOtherwise.push(Boolean.FALSE); + } + + // set up a check against illegal attribute/body combinations + bodyIllegal = false; + bodyNecessary = false; + if (isXmlTag(ns, ln, PARSE)) { + if (hasAttribute(a, SOURCE)) { + bodyIllegal = true; + } + } else if (isXmlTag(ns, ln, PARAM)) { + if (hasAttribute(a, VALUE)) { + bodyIllegal = true; + } else { + bodyNecessary = true; + } + } else if (isXmlTag(ns, ln, TRANSFORM)) { + if (hasAttribute(a, SOURCE)) { + transformWithSource.push(new Integer(depth)); + } + } + + // record the most recent tag (for error reporting) + lastElementName = qn; + lastElementId = a.getValue("http://java.sun.com/JSP/Page", "id"); + + // we're a new element, so increase depth + depth++; + } + + @Override + public void characters(char[] ch, int start, int length) { + + bodyNecessary = false; // body is no longer necessary! + + // ignore strings that are just whitespace + String s = new String(ch, start, length).trim(); + if (s.equals("")) { + return; + } + + // check and update body-related constraints + if (bodyIllegal) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", lastElementName)); + } + + // make sure has no non-whitespace text + if (chooseChild()) { + String msg = + Resources.getMessage("TLV_ILLEGAL_TEXT_BODY", + prefix, CHOOSE, + (s.length() < 7 ? s : s.substring(0, 7))); + fail(msg); + } + + // Specific check, directly inside + if (!transformWithSource.empty() + && topDepth(transformWithSource) == (depth - 1)) { + fail(Resources.getMessage("TLV_ILLEGAL_BODY", + prefix + ":" + TRANSFORM)); + } + } + + @Override + public void endElement(String ns, String ln, String qn) { + + // consistently, we ignore JSP_TEXT + if (qn.equals(JSP_TEXT)) { + return; + } + + // handle body-related invariant + if (bodyNecessary) { + fail(Resources.getMessage("TLV_MISSING_BODY", + lastElementName)); + } + bodyIllegal = false; // reset: we've left the tag + + // update -related state + if (isXmlTag(ns, ln, CHOOSE)) { + Boolean b = (Boolean) chooseHasWhen.pop(); + if (!b.booleanValue()) { + fail(Resources.getMessage("TLV_PARENT_WITHOUT_SUBTAG", + CHOOSE, WHEN)); + } + chooseDepths.pop(); + chooseHasOtherwise.pop(); + } + + // update -related state + if (!transformWithSource.empty() + && topDepth(transformWithSource) == (depth - 1)) { + transformWithSource.pop(); + } + + // update our depth + depth--; + } + + // are we directly under a ? + + private boolean chooseChild() { + return (!chooseDepths.empty() + && (depth - 1) == ((Integer) chooseDepths.peek()).intValue()); + } + + // returns the top int depth (peeked at) from a Stack of Integer + + private int topDepth(Stack s) { + return ((Integer) s.peek()).intValue(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/EscapeXML.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/EscapeXML.java new file mode 100644 index 000000000..fc56feb5a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/EscapeXML.java @@ -0,0 +1,207 @@ +/* + * 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.taglibs.standard.util; + +import java.io.IOException; +import java.io.Reader; + +import jakarta.servlet.jsp.JspWriter; + +/** + * Handles escaping of characters that could be interpreted as XML markup. + *

The specification for <c:out> defines the following + * character conversions to be applied: + * + * + * + * + * + * + * + * + * + * + * + *
CharacterCharacter Entity Code
<&lt;
>&gt;
&&amp;
'&#039;
"&#034;
+ */ +public class EscapeXML { + + private static final String[] ESCAPES; + + static { + int size = '>' + 1; // '>' is the largest escaped value + ESCAPES = new String[size]; + ESCAPES['<'] = "<"; + ESCAPES['>'] = ">"; + ESCAPES['&'] = "&"; + ESCAPES['\''] = "'"; + ESCAPES['"'] = """; + } + + private static String getEscape(char c) { + if (c < ESCAPES.length) { + return ESCAPES[c]; + } else { + return null; + } + } + + /** + * Escape a string. + * + * @param src the string to escape; must not be null + * @return the escaped string + */ + public static String escape(String src) { + // first pass to determine the length of the buffer so we only allocate once + int length = 0; + for (int i = 0; i < src.length(); i++) { + char c = src.charAt(i); + String escape = getEscape(c); + if (escape != null) { + length += escape.length(); + } else { + length += 1; + } + } + + // skip copy if no escaping is needed + if (length == src.length()) { + return src; + } + + // second pass to build the escaped string + StringBuilder buf = new StringBuilder(length); + for (int i = 0; i < src.length(); i++) { + char c = src.charAt(i); + String escape = getEscape(c); + if (escape != null) { + buf.append(escape); + } else { + buf.append(c); + } + } + return buf.toString(); + } + + /** + * Emit the supplied object to the specified writer, escaping characters if needed. + * + * @param src the object to write + * @param escapeXml if true, escape unsafe characters before writing + * @param out the JspWriter to emit to + * @throws IOException if there was a problem emitting the content + */ + public static void emit(Object src, boolean escapeXml, JspWriter out) throws IOException { + if (src instanceof Reader) { + emit((Reader) src, escapeXml, out); + } else { + emit(String.valueOf(src), escapeXml, out); + } + } + + /** + * Emit the supplied String to the specified writer, escaping characters if needed. + * + * @param src the String to write + * @param escapeXml if true, escape unsafe characters before writing + * @param out the JspWriter to emit to + * @throws IOException if there was a problem emitting the content + */ + public static void emit(String src, boolean escapeXml, JspWriter out) throws IOException { + if (escapeXml) { + emit(src, out); + } else { + out.write(src); + } + } + + /** + * Emit escaped content into the specified JSPWriter. + * + * @param src the string to escape; must not be null + * @param out the JspWriter to emit to + * @throws IOException if there was a problem emitting the content + */ + public static void emit(String src, JspWriter out) throws IOException { + int end = src.length(); + int from = 0; + for (int to = from; to < end; to++) { + String escape = getEscape(src.charAt(to)); + if (escape != null) { + if (to != from) { + out.write(src, from, to - from); + } + out.write(escape); + from = to + 1; + } + } + if (from != end) { + out.write(src, from, end - from); + } + } + + /** + * Copy the content of a Reader into the specified JSPWriter escaping characters if needed. + * + * @param src the Reader to read from + * @param escapeXml if true, escape characters + * @param out the JspWriter to emit to + * @throws IOException if there was a problem emitting the content + */ + public static void emit(Reader src, boolean escapeXml, JspWriter out) throws IOException { + int bufferSize = out.getBufferSize(); + if (bufferSize == 0) { + bufferSize = 4096; + } + char[] buffer = new char[bufferSize]; + int count; + while ((count = src.read(buffer)) > 0) { + if (escapeXml) { + emit(buffer, 0, count, out); + } else { + out.write(buffer, 0, count); + } + } + } + + /** + * Emit escaped content into the specified JSPWriter. + * + * @param buffer characters to escape + * @param from start position in the buffer + * @param count number of characters to emit + * @param out the JspWriter to emit to + * @throws IOException if there was a problem emitting the content + */ + public static void emit(char[] buffer, int from, int count, JspWriter out) throws IOException { + int end = from + count; + for (int to = from; to < end; to++) { + String escape = getEscape(buffer[to]); + if (escape != null) { + if (to != from) { + out.write(buffer, from, to - from); + } + out.write(escape); + from = to + 1; + } + } + if (from != end) { + out.write(buffer, from, end - from); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/ExpressionUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/ExpressionUtil.java new file mode 100644 index 000000000..e72698531 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/ExpressionUtil.java @@ -0,0 +1,87 @@ +/* + * 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.taglibs.standard.util; + +import jakarta.el.ExpressionFactory; +import jakarta.el.ValueExpression; +import jakarta.servlet.jsp.JspApplicationContext; +import jakarta.servlet.jsp.JspFactory; +import jakarta.servlet.jsp.PageContext; + +/** + * Helper functions for working with EL expressions. + */ +public class ExpressionUtil { + + /** + * Create a value expression. + * + * @param pageContext the context in which the expression will be parsed + * @param expression the expression + * @param expectedType the expected type of result + * @return a parsed expression + */ + public static ValueExpression createValueExpression(PageContext pageContext, String expression, Class expectedType) { + ExpressionFactory factory = getExpressionFactory(pageContext); + return factory.createValueExpression(pageContext.getELContext(), expression, expectedType); + } + + /** + * Return the JSP's ExpressionFactory. + * + * @param pageContext the context for the JSP + * @return the ExpressionFactory to use for EL expressions in that JSP + */ + public static ExpressionFactory getExpressionFactory(PageContext pageContext) { + JspApplicationContext appContext = JspFactory.getDefaultFactory().getJspApplicationContext(pageContext.getServletContext()); + return appContext.getExpressionFactory(); + } + + /** + * Evaluate a value expression. To support optional attributes, if the expression is null then + * null will be returned. + * + * @param expression the expression + * @param pageContext the context for the JSP + * @param the expected type of the expression + * @return the result of evaluating the expression + */ + public static T evaluate(ValueExpression expression, PageContext pageContext) { + if (expression == null) { + return null; + } + @SuppressWarnings("unchecked") + T value = (T) expression.getValue(pageContext.getELContext()); + return value; + } + + public static boolean evaluate(ValueExpression expression, PageContext pageContext, boolean fallback) { + if (expression == null) { + return fallback; + } + Boolean result = (Boolean) expression.getValue(pageContext.getELContext()); + return result == null ? fallback : result; + } + + public static int evaluate(ValueExpression expression, PageContext pageContext, int fallback) { + if (expression == null) { + return fallback; + } + Integer result = (Integer) expression.getValue(pageContext.getELContext()); + return result == null ? fallback : result; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UnclosableWriter.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UnclosableWriter.java new file mode 100644 index 000000000..912404778 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UnclosableWriter.java @@ -0,0 +1,47 @@ +/* + * 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.taglibs.standard.util; + +import java.io.IOException; +import java.io.Writer; + +/** + * A Writer based on a wrapped Writer but ignoring requests to + * close() and flush() it. (Someone must have wrapped the + * toilet in my office similarly...) + */ +public class UnclosableWriter extends Writer { + // TODO: shouldn't we be delegating all methods? + private Writer w; + + public UnclosableWriter(Writer w) { + this.w = w; + } + + @Override + public void close() { + } + + @Override + public void flush() { + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + w.write(cbuf, off, len); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UrlUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UrlUtil.java new file mode 100644 index 000000000..fae4a7f31 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/UrlUtil.java @@ -0,0 +1,95 @@ +/* + * 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.taglibs.standard.util; + +import java.util.BitSet; + +/** + * Utilities for working with URLs. + */ +public class UrlUtil { + /** + *

Valid characters in a scheme.

+ *

RFC 1738 says the following:

+ *
+ * Scheme names consist of a sequence of characters. The lower + * case letters "a"--"z", digits, and the characters plus ("+"), + * period ("."), and hyphen ("-") are allowed. For resiliency, + * programs interpreting URLs should treat upper case letters as + * equivalent to lower case in scheme names (e.g., allow "HTTP" as + * well as "http"). + *
+ *

We treat as absolute any URL that begins with such a scheme name, + * followed by a colon.

+ */ +/* + private static final String VALID_SCHEME_CHARS = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-"; +*/ + private static final BitSet VALID_SCHEME_CHARS; + static { + VALID_SCHEME_CHARS = new BitSet(128); + VALID_SCHEME_CHARS.set('A', 'Z' + 1); + VALID_SCHEME_CHARS.set('a', 'z' + 1); + VALID_SCHEME_CHARS.set('0', '9' + 1); + VALID_SCHEME_CHARS.set('+'); + VALID_SCHEME_CHARS.set('.'); + VALID_SCHEME_CHARS.set('-'); + } + + /** + * Determine if a URL is absolute by JSTL's definition. + */ + public static boolean isAbsoluteUrl(String url) { + // a null URL is not absolute, by our definition + if (url == null) { + return false; + } + + // do a fast, simple check first + int colonPos = url.indexOf(":"); + if (colonPos == -1) { + return false; + } + + // if we DO have a colon, make sure that every character + // leading up to it is a valid scheme character + for (int i = 0; i < colonPos; i++) { + if (!VALID_SCHEME_CHARS.get(url.charAt(i))) { + return false; + } + } + + // if so, we've got an absolute url + return true; + } + + public static String getScheme(CharSequence url) { + StringBuilder scheme = new StringBuilder(); + for (int i = 0; i < url.length(); i++) { + char ch = url.charAt(i); + if (ch == ':') { + String result = scheme.toString(); + if (!"jar".equals(result)) { + return result; + } + } + scheme.append(ch); + } + throw new IllegalArgumentException("No scheme found: " + url); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/XmlUtil.java b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/XmlUtil.java new file mode 100644 index 000000000..2efc8d2ca --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/java/org/apache/taglibs/standard/util/XmlUtil.java @@ -0,0 +1,408 @@ +/* + * 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.taglibs.standard.util; + +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.Reader; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.concurrent.Callable; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.PageContext; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.URIResolver; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.stream.StreamSource; + +import org.apache.taglibs.standard.resources.Resources; +import org.w3c.dom.Document; +import org.xml.sax.EntityResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.XMLReader; + +/** + * Utilities for working with JAXP and SAX. + */ +public class XmlUtil { + /* Cache factory classes when this class is initialized (since Java1.5 factories are required + * to be thread safe). + * + * As JavaEE 5 requires JSTL to be provided by the container we use our ClassLoader to locate + * the implementations rather than the application's. As we don't know the actual implementation + * class in use we can't use the newInstance() variant that allows the ClassLoader to be + * specified so we use the no-arg form and coerce the TCCL (which may be restricted by the + * AccessController). + */ + private static final DocumentBuilderFactory PARSER_FACTORY; + private static final SAXTransformerFactory TRANSFORMER_FACTORY; + private static final SAXParserFactory SAXPARSER_FACTORY; + static { + try { + PARSER_FACTORY = runWithOurClassLoader(new Callable() { + public DocumentBuilderFactory call() throws ParserConfigurationException { + return DocumentBuilderFactory.newInstance(); + } + }, ParserConfigurationException.class); + PARSER_FACTORY.setNamespaceAware(true); + PARSER_FACTORY.setValidating(false); + PARSER_FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + throw new ExceptionInInitializerError(e); + } + try { + TRANSFORMER_FACTORY = runWithOurClassLoader(new Callable() { + public SAXTransformerFactory call() throws TransformerConfigurationException { + TransformerFactory tf = TransformerFactory.newInstance(); + if (!(tf instanceof SAXTransformerFactory)) { + throw new TransformerConfigurationException("TransformerFactory does not support SAX"); + } + return (SAXTransformerFactory) tf; + } + }, TransformerConfigurationException.class); + TRANSFORMER_FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (TransformerConfigurationException e) { + throw new ExceptionInInitializerError(e); + } + try { + SAXPARSER_FACTORY = runWithOurClassLoader(new Callable() { + public SAXParserFactory call() { + return SAXParserFactory.newInstance(); + } + }, RuntimeException.class); + SAXPARSER_FACTORY.setNamespaceAware(true); + SAXPARSER_FACTORY.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException|SAXNotRecognizedException|SAXNotSupportedException e) { + throw new ExceptionInInitializerError(e); + } + } + + private static final String SP_ALLOWED_PROTOCOLS = "org.apache.taglibs.standard.xml.accessExternalEntity"; + private static final String ALLOWED_PROTOCOLS = initAllowedProtocols(); + + private static String initAllowedProtocols() { + if (System.getSecurityManager() == null) { + return System.getProperty(SP_ALLOWED_PROTOCOLS, "all"); + } else { + final String defaultProtocols = ""; + try { + return AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return System.getProperty(SP_ALLOWED_PROTOCOLS, defaultProtocols); + } + }); + } catch (AccessControlException e) { + // Fall back to the default i.e. none. + return defaultProtocols; + } + } + } + + static void checkProtocol(String allowedProtocols, String uri) { + if ("all".equalsIgnoreCase(allowedProtocols)) { + return; + } + String protocol = UrlUtil.getScheme(uri); + for (String allowed : allowedProtocols.split(",")) { + if (allowed.trim().equalsIgnoreCase(protocol)) { + return; + } + } + throw new AccessControlException("Access to external URI not allowed: " + uri); + } + + /** + * Create a new empty document. + * + * @return a new empty document + */ + public static Document newEmptyDocument() { + return newDocumentBuilder().newDocument(); + } + + /** + * Create a new DocumentBuilder configured for namespaces but not validating. + * + * @return a new, configured DocumentBuilder + */ + public static DocumentBuilder newDocumentBuilder() { + try { + return PARSER_FACTORY.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw (Error) new AssertionError().initCause(e); + } + } + + /** + * Create a new TransformerHandler. + * @return a new TransformerHandler + */ + public static TransformerHandler newTransformerHandler() throws TransformerConfigurationException { + return TRANSFORMER_FACTORY.newTransformerHandler(); + } + + /** + * Create a new Transformer from an XSLT. + * @param source the source of the XSLT. + * @return a new Transformer + * @throws TransformerConfigurationException if there was a problem creating the Transformer from the XSLT + */ + public static Transformer newTransformer(Source source, JstlUriResolver uriResolver) throws TransformerConfigurationException { + synchronized (TRANSFORMER_FACTORY) { + final URIResolver original = TRANSFORMER_FACTORY.getURIResolver(); + try { + TRANSFORMER_FACTORY.setURIResolver(uriResolver); + Transformer transformer = TRANSFORMER_FACTORY.newTransformer(source); + // Although newTransformer() is not allowed to return null, Xalan does. + // Trap that here by throwing the expected TransformerConfigurationException. + if (transformer == null) { + throw new TransformerConfigurationException("newTransformer returned null. XSLT may be invalid."); + } + return transformer; + } finally { + //restore URI resolver on factory to what was before + TRANSFORMER_FACTORY.setURIResolver(original); + } + } + } + + /** + * Create an InputSource from a Reader. + * + * The systemId will be wrapped for use with JSTL's EntityResolver and UriResolver. + * + * @param reader the source of the XML + * @param systemId the system id + * @return a configured InputSource + */ + public static InputSource newInputSource(Reader reader, String systemId) { + InputSource source = new InputSource(reader); + source.setSystemId(wrapSystemId(systemId)); + return source; + } + + /** + * Create an XMLReader that resolves entities using JSTL semantics. + * @param entityResolver for resolving using JSTL semantics + * @return a new XMLReader + * @throws ParserConfigurationException if there was a configuration problem creating the reader + * @throws SAXException if there was a problem creating the reader + */ + public static XMLReader newXMLReader(JstlEntityResolver entityResolver) + throws ParserConfigurationException, SAXException { + XMLReader xmlReader = SAXPARSER_FACTORY.newSAXParser().getXMLReader(); + xmlReader.setEntityResolver(entityResolver); + return xmlReader; + } + + /** + * Create a SAXSource from a Reader. Any entities will be resolved using JSTL semantics. + * + * @param reader the source of the XML + * @param systemId the system id + * @param entityResolver for resolving using JSTL semamtics + * @return a new SAXSource + * @throws ParserConfigurationException if there was a configuration problem creating the source + * @throws SAXException if there was a problem creating the source + */ + public static SAXSource newSAXSource(Reader reader, String systemId, JstlEntityResolver entityResolver) + throws ParserConfigurationException, SAXException { + SAXSource source = new SAXSource(newXMLReader(entityResolver), new InputSource(reader)); + source.setSystemId(wrapSystemId(systemId)); + return source; + } + + /** + * Wraps systemId with a "jstl:" prefix to prevent the parser from + * thinking that the URI is truly relative and resolving it against + * the current directory in the filesystem. + */ + private static String wrapSystemId(String systemId) { + if (systemId == null) { + return "jstl:"; + } else if (UrlUtil.isAbsoluteUrl(systemId)) { + return systemId; + } else { + return ("jstl:" + systemId); + } + } + + /** + * JSTL-specific implementation of EntityResolver, used by parsers. + */ + public static class JstlEntityResolver implements EntityResolver { + private final PageContext ctx; + + public JstlEntityResolver(PageContext ctx) { + this.ctx = ctx; + } + + public InputSource resolveEntity(String publicId, String systemId) throws FileNotFoundException { + + // pass if we don't have a systemId + if (systemId == null) { + return null; + } + + // strip leading "jstl:" off URL if applicable + if (systemId.startsWith("jstl:")) { + systemId = systemId.substring(5); + } + + // we're only concerned with relative URLs + if (UrlUtil.isAbsoluteUrl(systemId)) { + checkProtocol(ALLOWED_PROTOCOLS, systemId); + return null; + } + + // for relative URLs, load and wrap the resource. + // don't bother checking for 'null' since we specifically want + // the parser to fail if the resource doesn't exist + String path = systemId; + if (!path.startsWith("/")) { + String pagePath = ((HttpServletRequest) ctx.getRequest()).getServletPath(); + String basePath = pagePath.substring(0, pagePath.lastIndexOf("/")); + path = basePath + "/" + systemId; + } + + InputStream s = ctx.getServletContext().getResourceAsStream(path); + if (s == null) { + throw new FileNotFoundException(Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", systemId)); + } + return new InputSource(s); + } + } + + /** + * JSTL-specific implementation of URIResolver, used by transformers. + */ + public static class JstlUriResolver implements URIResolver { + private final PageContext ctx; + + public JstlUriResolver(PageContext ctx) { + this.ctx = ctx; + } + + public Source resolve(String href, String base) throws TransformerException { + + // pass if we don't have a systemId + if (href == null) { + return null; + } + + // remove "jstl" marker from 'base' + // NOTE: how 'base' is determined varies among different Xalan + // xsltc implementations + int index; + if (base != null && (index = base.indexOf("jstl:")) != -1) { + base = base.substring(index + 5); + } + + // we're only concerned with relative URLs + if (UrlUtil.isAbsoluteUrl(href)) { + checkProtocol(ALLOWED_PROTOCOLS, href); + return null; + } + if (base != null && UrlUtil.isAbsoluteUrl(base)) { + checkProtocol(ALLOWED_PROTOCOLS, base); + return null; + } + + // base is relative; remove everything after trailing '/' + if (base == null || base.lastIndexOf("/") == -1) { + base = ""; + } else { + base = base.substring(0, base.lastIndexOf("/") + 1); + } + + // concatenate to produce the real URL we're interested in + String target = base + href; + + // for relative URLs, load and wrap the resource. + // don't bother checking for 'null' since we specifically want + // the parser to fail if the resource doesn't exist + if (!target.startsWith("/")) { + String pagePath = ((HttpServletRequest) ctx.getRequest()).getServletPath(); + String basePath = pagePath.substring(0, pagePath.lastIndexOf("/")); + target = basePath + "/" + target; + } + InputStream s = ctx.getServletContext().getResourceAsStream(target); + if (s == null) { + throw new TransformerException(Resources.getMessage("UNABLE_TO_RESOLVE_ENTITY", href)); + } + return new StreamSource(s); + } + } + + /** + * Performs an action using this Class's ClassLoader as the Thread context ClassLoader. + * + * @param action the action to perform + * @param allowed an Exception that might be thrown by the action + * @param the type of the result + * @param the type of the allowed Exception + * @return the result of the action + * @throws E if the action threw the allowed Exception + */ + private static T runWithOurClassLoader(final Callable action, Class allowed) throws E { + PrivilegedExceptionAction actionWithClassloader = new PrivilegedExceptionAction() { + public T run() throws Exception { + ClassLoader original = Thread.currentThread().getContextClassLoader(); + ClassLoader ours = XmlUtil.class.getClassLoader(); + // Don't override the TCCL if it is not needed. + if (original == ours) { + return action.call(); + } else { + try { + Thread.currentThread().setContextClassLoader(ours); + return action.call(); + } finally { + Thread.currentThread().setContextClassLoader(original); + } + } + } + }; + try { + return AccessController.doPrivileged(actionWithClassloader); + } catch (PrivilegedActionException e) { + Throwable cause = e.getCause(); + if (allowed.isInstance(cause)) { + throw allowed.cast(cause); + } else { + throw (Error) new AssertionError().initCause(cause); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_0-rt.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_0-rt.tld new file mode 100644 index 000000000..72ca2d14a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_0-rt.tld @@ -0,0 +1,409 @@ + + + + + 1.0 + 1.2 + c_rt + http://java.sun.com/jstl/core_rt + JSTL core RT + JSTL 1.0 core library + + + + org.apache.taglibs.standard.tlv.JstlCoreTLV + + + Provides core validation features for JSTL tags. + + + + + catch + org.apache.taglibs.standard.tag.common.core.CatchTag + JSP + + Catches any Throwable that occurs in its body and optionally + exposes it. + + + var + false + false + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + if + org.apache.taglibs.standard.tag.rt.core.IfTag + JSP + + 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 + + + test + true + true + boolean + + + var + false + false + + + scope + false + false + + + + + import + org.apache.taglibs.standard.tag.rt.core.ImportTag + org.apache.taglibs.standard.tei.ImportTEI + JSP + + Retrieves an absolute or relative URL and exposes its contents + to either the page, a String in 'var', or a Reader in 'varReader'. + + + url + true + true + + + var + false + false + + + scope + false + false + + + varReader + false + false + + + context + false + true + + + charEncoding + false + true + + + + + forEach + org.apache.taglibs.standard.tag.rt.core.ForEachTag + org.apache.taglibs.standard.tei.ForEachTEI + JSP + + The basic iteration tag, accepting many different + collection types and supporting subsetting and other + functionality + + + items + false + true + java.lang.Object + + + begin + false + true + int + + + end + false + true + int + + + step + false + true + int + + + var + false + false + + + varStatus + false + false + + + + + forTokens + org.apache.taglibs.standard.tag.rt.core.ForTokensTag + JSP + + Iterates over tokens, separated by the supplied delimeters + + + items + true + true + java.lang.String + + + delims + true + true + java.lang.String + + + begin + false + true + int + + + end + false + true + int + + + step + false + true + int + + + var + false + false + + + varStatus + false + false + + + + + out + org.apache.taglibs.standard.tag.rt.core.OutTag + JSP + + Like <%= ... >, but for expressions. + + + value + true + true + + + default + false + true + + + escapeXml + false + true + + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.rt.core.ParamTag + JSP + + Adds a parameter to a containing 'import' tag's URL. + + + name + true + true + + + value + false + true + + + + + redirect + org.apache.taglibs.standard.tag.rt.core.RedirectTag + JSP + + Redirects to a new URL. + + + var + false + false + + + scope + false + false + + + url + false + true + + + context + false + true + + + + + remove + org.apache.taglibs.standard.tag.common.core.RemoveTag + empty + + Removes a scoped variable (from a particular scope, if specified). + + + var + true + false + + + scope + false + false + + + + + set + org.apache.taglibs.standard.tag.rt.core.SetTag + JSP + + Sets the result of an expression evaluation in a 'scope' + + + var + false + false + + + value + false + true + + + target + false + true + + + property + false + true + + + scope + false + false + + + + + url + org.apache.taglibs.standard.tag.rt.core.UrlTag + JSP + + Creates a URL with optional query parameters. + + + var + false + false + + + scope + false + false + + + value + false + true + + + context + false + true + + + + + when + org.apache.taglibs.standard.tag.rt.core.WhenTag + JSP + + Subtag of <choose> that includes its body if its + condition evalutes to 'true' + + + test + true + true + boolean + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_1.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_1.tld new file mode 100644 index 000000000..98a6b17ad --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c-1_1.tld @@ -0,0 +1,578 @@ + + + + + JSTL 1.1 core library + JSTL core + 1.1 + c + http://java.sun.com/jsp/jstl/core_1_1 + + + + Provides core validation features for JSTL tags. + + + org.apache.taglibs.standard.tlv.JstlCoreTLV + + + + + + Catches any Throwable that occurs in its body and optionally + exposes it. + + catch + org.apache.taglibs.standard.tag.common.core.CatchTag + JSP + + + 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. + + var + false + false + + + + + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + + + + 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 + + if + org.apache.taglibs.standard.tag.rt.core.IfTag + JSP + + + The test condition that determines whether or + not the body content should be processed. + + test + true + true + boolean + + + + Name of the exported scoped variable for the + resulting value of the test condition. The type + of the scoped variable is Boolean. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + + + Retrieves an absolute or relative URL and exposes its contents + to either the page, a String in 'var', or a Reader in 'varReader'. + + import + org.apache.taglibs.standard.tag.rt.core.ImportTag + org.apache.taglibs.standard.tei.ImportTEI + JSP + + + The URL of the resource to import. + + url + true + true + + + + Name of the exported scoped variable for the + resource's content. The type of the scoped + variable is String. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + Name of the exported scoped variable for the + resource's content. The type of the scoped + variable is Reader. + + varReader + false + false + + + + Name of the context when accessing a relative + URL resource that belongs to a foreign + context. + + context + false + true + + + + Character encoding of the content at the input + resource. + + charEncoding + false + true + + + + + + The basic iteration tag, accepting many different + collection types and supporting subsetting and other + functionality + + forEach + org.apache.taglibs.standard.tag.rt.core.ForEachTag + org.apache.taglibs.standard.tei.ForEachTEI + JSP + + + Collection of items to iterate over. + + items + false + true + java.lang.Object + + + + 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. + + begin + false + true + int + + + + 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. + + end + false + true + int + + + + Iteration will only process every step items of + the collection, starting with the first one. + + step + false + true + int + + + + 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. + + var + false + false + + + + 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. + + varStatus + false + false + + + + + + Iterates over tokens, separated by the supplied delimeters + + forTokens + org.apache.taglibs.standard.tag.rt.core.ForTokensTag + JSP + + + String of tokens to iterate over. + + items + true + true + java.lang.String + + + + The set of delimiters (the characters that + separate the tokens in the string). + + delims + true + true + java.lang.String + + + + Iteration begins at the token located at the + specified index. First token has index 0. + + begin + false + true + int + + + + Iteration ends at the token located at the + specified index (inclusive). + + end + false + true + int + + + + Iteration will only process every step tokens + of the string, starting with the first one. + + step + false + true + int + + + + Name of the exported scoped variable for the + current item of the iteration. This scoped + variable has nested visibility. + + var + false + false + + + + 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. + + varStatus + false + false + + + + + + Like <%= ... >, but for expressions. + + out + org.apache.taglibs.standard.tag.rt.core.OutTag + JSP + + + Expression to be evaluated. + + value + true + true + + + + Default value if the resulting value is null. + + default + false + true + + + + Determines whether characters <,>,&,'," in the + resulting string should be converted to their + corresponding character entity codes. Default value is + true. + + escapeXml + false + true + + + + + + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + + + + Adds a parameter to a containing 'import' tag's URL. + + param + org.apache.taglibs.standard.tag.rt.core.ParamTag + JSP + + + Name of the query string parameter. + + name + true + true + + + + Value of the parameter. + + value + false + true + + + + + + Redirects to a new URL. + + redirect + org.apache.taglibs.standard.tag.rt.core.RedirectTag + JSP + + + The URL of the resource to redirect to. + + url + false + true + + + + Name of the context when redirecting to a relative URL + resource that belongs to a foreign context. + + context + false + true + + + + + + Removes a scoped variable (from a particular scope, if specified). + + remove + org.apache.taglibs.standard.tag.common.core.RemoveTag + empty + + + Name of the scoped variable to be removed. + + var + true + false + + + + Scope for var. + + scope + false + false + + + + + + Sets the result of an expression evaluation in a 'scope' + + set + org.apache.taglibs.standard.tag.rt.core.SetTag + JSP + + + 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. + + var + false + false + + + + Expression to be evaluated. + + value + false + true + + + + Target object whose property will be set. Must evaluate to + a JavaBeans object with setter property property, or to a + java.util.Map object. + + target + false + true + + + + Name of the property to be set in the target object. + + property + false + true + + + + Scope for var. + + scope + false + false + + + + + + Creates a URL with optional query parameters. + + url + org.apache.taglibs.standard.tag.rt.core.UrlTag + JSP + + + Name of the exported scoped variable for the + processed url. The type of the scoped variable is + String. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + URL to be processed. + + value + false + true + + + + Name of the context when specifying a relative URL + resource that belongs to a foreign context. + + context + false + true + + + + + + Subtag of <choose> that includes its body if its + condition evalutes to 'true' + + when + org.apache.taglibs.standard.tag.rt.core.WhenTag + JSP + + + The test condition that determines whether or not the + body content should be processed. + + test + true + true + boolean + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c.tld new file mode 100644 index 000000000..f372da845 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/c.tld @@ -0,0 +1,587 @@ + + + + + JSTL 1.2 core library + JSTL core + 1.2 + c + http://java.sun.com/jsp/jstl/core + + + + Provides core validation features for JSTL tags. + + + org.apache.taglibs.standard.tlv.JstlCoreTLV + + + + + + Catches any Throwable that occurs in its body and optionally + exposes it. + + catch + org.apache.taglibs.standard.tag.common.core.CatchTag + JSP + + + 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. + + var + false + false + + + + + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + + + + 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 + + if + org.apache.taglibs.standard.tag.rt.core.IfTag + JSP + + + The test condition that determines whether or + not the body content should be processed. + + test + true + true + boolean + + + + Name of the exported scoped variable for the + resulting value of the test condition. The type + of the scoped variable is Boolean. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + + + Retrieves an absolute or relative URL and exposes its contents + to either the page, a String in 'var', or a Reader in 'varReader'. + + import + org.apache.taglibs.standard.tag.rt.core.ImportTag + org.apache.taglibs.standard.tei.ImportTEI + JSP + + + The URL of the resource to import. + + url + true + true + + + + Name of the exported scoped variable for the + resource's content. The type of the scoped + variable is String. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + Name of the exported scoped variable for the + resource's content. The type of the scoped + variable is Reader. + + varReader + false + false + + + + Name of the context when accessing a relative + URL resource that belongs to a foreign + context. + + context + false + true + + + + Character encoding of the content at the input + resource. + + charEncoding + false + true + + + + + + The basic iteration tag, accepting many different + collection types and supporting subsetting and other + functionality + + forEach + org.apache.taglibs.standard.tag.rt.core.ForEachTag + org.apache.taglibs.standard.tei.ForEachTEI + JSP + + + Collection of items to iterate over. + + items + false + true + java.lang.Object + + java.lang.Object + + + + + 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. + + begin + false + true + int + + + + 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. + + end + false + true + int + + + + Iteration will only process every step items of + the collection, starting with the first one. + + step + false + true + int + + + + 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. + + var + false + false + + + + 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. + + varStatus + false + false + + + + + + Iterates over tokens, separated by the supplied delimeters + + forTokens + org.apache.taglibs.standard.tag.rt.core.ForTokensTag + JSP + + + String of tokens to iterate over. + + items + true + true + java.lang.String + + java.lang.String + + + + + The set of delimiters (the characters that + separate the tokens in the string). + + delims + true + true + java.lang.String + + + + Iteration begins at the token located at the + specified index. First token has index 0. + + begin + false + true + int + + + + Iteration ends at the token located at the + specified index (inclusive). + + end + false + true + int + + + + Iteration will only process every step tokens + of the string, starting with the first one. + + step + false + true + int + + + + Name of the exported scoped variable for the + current item of the iteration. This scoped + variable has nested visibility. + + var + false + false + + + + 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. + + varStatus + false + false + + + + + + Like <%= ... >, but for expressions. + + out + org.apache.taglibs.standard.tag.rt.core.OutTag + JSP + + + Expression to be evaluated. + + value + true + true + + + + Default value if the resulting value is null. + + default + false + true + + + + Determines whether characters <,>,&,'," in the + resulting string should be converted to their + corresponding character entity codes. Default value is + true. + + escapeXml + false + true + + + + + + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + + + + Adds a parameter to a containing 'import' tag's URL. + + param + org.apache.taglibs.standard.tag.rt.core.ParamTag + JSP + + + Name of the query string parameter. + + name + true + true + + + + Value of the parameter. + + value + false + true + + + + + + Redirects to a new URL. + + redirect + org.apache.taglibs.standard.tag.rt.core.RedirectTag + JSP + + + The URL of the resource to redirect to. + + url + false + true + + + + Name of the context when redirecting to a relative URL + resource that belongs to a foreign context. + + context + false + true + + + + + + Removes a scoped variable (from a particular scope, if specified). + + remove + org.apache.taglibs.standard.tag.common.core.RemoveTag + empty + + + Name of the scoped variable to be removed. + + var + true + false + + + + Scope for var. + + scope + false + false + + + + + + Sets the result of an expression evaluation in a 'scope' + + set + org.apache.taglibs.standard.tag.rt.core.SetTag + JSP + + + 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. + + var + false + false + + + + Expression to be evaluated. + + value + false + true + + java.lang.Object + + + + + Target object whose property will be set. Must evaluate to + a JavaBeans object with setter property property, or to a + java.util.Map object. + + target + false + true + + + + Name of the property to be set in the target object. + + property + false + true + + + + Scope for var. + + scope + false + false + + + + + + Creates a URL with optional query parameters. + + url + org.apache.taglibs.standard.tag.rt.core.UrlTag + JSP + + + Name of the exported scoped variable for the + processed url. The type of the scoped variable is + String. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + URL to be processed. + + value + false + true + + + + Name of the context when specifying a relative URL + resource that belongs to a foreign context. + + context + false + true + + + + + + Subtag of <choose> that includes its body if its + condition evalutes to 'true' + + when + org.apache.taglibs.standard.tag.rt.core.WhenTag + JSP + + + The test condition that determines whether or not the + body content should be processed. + + test + true + true + boolean + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt-1_0-rt.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt-1_0-rt.tld new file mode 100644 index 000000000..8bd72b518 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt-1_0-rt.tld @@ -0,0 +1,419 @@ + + + + + 1.0 + 1.2 + fmt_rt + http://java.sun.com/jstl/fmt_rt + JSTL fmt RT + JSTL 1.0 i18n-capable formatting library + + + + org.apache.taglibs.standard.tlv.JstlFmtTLV + + + Provides core validation features for JSTL tags. + + + + + requestEncoding + org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag + empty + + Sets the request character encoding + + + value + false + true + + + + + setLocale + org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag + empty + + Stores the given locale in the locale configuration variable + + + value + true + true + + + variant + false + true + + + scope + false + false + + + + + timeZone + org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag + JSP + + Specifies the time zone for any time formatting or parsing actions + nested in its body + + + value + true + true + + + + + setTimeZone + org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag + empty + + Stores the given time zone in the time zone configuration variable + + + value + true + true + + + var + false + false + + + scope + false + false + + + + + bundle + org.apache.taglibs.standard.tag.rt.fmt.BundleTag + JSP + + Loads a resource bundle to be used by its tag body + + + basename + true + true + + + prefix + false + true + + + + + setBundle + org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag + empty + + Loads a resource bundle and stores it in the named scoped variable or + the bundle configuration variable + + + basename + true + true + + + var + false + false + + + scope + false + false + + + + + message + org.apache.taglibs.standard.tag.rt.fmt.MessageTag + JSP + + Maps key to localized message and performs parametric replacement + + + key + false + true + + + bundle + false + true + + + var + false + false + + + scope + false + false + + + + + param + org.apache.taglibs.standard.tag.rt.fmt.ParamTag + JSP + + Supplies an argument for parametric replacement to a containing + <message> tag + + + value + false + true + + + + + formatNumber + org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag + JSP + + Formats a numeric value as a number, currency, or percentage + + + value + false + true + + + type + false + true + + + pattern + false + true + + + currencyCode + false + true + + + currencySymbol + false + true + + + groupingUsed + false + true + + + maxIntegerDigits + false + true + + + minIntegerDigits + false + true + + + maxFractionDigits + false + true + + + minFractionDigits + false + true + + + var + false + false + + + scope + false + false + + + + + parseNumber + org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag + JSP + + Parses the string representation of a number, currency, or percentage + + + value + false + true + + + type + false + true + + + pattern + false + true + + + parseLocale + false + true + + + integerOnly + false + true + + + var + false + false + + + scope + false + false + + + + + formatDate + org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag + empty + + Formats a date and/or time using the supplied styles and pattern + + + value + true + true + + + type + false + true + + + dateStyle + false + true + + + timeStyle + false + true + + + pattern + false + true + + + timeZone + false + true + + + var + false + false + + + scope + false + false + + + + + parseDate + org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag + JSP + + Parses the string representation of a date and/or time + + + value + false + true + + + type + false + true + + + dateStyle + false + true + + + timeStyle + false + true + + + pattern + false + true + + + timeZone + false + true + + + parseLocale + false + true + + + var + false + false + + + scope + false + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt.tld new file mode 100644 index 000000000..ed4de8411 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fmt.tld @@ -0,0 +1,686 @@ + + + + + JSTL 1.1 i18n-capable formatting library + JSTL fmt + 1.1 + fmt + http://java.sun.com/jsp/jstl/fmt + + + + Provides core validation features for JSTL tags. + + + org.apache.taglibs.standard.tlv.JstlFmtTLV + + + + + + Sets the request character encoding + + requestEncoding + org.apache.taglibs.standard.tag.rt.fmt.RequestEncodingTag + empty + + + Name of character encoding to be applied when + decoding request parameters. + + value + false + true + + + + + + Stores the given locale in the locale configuration variable + + setLocale + org.apache.taglibs.standard.tag.rt.fmt.SetLocaleTag + empty + + + A String value is interpreted as the + printable representation of a locale, which + must contain a two-letter (lower-case) + language code (as defined by ISO-639), + and may contain a two-letter (upper-case) + country code (as defined by ISO-3166). + Language and country codes must be + separated by hyphen (-) or underscore + (_). + + value + true + true + + + + Vendor- or browser-specific variant. + See the java.util.Locale javadocs for + more information on variants. + + variant + false + true + + + + Scope of the locale configuration variable. + + scope + false + false + + + + + + Specifies the time zone for any time formatting or parsing actions + nested in its body + + timeZone + org.apache.taglibs.standard.tag.rt.fmt.TimeZoneTag + JSP + + + The time zone. A String value is interpreted as + a time zone ID. This may be one of the time zone + IDs supported by the Java platform (such as + "America/Los_Angeles") or a custom time zone + ID (such as "GMT-8"). See + java.util.TimeZone for more information on + supported time zone formats. + + value + true + true + + + + + + Stores the given time zone in the time zone configuration variable + + setTimeZone + org.apache.taglibs.standard.tag.rt.fmt.SetTimeZoneTag + empty + + + The time zone. A String value is interpreted as + a time zone ID. This may be one of the time zone + IDs supported by the Java platform (such as + "America/Los_Angeles") or a custom time zone + ID (such as "GMT-8"). See java.util.TimeZone for + more information on supported time zone + formats. + + value + true + true + + + + Name of the exported scoped variable which + stores the time zone of type + java.util.TimeZone. + + var + false + false + + + + Scope of var or the time zone configuration + variable. + + scope + false + false + + + + + + Loads a resource bundle to be used by its tag body + + bundle + org.apache.taglibs.standard.tag.rt.fmt.BundleTag + JSP + + + Resource bundle base name. This is the bundle's + fully-qualified resource name, which has the same + form as a fully-qualified class name, that is, it uses + "." as the package component separator and does not + have any file type (such as ".class" or ".properties") + suffix. + + basename + true + true + + + + Prefix to be prepended to the value of the message + key of any nested <fmt:message> action. + + prefix + false + true + + + + + + Loads a resource bundle and stores it in the named scoped variable or + the bundle configuration variable + + setBundle + org.apache.taglibs.standard.tag.rt.fmt.SetBundleTag + empty + + + Resource bundle base name. This is the bundle's + fully-qualified resource name, which has the same + form as a fully-qualified class name, that is, it uses + "." as the package component separator and does not + have any file type (such as ".class" or ".properties") + suffix. + + basename + true + true + + + + Name of the exported scoped variable which stores + the i18n localization context of type + javax.servlet.jsp.jstl.fmt.LocalizationC + ontext. + + var + false + false + + + + Scope of var or the localization context + configuration variable. + + scope + false + false + + + + + + Maps key to localized message and performs parametric replacement + + message + org.apache.taglibs.standard.tag.rt.fmt.MessageTag + JSP + + + Message key to be looked up. + + key + false + true + + + + Localization context in whose resource + bundle the message key is looked up. + + bundle + false + true + + + + Name of the exported scoped variable + which stores the localized message. + + var + false + false + + + + Scope of var. + + scope + false + false + + + + + + Supplies an argument for parametric replacement to a containing + <message> tag + + param + org.apache.taglibs.standard.tag.rt.fmt.ParamTag + JSP + + + Argument used for parametric replacement. + + value + false + true + + + + + + Formats a numeric value as a number, currency, or percentage + + formatNumber + org.apache.taglibs.standard.tag.rt.fmt.FormatNumberTag + JSP + + + Numeric value to be formatted. + + value + false + true + + + + Specifies whether the value is to be + formatted as number, currency, or + percentage. + + type + false + true + + + + Custom formatting pattern. + + pattern + false + true + + + + ISO 4217 currency code. Applied only + when formatting currencies (i.e. if type is + equal to "currency"); ignored otherwise. + + currencyCode + false + true + + + + Currency symbol. Applied only when + formatting currencies (i.e. if type is equal + to "currency"); ignored otherwise. + + currencySymbol + false + true + + + + Specifies whether the formatted output + will contain any grouping separators. + + groupingUsed + false + true + + + + Maximum number of digits in the integer + portion of the formatted output. + + maxIntegerDigits + false + true + + + + Minimum number of digits in the integer + portion of the formatted output. + + minIntegerDigits + false + true + + + + Maximum number of digits in the + fractional portion of the formatted output. + + maxFractionDigits + false + true + + + + Minimum number of digits in the + fractional portion of the formatted output. + + minFractionDigits + false + true + + + + Name of the exported scoped variable + which stores the formatted result as a + String. + + var + false + false + + + + Scope of var. + + scope + false + false + + + + + + Parses the string representation of a number, currency, or percentage + + parseNumber + org.apache.taglibs.standard.tag.rt.fmt.ParseNumberTag + JSP + + + String to be parsed. + + value + false + true + + + + Specifies whether the string in the value + attribute should be parsed as a number, + currency, or percentage. + + type + false + true + + + + Custom formatting pattern that determines + how the string in the value attribute is to be + parsed. + + pattern + false + true + + + + Locale whose default formatting pattern (for + numbers, currencies, or percentages, + respectively) is to be used during the parse + operation, or to which the pattern specified + via the pattern attribute (if present) is + applied. + + parseLocale + false + true + + + + Specifies whether just the integer portion of + the given value should be parsed. + + integerOnly + false + true + + + + Name of the exported scoped variable which + stores the parsed result (of type + java.lang.Number). + + var + false + false + + + + Scope of var. + + scope + false + false + + + + + + Formats a date and/or time using the supplied styles and pattern + + formatDate + org.apache.taglibs.standard.tag.rt.fmt.FormatDateTag + empty + + + Date and/or time to be formatted. + + value + true + true + + + + Specifies whether the time, the date, or both + the time and date components of the given + date are to be formatted. + + type + false + true + + + + Predefined formatting style for dates. Follows + the semantics defined in class + java.text.DateFormat. Applied only + when formatting a date or both a date and + time (i.e. if type is missing or is equal to + "date" or "both"); ignored otherwise. + + dateStyle + false + true + + + + Predefined formatting style for times. Follows + the semantics defined in class + java.text.DateFormat. Applied only + when formatting a time or both a date and + time (i.e. if type is equal to "time" or "both"); + ignored otherwise. + + timeStyle + false + true + + + + Custom formatting style for dates and times. + + pattern + false + true + + + + Time zone in which to represent the formatted + time. + + timeZone + false + true + + + + Name of the exported scoped variable which + stores the formatted result as a String. + + var + false + false + + + + Scope of var. + + scope + false + false + + + + + + Parses the string representation of a date and/or time + + parseDate + org.apache.taglibs.standard.tag.rt.fmt.ParseDateTag + JSP + + + Date string to be parsed. + + value + false + true + + + + Specifies whether the date string in the + value attribute is supposed to contain a + time, a date, or both. + + type + false + true + + + + Predefined formatting style for days + which determines how the date + component of the date string is to be + parsed. Applied only when formatting a + date or both a date and time (i.e. if type + is missing or is equal to "date" or "both"); + ignored otherwise. + + dateStyle + false + true + + + + Predefined formatting styles for times + which determines how the time + component in the date string is to be + parsed. Applied only when formatting a + time or both a date and time (i.e. if type + is equal to "time" or "both"); ignored + otherwise. + + timeStyle + false + true + + + + Custom formatting pattern which + determines how the date string is to be + parsed. + + pattern + false + true + + + + Time zone in which to interpret any time + information in the date string. + + timeZone + false + true + + + + Locale whose predefined formatting styles + for dates and times are to be used during + the parse operation, or to which the + pattern specified via the pattern + attribute (if present) is applied. + + parseLocale + false + true + + + + Name of the exported scoped variable in + which the parsing result (of type + java.util.Date) is stored. + + var + false + false + + + + Scope of var. + + scope + false + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fn.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fn.tld new file mode 100644 index 000000000..0076116d6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/fn.tld @@ -0,0 +1,222 @@ + + + + + JSTL 1.1 functions library + JSTL functions + 1.1 + fn + http://java.sun.com/jsp/jstl/functions + + + + Tests if an input string contains the specified substring. + + contains + org.apache.taglibs.standard.functions.Functions + boolean contains(java.lang.String, java.lang.String) + + <c:if test="${fn:contains(name, searchString)}"> + + + + + + Tests if an input string contains the specified substring in a case insensitive way. + + containsIgnoreCase + org.apache.taglibs.standard.functions.Functions + boolean containsIgnoreCase(java.lang.String, java.lang.String) + + <c:if test="${fn:containsIgnoreCase(name, searchString)}"> + + + + + + Tests if an input string ends with the specified suffix. + + endsWith + org.apache.taglibs.standard.functions.Functions + boolean endsWith(java.lang.String, java.lang.String) + + <c:if test="${fn:endsWith(filename, ".txt")}"> + + + + + + Escapes characters that could be interpreted as XML markup. + + escapeXml + org.apache.taglibs.standard.functions.Functions + java.lang.String escapeXml(java.lang.String) + + ${fn:escapeXml(param:info)} + + + + + + Returns the index withing a string of the first occurrence of a specified substring. + + indexOf + org.apache.taglibs.standard.functions.Functions + int indexOf(java.lang.String, java.lang.String) + + ${fn:indexOf(name, "-")} + + + + + + Joins all elements of an array into a string. + + join + org.apache.taglibs.standard.functions.Functions + java.lang.String join(java.lang.String[], java.lang.String) + + ${fn:join(array, ";")} + + + + + + Returns the number of items in a collection, or the number of characters in a string. + + length + org.apache.taglibs.standard.functions.Functions + int length(java.lang.Object) + + You have ${fn:length(shoppingCart.products)} in your shopping cart. + + + + + + Returns a string resulting from replacing in an input string all occurrences + of a "before" string into an "after" substring. + + replace + org.apache.taglibs.standard.functions.Functions + java.lang.String replace(java.lang.String, java.lang.String, java.lang.String) + + ${fn:replace(text, "-", "•")} + + + + + + Splits a string into an array of substrings. + + split + org.apache.taglibs.standard.functions.Functions + java.lang.String[] split(java.lang.String, java.lang.String) + + ${fn:split(customerNames, ";")} + + + + + + Tests if an input string starts with the specified prefix. + + startsWith + org.apache.taglibs.standard.functions.Functions + boolean startsWith(java.lang.String, java.lang.String) + + <c:if test="${fn:startsWith(product.id, "100-")}"> + + + + + + Returns a subset of a string. + + substring + org.apache.taglibs.standard.functions.Functions + java.lang.String substring(java.lang.String, int, int) + + P.O. Box: ${fn:substring(zip, 6, -1)} + + + + + + Returns a subset of a string following a specific substring. + + substringAfter + org.apache.taglibs.standard.functions.Functions + java.lang.String substringAfter(java.lang.String, java.lang.String) + + P.O. Box: ${fn:substringAfter(zip, "-")} + + + + + + Returns a subset of a string before a specific substring. + + substringBefore + org.apache.taglibs.standard.functions.Functions + java.lang.String substringBefore(java.lang.String, java.lang.String) + + Zip (without P.O. Box): ${fn:substringBefore(zip, "-")} + + + + + + Converts all of the characters of a string to lower case. + + toLowerCase + org.apache.taglibs.standard.functions.Functions + java.lang.String toLowerCase(java.lang.String) + + Product name: ${fn.toLowerCase(product.name)} + + + + + + Converts all of the characters of a string to upper case. + + toUpperCase + org.apache.taglibs.standard.functions.Functions + java.lang.String toUpperCase(java.lang.String) + + Product name: ${fn.UpperCase(product.name)} + + + + + + Removes white spaces from both ends of a string. + + trim + org.apache.taglibs.standard.functions.Functions + java.lang.String trim(java.lang.String) + + Name: ${fn.trim(name)} + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/permittedTaglibs.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/permittedTaglibs.tld new file mode 100644 index 000000000..42a514528 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/permittedTaglibs.tld @@ -0,0 +1,49 @@ + + + + + Restricts JSP pages to the JSTL tag libraries + + permittedTaglibs + 1.1 + permittedTaglibs + http://jakarta.apache.org/taglibs/standard/permittedTaglibs + + + + javax.servlet.jsp.jstl.tlv.PermittedTaglibsTLV + + + + Whitespace-separated list of taglib URIs to permit. This example + TLD for the Standard Taglib allows only JSTL 'el' taglibs to be + imported. + + permittedTaglibs + + http://java.sun.com/jsp/jstl/core + http://java.sun.com/jsp/jstl/fmt + http://java.sun.com/jsp/jstl/sql + http://java.sun.com/jsp/jstl/xml + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/scriptfree.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/scriptfree.tld new file mode 100644 index 000000000..b7e4a4b60 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/scriptfree.tld @@ -0,0 +1,66 @@ + + + + + Validates JSP pages to prohibit use of scripting elements. + + 1.1 + scriptfree + http://jakarta.apache.org/taglibs/standard/scriptfree + + + + Validates prohibitions against scripting elements. + + + javax.servlet.jsp.jstl.tlv.ScriptFreeTLV + + + + Controls whether or not declarations are considered valid. + + allowDeclarations + false + + + + Controls whether or not scriptlets are considered valid. + + allowScriptlets + false + + + + Controls whether or not top-level expressions are considered valid. + + allowExpressions + false + + + + Controls whether or not expressions used to supply request-time + attribute values are considered valid. + + allowRTExpressions + false + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql-1_0-rt.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql-1_0-rt.tld new file mode 100644 index 000000000..00d7ba529 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql-1_0-rt.tld @@ -0,0 +1,204 @@ + + + + + 1.0 + 1.2 + sql_rt + http://java.sun.com/jstl/sql_rt + JSTL sql RT + JSTL 1.0 sql library + + + + org.apache.taglibs.standard.tlv.JstlSqlTLV + + + Provides core validation features for JSTL tags. + + + + + transaction + org.apache.taglibs.standard.tag.rt.sql.TransactionTag + JSP + + Provides nested database action elements with a shared Connection, + set up to execute all statements as one transaction. + + + dataSource + false + true + + + isolation + false + true + + + + + query + org.apache.taglibs.standard.tag.rt.sql.QueryTag + JSP + + Executes the SQL query defined in its body or through the + sql attribute. + + + var + true + false + + + scope + false + false + + + sql + false + true + + + dataSource + false + true + + + startRow + false + true + + + maxRows + false + true + + + + + update + org.apache.taglibs.standard.tag.rt.sql.UpdateTag + JSP + + Executes the SQL update defined in its body or through the + sql attribute. + + + var + false + false + + + scope + false + false + + + sql + false + true + + + dataSource + false + true + + + + + param + org.apache.taglibs.standard.tag.rt.sql.ParamTag + JSP + + Sets a parameter in an SQL statement to the specified value. + + + value + false + true + + + + + dateParam + org.apache.taglibs.standard.tag.rt.sql.DateParamTag + empty + + Sets a parameter in an SQL statement to the specified java.util.Date value. + + + value + true + true + + + type + false + true + + + + + setDataSource + org.apache.taglibs.standard.tag.rt.sql.SetDataSourceTag + empty + + Creates a simple DataSource suitable only for prototyping. + + + var + false + false + + + scope + false + false + + + dataSource + false + true + + + driver + false + true + + + url + false + true + + + user + false + true + + + password + false + true + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql.tld new file mode 100644 index 000000000..b46a57161 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/sql.tld @@ -0,0 +1,304 @@ + + + + + JSTL 1.1 sql library + JSTL sql + 1.1 + sql + http://java.sun.com/jsp/jstl/sql + + + + Provides core validation features for JSTL tags. + + + org.apache.taglibs.standard.tlv.JstlSqlTLV + + + + + + Provides nested database action elements with a shared Connection, + set up to execute all statements as one transaction. + + transaction + org.apache.taglibs.standard.tag.rt.sql.TransactionTag + JSP + + + DataSource associated with the database to access. A + String value represents a relative path to a JNDI + resource or the parameters for the JDBC + DriverManager facility. + + dataSource + false + true + + + + Transaction isolation level. If not specified, it is the + isolation level the DataSource has been configured + with. + + isolation + false + true + + + + + + Executes the SQL query defined in its body or through the + sql attribute. + + query + org.apache.taglibs.standard.tag.rt.sql.QueryTag + JSP + + + Name of the exported scoped variable for the + query result. The type of the scoped variable is + javax.servlet.jsp.jstl.sql. + Result (see Chapter 16 "Java APIs"). + + var + true + false + + + + Scope of var. + + scope + false + false + + + + SQL query statement. + + sql + false + true + + + + Data source associated with the database to + query. A String value represents a relative path + to a JNDI resource or the parameters for the + DriverManager class. + + dataSource + false + true + + + + The returned Result object includes the rows + starting at the specified index. The first row of + the original query result set is at index 0. If not + specified, rows are included starting from the + first row at index 0. + + startRow + false + true + + + + The maximum number of rows to be included in + the query result. If not specified, or set to -1, no + limit on the maximum number of rows is + enforced. + + maxRows + false + true + + + + + + Executes the SQL update defined in its body or through the + sql attribute. + + update + org.apache.taglibs.standard.tag.rt.sql.UpdateTag + JSP + + + Name of the exported scoped variable for the result + of the database update. The type of the scoped + variable is java.lang.Integer. + + var + false + false + + + + Scope of var. + + scope + false + false + + + + SQL update statement. + + sql + false + true + + + + Data source associated with the database to update. + A String value represents a relative path to a JNDI + resource or the parameters for the JDBC + DriverManager class. + + dataSource + false + true + + + + + + Sets a parameter in an SQL statement to the specified value. + + param + org.apache.taglibs.standard.tag.rt.sql.ParamTag + JSP + + + Parameter value. + + value + false + true + + + + + + Sets a parameter in an SQL statement to the specified java.util.Date value. + + dateParam + org.apache.taglibs.standard.tag.rt.sql.DateParamTag + empty + + + Parameter value for DATE, TIME, or + TIMESTAMP column in a database table. + + value + true + true + + + + One of "date", "time" or "timestamp". + + type + false + true + + + + + + Creates a simple DataSource suitable only for prototyping. + + setDataSource + org.apache.taglibs.standard.tag.rt.sql.SetDataSourceTag + empty + + + Name of the exported scoped variable + for the data source specified. Type can + be String or DataSource. + + var + false + false + + + + If var is specified, scope of the + exported variable. Otherwise, scope of + the data source configuration variable. + + scope + false + false + + + + Data source. If specified as a string, it + can either be a relative path to a JNDI + resource, or a JDBC parameters string + as defined in Section 10.1.1. + + dataSource + false + true + + + + JDBC parameter: driver class name. + + driver + false + true + + + + JDBC parameter: URL associated with + the database. + + url + false + true + + + + JDBC parameter: database user on + whose behalf the connection to the + database is being made. + + user + false + true + + + + JDBC parameter: user password + + password + false + true + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x-1_0-rt.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x-1_0-rt.tld new file mode 100644 index 000000000..dd5b07f9a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x-1_0-rt.tld @@ -0,0 +1,272 @@ + + + + + 1.0 + 1.2 + x_rt + http://java.sun.com/jstl/xml_rt + JSTL XML RT + JSTL 1.0 XML library + + + + org.apache.taglibs.standard.tlv.JstlXmlTLV + + + Provides validation features for JSTL XML tags. + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + out + org.apache.taglibs.standard.tag.rt.xml.ExprTag + empty + + Like <%= ... >, but for XPath expressions. + + + select + true + false + + + escapeXml + false + true + + + + + if + org.apache.taglibs.standard.tag.common.xml.IfTag + JSP + + XML conditional tag, which evalutes its body if the + supplied XPath expression evalutes to 'true' as a boolean + + + select + true + false + + + var + false + false + + + scope + false + false + + + + + forEach + org.apache.taglibs.standard.tag.common.xml.ForEachTag + JSP + + XML iteration tag. + + + var + false + false + + + select + true + false + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.rt.xml.ParamTag + JSP + + Adds a parameter to a containing 'transform' tag's Transformer + + + name + true + true + + + value + false + true + + + + + parse + org.apache.taglibs.standard.tag.rt.xml.ParseTag + org.apache.taglibs.standard.tei.XmlParseTEI + JSP + + Parses XML content from 'source' attribute or 'body' + + + var + false + false + + + varDom + false + false + + + scope + false + false + + + scopeDom + false + false + + + xml + false + true + + + systemId + false + true + + + filter + false + true + + + + + set + org.apache.taglibs.standard.tag.common.xml.SetTag + empty + + Saves the result of an XPath expression evaluation in a 'scope' + + + var + true + false + + + select + false + false + + + scope + false + false + + + + + transform + org.apache.taglibs.standard.tag.rt.xml.TransformTag + org.apache.taglibs.standard.tei.XmlTransformTEI + JSP + + Conducts a transformation given a source XML document + and an XSLT stylesheet + + + var + false + false + + + scope + false + false + + + result + false + true + + + xml + false + true + + + xmlSystemId + false + true + + + xslt + false + true + + + xsltSystemId + false + true + + + + + when + org.apache.taglibs.standard.tag.common.xml.WhenTag + JSP + + Subtag of <choose> that includes its body if its + expression evalutes to 'true' + + + select + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x.tld b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x.tld new file mode 100644 index 000000000..f4fd70fbd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/META-INF/x.tld @@ -0,0 +1,463 @@ + + + + + JSTL 1.1 XML library + JSTL XML + 1.1 + x + http://java.sun.com/jsp/jstl/xml + + + + Provides validation features for JSTL XML tags. + + + org.apache.taglibs.standard.tlv.JstlXmlTLV + + + + + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + + + + Like <%= ... >, but for XPath expressions. + + out + org.apache.taglibs.standard.tag.rt.xml.ExprTag + empty + + + XPath expression to be evaluated. + + select + true + false + + + + Determines whether characters <,>,&,'," in the + resulting string should be converted to their + corresponding character entity codes. Default + value is true. + + escapeXml + false + true + + + + + + XML conditional tag, which evalutes its body if the + supplied XPath expression evalutes to 'true' as a boolean + + if + org.apache.taglibs.standard.tag.common.xml.IfTag + JSP + + + The test condition that tells whether or not the + body content should be processed. + + select + true + false + + + + Name of the exported scoped variable for the + resulting value of the test condition. The type + of the scoped variable is Boolean. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + + + XML iteration tag. + + forEach + org.apache.taglibs.standard.tag.common.xml.ForEachTag + JSP + + + Name of the exported scoped variable for the + current item of the iteration. This scoped variable + has nested visibility. Its type depends on the + result of the XPath expression in the select + attribute. + + var + false + false + + + + XPath expression to be evaluated. + + select + true + false + + + + Iteration begins at the item located at the + specified index. First item of the collection has + index 0. + + begin + false + true + int + + + + Iteration ends at the item located at the specified + index (inclusive). + + end + false + true + int + + + + Iteration will only process every step items of + the collection, starting with the first one. + + step + false + true + int + + + + 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. + + varStatus + false + false + + + + + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + + + + Adds a parameter to a containing 'transform' tag's Transformer + + param + org.apache.taglibs.standard.tag.rt.xml.ParamTag + JSP + + + Name of the transformation parameter. + + name + true + true + + + + Value of the parameter. + + value + false + true + + + + + + Parses XML content from 'source' attribute or 'body' + + parse + org.apache.taglibs.standard.tag.rt.xml.ParseTag + org.apache.taglibs.standard.tei.XmlParseTEI + JSP + + + Name of the exported scoped variable for + the parsed XML document. The type of the + scoped variable is implementation + dependent. + + var + false + false + + + + Name of the exported scoped variable for + the parsed XML document. The type of the + scoped variable is + org.w3c.dom.Document. + + varDom + false + false + + + + Scope for var. + + scope + false + false + + + + Scope for varDom. + + scopeDom + false + false + + + + Deprecated. Use attribute 'doc' instead. + + xml + false + true + + + + Source XML document to be parsed. + + doc + false + true + + + + The system identifier (URI) for parsing the + XML document. + + systemId + false + true + + + + Filter to be applied to the source + document. + + filter + false + true + + + + + + Saves the result of an XPath expression evaluation in a 'scope' + + set + org.apache.taglibs.standard.tag.common.xml.SetTag + empty + + + Name of the exported scoped variable to hold + the value specified in the action. The type of the + scoped variable is whatever type the select + expression evaluates to. + + var + true + false + + + + XPath expression to be evaluated. + + select + false + false + + + + Scope for var. + + scope + false + false + + + + + + Conducts a transformation given a source XML document + and an XSLT stylesheet + + transform + org.apache.taglibs.standard.tag.rt.xml.TransformTag + org.apache.taglibs.standard.tei.XmlTransformTEI + JSP + + + Name of the exported + scoped variable for the + transformed XML + document. The type of the + scoped variable is + org.w3c.dom.Document. + + var + false + false + + + + Scope for var. + + scope + false + false + + + + Result + Object that captures or + processes the transformation + result. + + result + false + true + + + + Deprecated. Use attribute + 'doc' instead. + + xml + false + true + + + + Source XML document to be + transformed. (If exported by + <x:set>, it must correspond + to a well-formed XML + document, not a partial + document.) + + doc + false + true + + + + Deprecated. Use attribute + 'docSystemId' instead. + + xmlSystemId + false + true + + + + The system identifier (URI) + for parsing the XML + document. + + docSystemId + false + true + + + + javax.xml.transform.Source + Transformation stylesheet as + a String, Reader, or + Source object. + + xslt + false + true + + + + The system identifier (URI) + for parsing the XSLT + stylesheet. + + xsltSystemId + false + true + + + + + + Subtag of <choose> that includes its body if its + expression evalutes to 'true' + + when + org.apache.taglibs.standard.tag.common.xml.WhenTag + JSP + + + The test condition that tells whether or + not the body content should be + processed + + select + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties new file mode 100644 index 000000000..701ef03ed --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources.properties @@ -0,0 +1,344 @@ +# 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. + +######################################################################### +# Conventions: +# - For error messages from particular tags, the resource should +# - (a) have a name beginning with TAGNAME_ +# - (b) contain the name of the tag within the message +# - Generic tag messages -- i.e., those used in more than one tag -- +# should begin with TAG_ +# - Errors for TagLibraryValidators should begin with TLV_ +######################################################################### + + +######################################################################### +# Test messages - do not localize +######################################################################### +TEST_NO_ARGUMENTS=test no arguments +TEST_ONE_ARGUMENT=test argument {0} +TEST_MULTIPLE_ARGUMENT=test argument {0} {1} + +######################################################################### +# Generic tag error messages +######################################################################### + +TAG_NULL_ATTRIBUTE=\ + The "{0}" attribute illegally evaluated to "null" or "" in <{1}> + +######################################################################### +# Specific tag error messages +######################################################################### + +# CORE + +CHOOSE_EXCLUSIVITY=\ + Only one (or is it two?) <choose> subtag may evaluate its body + +EXPR_BAD_VALUE=\ + In <expr>, attribute value="{0}" didn't evaluate successfully, \ + but there was no "default" attribute and no non-whitespace content \ + for the tag. + +FOREACH_STEP_NO_RESULTSET=\ + Step cannot be > 1 when iterating over a ResultSet with <forEach> + +FOREACH_BAD_ITEMS=\ + Don't know how to iterate over supplied "items" in <forEach> + +IMPORT_BAD_RELATIVE=\ + In URL tags, when the "context" attribute is specified, \ + values of both "context" and "url" must start with "/". + +IMPORT_REL_WITHOUT_HTTP=\ + Relative <import> from non-HTTP request not allowed + +IMPORT_REL_WITHOUT_DISPATCHER=\ + Unable to get RequestDispatcher for Context: "{0}" and URL: "{1}". \ + Verify values and/or enable cross context access. + +IMPORT_IO=\ + I/O error in <import> occurred reading "{0}" + +IMPORT_ILLEGAL_STREAM=\ + Unexpected internal error during <import>: \ + Target servlet called getWriter(), then getOutputStream() + +IMPORT_ILLEGAL_WRITER=\ + Unexpected internal error during <import>: \ + Target servlet called getOutputStream(), then getWriter() + +#IMPORT_ILLEGAL_GETSTRING=\ +# Unexpected internal error during <import>: \ +# Target servlet called neither getOutputStream() nor getWriter() + +PARAM_OUTSIDE_PARENT=\ + <param> outside <import> or <urlEncode> + +PARAM_ENCODE_BOOLEAN=\ + In <param>, "encode" must be "true" or "false". Got "{0}" instead. + +SET_BAD_SCOPE=\ + Invalid "scope" attribute for <set>: "{0}" + +SET_INVALID_PROPERTY=\ + Invalid property in <set>: "{0}" + +SET_INVALID_TARGET=\ + Attempt to set the property of an invalid object in <set>. + +SET_BAD_DEFERRED_SCOPE=\ + Invalid scope for ValueExpression in <set>. "page" scope is required but was "{0}" + +SET_NO_VALUE=\ + Need either non-whitespace body or "value" attribute in <set> + +URLENCODE_NO_VALUE=\ + Need either non-whitespace body or "value" attribute in <urlEncode> + +WHEN_OUTSIDE_CHOOSE=\ + Illegal use of <when>-style tag without <choose> as its \ + direct parent + +# I18N + +LOCALE_NO_LANGUAGE=\ + Missing language component in 'value' attribute in <setLocale> + +LOCALE_EMPTY_COUNTRY=\ + Empty country component in 'value' attribute in <setLocale> + +PARAM_OUTSIDE_MESSAGE=\ + <param> outside <message> + +MESSAGE_NO_KEY=\ + <message> needs 'key' attribute or non-whitespace body + +FORMAT_NUMBER_INVALID_TYPE=\ + In <formatNumber>, invalid 'type' attribute: "{0}" + +FORMAT_NUMBER_NO_VALUE=\ + <formatNumber> needs 'value' attribute or non-whitespace body + +FORMAT_NUMBER_PARSE_ERROR=\ + In <formatNumber>, 'value' attribute can not be parsed into java.lang.Number: "{0}" + +FORMAT_NUMBER_CURRENCY_ERROR=\ + In <formatNumber>, unable to set currency + +PARSE_NUMBER_INVALID_TYPE=\ + In <parseNumber>, invalid 'type' attribute: "{0}" + +PARSE_NUMBER_NO_VALUE=\ + <parseNumber> needs 'value' attribute or non-whitespace body + +PARSE_NUMBER_NO_PARSE_LOCALE=\ + In <parseNumber>, a parse locale can not be established + +PARSE_NUMBER_PARSE_ERROR=\ + In <parseNumber>, 'value' attribute can not be parsed: "{0}" + +FORMAT_DATE_INVALID_TYPE=\ + In <formatDate>, invalid 'type' attribute: "{0}" + +FORMAT_DATE_BAD_TIMEZONE=\ + In <formatDate>, 'timeZone' must be an instance of java.lang.String or java.util.TimeZone + +FORMAT_DATE_INVALID_DATE_STYLE=\ + In <formatDate>, invalid 'dateStyle' attribute: "{0}" + +FORMAT_DATE_INVALID_TIME_STYLE=\ + In <formatDate>, invalid 'timeStyle' attribute: "{0}" + +PARSE_DATE_INVALID_TYPE=\ + In <parseDate>, invalid 'type' attribute: "{0}" + +PARSE_DATE_BAD_TIMEZONE=\ + In <parseDate>, 'timeZone' must be an instance of java.lang.String or java.util.TimeZone + +PARSE_DATE_INVALID_DATE_STYLE=\ + In <parseDate>, invalid 'dateStyle' attribute: "{0}" + +PARSE_DATE_INVALID_TIME_STYLE=\ + In <parseDate>, invalid 'timeStyle' attribute: "{0}" + +PARSE_DATE_NO_VALUE=\ + <parseDate> needs 'value' attribute or non-whitespace body + +PARSE_DATE_PARSE_ERROR=\ + In <parseDate>, 'value' attribute can not be parsed: "{0}" + +PARSE_DATE_NO_PARSE_LOCALE=\ + In <parseDate>, a parse locale can not be established + +# SQL + +DRIVER_INVALID_CLASS=\ + In <driver>, invalid driver class name: "{0}" + +DATASOURCE_INVALID=\ + Unable to get connection, DataSource invalid: "{0}" + +JDBC_PARAM_COUNT=\ + Invalid number of JDBC parameters specified. + +PARAM_BAD_VALUE=\ + Invalid or out of bounds value specified in parameter. + +TRANSACTION_NO_SUPPORT=\ + In <transaction>, datasource does not support transactions + +TRANSACTION_COMMIT_ERROR=\ + In <transaction>, error committing transaction: "{0}" + +TRANSACTION_INVALID_ISOLATION=\ + In <transaction>, invalid transaction isolation + +NOT_SUPPORTED=\ + Not supported + +ERROR_GET_CONNECTION=\ + Error getting connection: "{0}" + +ERROR_NESTED_DATASOURCE=\ + It is illegal to specify a DataSource when nested within a <transaction> + +SQL_PARAM_OUTSIDE_PARENT=\ + <param> or <dateParam> must be subtag of SQLExecutionTag actions like <query> or <update> + +SQL_NO_STATEMENT=\ + No SQL statement specified + +SQL_PROCESS_ERROR=\ + Error processing SQL: "{0}" + +SQL_DATASOURCE_INVALID_TYPE=\ + 'dataSource' is neither a String nor a javax.sql.DataSource + +SQL_DATASOURCE_NULL=\ + 'dataSource' is null + +SQL_MAXROWS_PARSE_ERROR=\ + Error parsing 'javax.servlet.jsp.jstl.sql.maxRows' configuration setting: "{0}" + +SQL_MAXROWS_INVALID=\ + 'javax.servlet.jsp.jstl.sql.maxRows' configuration setting neither an Integer nor a String + +SQL_DATE_PARAM_INVALID_TYPE=\ + In <dateParam>, invalid 'type' attribute: "{0}" + +# XML + +FOREACH_NOT_NODESET=\ + <forEach> can't iterate over XPath expressions that don't return a node-set + +PARAM_NO_VALUE=\ + <param> needs 'value' attribute or non-whitespace body + +PARAM_OUTSIDE_TRANSFORM=\ + <param> outside <transform> + +PARSE_INVALID_SOURCE=\ + Unrecognized object supplied as 'xml' attribute to <parse> + +PARSE_NO_SAXTRANSFORMER=\ + Filter supplied to <parse>, but default TransformerFactory \ + does not support SAX. + +TRANSFORM_XSLT_IS_NULL=\ + <transform> 'xslt' attribute must not be null + +TRANSFORM_XSLT_IS_EMPTY=\ + <transform> 'xslt' attribute must not be an empty String + +TRANSFORM_XSLT_UNSUPPORTED_TYPE=\ + <transform> 'xslt' attribute was of an unsupported type: {0} + +TRANSFORM_XML_IS_NULL=\ + <transform> 'xml' or 'doc' attribute must not be null + +TRANSFORM_XML_IS_EMPTY=\ + <transform> 'xml' or 'doc' attribute must not be an empty String + +TRANSFORM_XML_LIST_SIZE=\ + <transform> 'xml' or 'doc' attribute of List type may only contain 1 element + +TRANSFORM_XML_UNSUPPORTED_TYPE=\ + <transform> 'xml' or 'doc' attribute was of an unsupported type: {0} + +TRANSFORM_BODY_IS_NULL=\ + <transform> body content was null + +TRANSFORM_BODY_CONTENT_IS_NULL=\ + <transform> body content value was null + +TRANSFORM_BODY_IS_EMPTY=\ + <transform> body content evaluated to an empty String + +UNABLE_TO_RESOLVE_ENTITY=\ + Could not resolve entity reference: "{0}" + +XPATH_UNABLE_TO_RESOLVE_VARIABLE=\ + Could not resolve XPath variable: {0} + +######################################################################### +# JSTL core TLV messages +######################################################################### + +# Parameters + +TLV_PARAMETER_ERROR=\ + Invalid value for "{0}" validator parameter in TLD + +# Generic errors + +TLV_ILLEGAL_BODY=\ + Encountered illegal body of tag "{0}" tag, given its attributes. + +TLV_MISSING_BODY=\ + A body is necessary inside the "{0}" tag, given its attributes. + +TLV_ILLEGAL_CHILD_TAG=\ + Illegal child tag in "{0}:{1}" tag: "{2}" tag + +TLV_ILLEGAL_TEXT_BODY=\ + Illegal text inside "{0}:{1}" tag: "{2}...". + +TLV_INVALID_ATTRIBUTE=\ + Invalid "{0}" attribute in "{1}" tag: "{2}" + +TLV_ILLEGAL_ORPHAN=\ + Invalid use of "{0}" tag outside legitimate parent tag + +TLV_PARENT_WITHOUT_SUBTAG=\ + Illegal "{0}" without child "{1}" tag + +# Errors customized to particular tags (sort of) :-) + +TLV_ILLEGAL_ORDER=\ + Illegal "{0}" after "{1}:{2}" tag in "{1}:{3}" tag. + +TLV_ILLEGAL_PARAM=\ + Illegal "{0}:{1}" tag within "{0}:{2} {3}='...'" tag + +TLV_DANGLING_SCOPE=\ + Illegal 'scope' attribute without 'var' in "{0}" tag. + +TLV_EMPTY_VAR=\ + Empty 'var' attribute in "{0}" tag. + +SET_NO_SETTER_METHOD=No setter method in <set> for property "{0}" + +IMPORT_ABS_ERROR=Problem accessing the absolute URL "{0}". {1} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources_ja.properties b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources_ja.properties new file mode 100644 index 000000000..019c35856 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/main/resources/org/apache/taglibs/standard/resources/Resources_ja.properties @@ -0,0 +1,312 @@ +# 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. + +######################################################################### +# Conventions: +# - For error messages from particular tags, the resource should +# - (a) have a name beginning with TAGNAME_ +# - (b) contain the name of the tag within the message +# - Generic tag messages -- i.e., those used in more than one tag -- +# should begin with TAG_ +# - Errors for TagLibraryValidators should begin with TLV_ +######################################################################### + + +######################################################################### +# Generic tag error messages +######################################################################### + +TAG_NULL_ATTRIBUTE=\ + <{1}> \u5185\u306b\u3042\u308b "{0}" \u5c5e\u6027\u304c "null" \u3082\u3057\u304f\u306f "" \u3067\u3042\u308b\u3068\u4e0d\u6b63\u306b\u8a55\u4fa1\u3057\u307e\u3057\u305f\u3002 + +######################################################################### +# Specific tag error messages +######################################################################### + +# CORE + +CHOOSE_EXCLUSIVITY=\ + \uff11\u3064\u3057\u304b\u5b58\u5728\u306a\u3044 <choose> \u306e\u4e0b\u4f4d\u30bf\u30b0\u306f\u30dc\u30c7\u30a3\u306e\u4e2d\u8eab\u3092\u305d\u306e\u307e\u307e\u8a55\u4fa1\u3057\u307e\u3059 + +EXPR_BAD_VALUE=\ + <expr> \u5185\u3067\u3001\u5c5e\u6027\u5024="{0}" \u304c\u6b63\u3057\u304f\u8a55\u4fa1\u3055\u308c\u305a\u3001"default" \u5c5e\u6027\u3084\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30b3\u30f3\u30c6\u30f3\u30c4\u304c\u30bf\u30b0\u306e\u4e2d\u306b\u5b58\u5728\u3057\u307e\u305b\u3093 + +FOREACH_STEP_NO_RESULTSET=\ + <forEach> \u3067 ResultSet \u3092\u53cd\u5fa9\u51e6\u7406\u3057\u3088\u3046\u3068\u3057\u305f\u3068\u3053\u308d\u3001step \u306e\u5024\u3092 1 \u3088\u308a\u5927\u304d\u304f\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093 + +FOREACH_BAD_ITEMS=\ + <forEach> \u5185\u3067\u4f9b\u7d66\u3055\u308c\u305f "items" \u3092\u53cd\u5fa9\u51e6\u7406\u3059\u308b\u65b9\u6cd5\u304c\u4e0d\u660e\u3067\u3059 + +IMPORT_BAD_RELATIVE=\ + URL \u30bf\u30b0\u3067 "context" \u5c5e\u6027\u3092\u6307\u5b9a\u3059\u308b\u969b\u3001"context" \u304a\u3088\u3073 "url" \u306e\u4e21\u65b9\u306e\u5024\u306f "/" \u3067\u59cb\u307e\u3063\u3066\u3044\u306a\u3044\u3068\u3044\u3051\u307e\u305b\u3093 + +IMPORT_REL_WITHOUT_HTTP=\ + \u975e HTTP \u8981\u6c42\u3067\u306f\u3001URL\u3092\u76f8\u5bfe\u6307\u5b9a\u3059\u308b <import> \u3092\u8a31\u53ef\u3057\u3066\u3044\u307e\u305b\u3093 + +IMPORT_REL_WITHOUT_DISPATCHER=\ + Context: "{0}" \u304a\u3088\u3073 URL: "{1}" \u306b\u5bfe\u3057\u3066 RequestDispatcher \u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002\u6307\u5b9a\u3057\u305f\u5024\u3092\u78ba\u8a8d\u3059\u308b\u304b\u3001\u3082\u3057\u304f\u306f\u3001Context \u3092\u76f8\u4e92\u7684\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3088\u3046\u306b\u3057\u3066\u304f\u3060\u3055\u3044 + +IMPORT_IO=\ + <import> \u3067\u3001"{0}" \u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u5165\u51fa\u529b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +IMPORT_ILLEGAL_STREAM=\ + <import> \u5185\u3067\u4e88\u671f\u305b\u306c\u5185\u90e8\u30a8\u30e9\u30fc: \u5bfe\u8c61\u3068\u306a\u3063\u305f Servlet \u3067 getWriter() \u30e1\u30bd\u30c3\u30c9\u304c\u547c\u3073\u51fa\u3055\u308c\u3066\u3044\u308b\u306e\u306b getOutputStream() \u30e1\u30bd\u30c3\u30c9\u3092\u547c\u3073\u51fa\u305d\u3046\u3068\u3057\u307e\u3057\u305f + +IMPORT_ILLEGAL_WRITER=\ + <import> \u5185\u3067\u4e88\u671f\u305b\u306c\u5185\u90e8\u30a8\u30e9\u30fc: \u5bfe\u8c61\u3068\u306a\u3063\u305f Servlet \u3067 getOutputStream() \u30e1\u30bd\u30c3\u30c9\u304c\u547c\u3073\u51fa\u3055\u308c\u3066\u3044\u308b\u306e\u306b getWriter() \u30e1\u30bd\u30c3\u30c9\u3092\u547c\u3073\u51fa\u305d\u3046\u3068\u3057\u307e\u3057\u305f + +#IMPORT_ILLEGAL_GETSTRING=\ +# Unexpected internal error during <import>: \ +# Target servlet called neither getOutputStream() nor getWriter() + +PARAM_OUTSIDE_PARENT=\ + <import> \u3082\u3057\u304f\u306f <urlEncode> \u306e\u5916\u5074\u306b <param> \u304c\u3042\u308a\u307e\u3059 + +PARAM_ENCODE_BOOLEAN=\ + <param> \u3067\u306f\u3001"encode" \u306f "true" \u3082\u3057\u304f\u306f "false" \u3067\u306a\u3044\u3068\u3044\u3051\u307e\u305b\u3093\u3002\u4ee3\u308f\u308a\u306b "{0}" \u3092\u53d6\u5f97\u3057\u307e\u3057\u305f + +SET_BAD_SCOPE=\ + <set> \u306b\u5bfe\u3057\u3001\u7121\u52b9\u306a "scope" \u5c5e\u6027\u3067\u3059: "{0}" + +SET_INVALID_PROPERTY=\ + <set> \u306b\u5bfe\u3057\u3001\u7121\u52b9\u306a\u30d7\u30ed\u30d1\u30c6\u30a3\u3067\u3059: "{0}" + +SET_INVALID_TARGET=\ + <set> \u306b\u5bfe\u3057\u3001\u7121\u52b9\u306a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30d7\u30ed\u30d1\u30c6\u30a3\u3092\u30bb\u30c3\u30c8\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +SET_NO_VALUE=\ + <set> \u3067\u306f\u3001\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u3082\u3057\u304f\u306f "value" \u5c5e\u6027\u304c\u5fc5\u8981\u3067\u3059 + +URLENCODE_NO_VALUE=\ + <urlEncode> \u3067\u306f\u3001\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u3082\u3057\u304f\u306f "value" \u5c5e\u6027\u304c\u5fc5\u8981\u3067\u3059 + +WHEN_OUTSIDE_CHOOSE=\ + \u76f4\u8fd1\u306e\u89aa\u30bf\u30b0\u3067\u3042\u308b <choose> \u3092\u30bb\u30c3\u30c8\u305b\u305a\u306b <when> \u30b9\u30bf\u30a4\u30eb\u30fb\u30bf\u30b0\u3092\u4f7f\u3046\u3053\u3068\u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +# I18N + +LOCALE_NO_LANGUAGE=\ + <setLocale> \u3067\u3001'value' \u5c5e\u6027\u306b\u6307\u5b9a\u3057\u305f\u8a00\u8a9e\u30b3\u30fc\u30c9\u304c\u307e\u3061\u304c\u3063\u3066\u3044\u307e\u3059 + +LOCALE_EMPTY_COUNTRY=\ + <setLocale> \u3067\u3001'value' \u5c5e\u6027\u306b\u6307\u5b9a\u3057\u305f\u56fd\u30b3\u30fc\u30c9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093 + +PARAM_OUTSIDE_MESSAGE=\ + <message> \u306e\u5916\u5074\u306b <param> \u304c\u3042\u308a\u307e\u3059 + +MESSAGE_NO_KEY=\ + <message> \u3067\u306f 'key' \u5c5e\u6027\u3082\u3057\u304f\u306f\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u304c\u5fc5\u8981\u3067\u3059 + +FORMAT_NUMBER_INVALID_TYPE=\ + <formatNumber> \u3067\u3001\u7121\u52b9\u306a 'type' \u5c5e\u6027\u3067\u3059: "{0}" + +FORMAT_NUMBER_NO_VALUE=\ + <formatNumber> \u3067\u306f 'value' \u5c5e\u6027\u3082\u3057\u304f\u306f\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u304c\u5fc5\u8981\u3067\u3059 + +FORMAT_NUMBER_PARSE_ERROR=\ + <formatNumber> \u5185\u306b\u3042\u308b\u3001'value' \u5c5e\u6027\u3092 java.lang.Number \u578b\u3067\u89e3\u6790\u3067\u304d\u307e\u305b\u3093: "{0}" + +FORMAT_NUMBER_CURRENCY_ERROR=\ + <formatNumber> \u3067\u3001\u901a\u8ca8\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u3092\u30bb\u30c3\u30c8\u3067\u304d\u307e\u305b\u3093 + +PARSE_NUMBER_INVALID_TYPE=\ + <parseNumber> \u3067\u3001\u7121\u52b9\u306a 'type' \u5c5e\u6027\u3067\u3059: "{0}" + +PARSE_NUMBER_NO_VALUE=\ + <parseNumber> \u3067\u306f 'value' \u5c5e\u6027\u3082\u3057\u304f\u306f\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u304c\u5fc5\u8981\u3067\u3059 + +PARSE_NUMBER_NO_PARSE_LOCALE=\ + <parseNumber> \u5185\u3067\u3001\u89e3\u6790\u3055\u308c\u305f\u30ed\u30b1\u30fc\u30eb\u3092\u78ba\u5b9a\u3067\u304d\u307e\u305b\u3093 + +PARSE_NUMBER_PARSE_ERROR=\ + <parseNumber> \u5185\u306b\u3042\u308b\u3001'value' \u5c5e\u6027\u3092\u89e3\u6790\u3067\u304d\u307e\u305b\u3093: "{0}" + +FORMAT_DATE_INVALID_TYPE=\ + <formatDate> \u3067\u3001\u7121\u52b9\u306a 'type' \u5c5e\u6027\u3067\u3059: "{0}" + +FORMAT_DATE_BAD_TIMEZONE=\ + <formatDate> \u3067\u306f\u3001'timeZone' \u306f java.lang.String \u578b\u3082\u3057\u304f\u306f java.util.TimeZone \u578b\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u306a\u3044\u3068\u3044\u3051\u307e\u305b\u3093 + +FORMAT_DATE_INVALID_DATE_STYLE=\ + <formatDate> \u3067\u3001\u7121\u52b9\u306a 'dateStyle' \u5c5e\u6027\u3067\u3059: "{0}" + +FORMAT_DATE_INVALID_TIME_STYLE=\ + <formatDate> \u3067\u3001\u7121\u52b9\u306a 'timeStyle' \u5c5e\u6027\u3067\u3059: "{0}" + +PARSE_DATE_INVALID_TYPE=\ + <parseDate> \u3067\u3001\u7121\u52b9\u306a 'type' \u5c5e\u6027\u3067\u3059: "{0}" + +PARSE_DATE_BAD_TIMEZONE=\ + <parseDate> \u5185\u306b\u3042\u308b\u3001'timeZone' \u306f java.lang.String \u578b\u3082\u3057\u304f\u306f java.util.TimeZone \u578b\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u306a\u3044\u3068\u3044\u3051\u307e\u305b\u3093 + +PARSE_DATE_INVALID_DATE_STYLE=\ + <parseDate> \u3067\u3001\u7121\u52b9\u306a 'dateStyle' \u5c5e\u6027\u3067\u3059: "{0}" + +PARSE_DATE_INVALID_TIME_STYLE=\ + <parseDate> \u3067\u3001\u7121\u52b9\u306a 'timeStyle' \u5c5e\u6027\u3067\u3059: "{0}" + +PARSE_DATE_NO_VALUE=\ + <parseDate> \u3067\u306f 'value' \u5c5e\u6027\u3082\u3057\u304f\u306f\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u304c\u5fc5\u8981\u3067\u3059 + +PARSE_DATE_PARSE_ERROR=\ + <parseDate> \u5185\u306b\u3042\u308b\u3001'value' \u5c5e\u6027\u3092\u89e3\u6790\u3067\u304d\u307e\u305b\u3093: "{0}" + +PARSE_DATE_NO_PARSE_LOCALE=\ + <parseDate> \u5185\u3067\u3001\u89e3\u6790\u3055\u308c\u305f\u30ed\u30b1\u30fc\u30eb\u3092\u78ba\u5b9a\u3067\u304d\u307e\u305b\u3093 + +# SQL + +DRIVER_INVALID_CLASS=\ + <driver> \u3067\u3001\u7121\u52b9\u306a\u30c9\u30e9\u30a4\u30d0\u30fb\u30af\u30e9\u30b9\u540d\u3092\u6307\u5b9a\u3057\u307e\u3057\u305f: "{0}" + +DATASOURCE_INVALID=\ + DataSource \u304c\u7121\u52b9\u3067\u3042\u308b\u305f\u3081\u3001Connection \u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093: "{0}" + +JDBC_PARAM_COUNT=\ + \u6307\u5b9a\u3057\u305f JDBC \u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u6570\u304c\u7121\u52b9\u3067\u3059 + +PARAM_BAD_VALUE=\ + \u30d1\u30e9\u30e1\u30fc\u30bf\u3067\u6307\u5b9a\u3057\u305f\u5024\u304c\u7121\u52b9\u3067\u3042\u308b\u304b\u7bc4\u56f2\u5916\u3067\u3059 + +TRANSACTION_NO_SUPPORT=\ + <transaction> \u5185\u306b\u3042\u308b\u3001DataSource \u306f\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093 + +TRANSACTION_COMMIT_ERROR=\ + <transaction> \u306b\u304a\u3044\u3066\u3001\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u30b3\u30df\u30c3\u30c8\u6642\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: "{0}" + +TRANSACTION_INVALID_ISOLATION=\ + <transaction> \u306b\u304a\u3044\u3066\u3001\u7121\u52b9\u306a\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u906e\u65ad\u30ec\u30d9\u30eb\u3092\u6307\u5b9a\u3057\u307e\u3057\u305f + +NOT_SUPPORTED=\ + \u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093 + +ERROR_GET_CONNECTION=\ + Connection \u306e\u53d6\u5f97\u6642\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: "{0}" + +ERROR_NESTED_DATASOURCE=\ + <transaction> \u306e\u4e2d\u3067\u5165\u308c\u5b50\u3068\u306a\u3063\u305f\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u306f\u4e0d\u6b63\u3067\u3059 + +SQL_PARAM_OUTSIDE_PARENT=\ + <param> \u307e\u305f\u306f <dateParam> \u306f <query> \u3082\u3057\u304f\u306f <update> \u306e\u3088\u3046\u306b SQLExecutionTag \u547d\u4ee4\u306e\u4e0b\u4f4d\u30bf\u30b0\u3067\u306a\u3051\u308c\u3070\u3044\u3051\u307e\u305b\u3093 + +SQL_NO_STATEMENT=\ + SQL \u30b9\u30c6\u30fc\u30c8\u30e1\u30f3\u30c8\u304c\u6307\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 + +SQL_PROCESS_ERROR=\ + SQL \u306e\u51e6\u7406\u6642\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: "{0}" + +SQL_DATASOURCE_INVALID_TYPE=\ + 'dataSource' \u304c String \u578b \u3067\u3082 javax.sql.DataSource \u578b\u306e\u3069\u3061\u3089\u3067\u3082\u3042\u308a\u307e\u305b\u3093 + +SQL_DATASOURCE_NULL=\ + 'dataSource' \u304c null \u3067\u3059 + +SQL_MAXROWS_PARSE_ERROR=\ + 'javax.servlet.jsp.jstl.sql.maxRows' \u306e\u74b0\u5883\u8a2d\u5b9a\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: "{0}" + +SQL_MAXROWS_INVALID=\ + 'javax.servlet.jsp.jstl.sql.maxRows' \u3067\u74b0\u5883\u8a2d\u5b9a\u3057\u305f\u5024\u306f Integer \u578b \u3067\u3082 String \u578b\u306e\u3069\u3061\u3089\u3067\u3082\u3042\u308a\u307e\u305b\u3093 + +SQL_DATE_PARAM_INVALID_TYPE=\ + <dateParam> \u3067\u3001\u7121\u52b9\u306a 'type' \u5c5e\u6027\u3067\u3059: "{0}" + +# XML + +FOREACH_NOT_NODESET=\ + \u30ce\u30fc\u30c9\u30bb\u30c3\u30c8\u306e\u8fd4\u3055\u308c\u306a\u3044 XPath \u8868\u73fe\u306b\u5bfe\u3057 <forEach> \u306f\u53cd\u5fa9\u51e6\u7406\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 + +PARAM_NO_VALUE=\ + <param> \u3067\u306f 'value' \u5c5e\u6027\u3082\u3057\u304f\u306f\u30db\u30ef\u30a4\u30c8\u30b9\u30da\u30fc\u30b9\u306e\u306a\u3044\u30dc\u30c7\u30a3\u304c\u5fc5\u8981\u3067\u3059 + +PARAM_OUTSIDE_TRANSFORM=\ + <transform> \u306e\u5916\u5074\u306b <param> \u304c\u3042\u308a\u307e\u3059 + +PARSE_INVALID_SOURCE=\ + <parse> \u306b\u5bfe\u3057 'xml' \u5c5e\u6027\u3068\u3057\u3066\u4f9b\u7d66\u3057\u305f\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092\u8a8d\u8b58\u3067\u304d\u307e\u305b\u3093 + +PARSE_NO_SAXTRANSFORMER=\ + <parse> \u306b\u5bfe\u3057\u30d5\u30a3\u30eb\u30bf\u30fc\u304c\u4f9b\u7d66\u3055\u308c\u307e\u3057\u305f\u304c\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u306e TransformerFactory \u304c SAX \u3092\u30b5\u30dd\u30fc\u30c8\u3057\u3066\u3044\u307e\u305b\u3093 + +TRANSFORM_NO_TRANSFORMER=\ + <transform> \u306b\u5bfe\u3057 XSLT \u30b9\u30bf\u30a4\u30eb\u30b7\u30fc\u30c8\u304c\u901a\u308a\u307e\u305b\u3093 + +TRANSFORM_SOURCE_INVALID_LIST=\ + <transform> \u5185\u3067 'xml' \u5c5e\u6027\u306e\u51e6\u7406\u4e2d\u306b\u7121\u52b9\u306a java.util.List \u3068\u906d\u9047\u3057\u307e\u3057\u305f\u3002\u3053\u308c\u306f\u3001<transform> \u5185\u306e 'xml' \u5c5e\u6027\u306b\u5bfe\u3057\u3066 1 \u4ee5\u4e0a\u306e\u30ce\u30fc\u30c9\u3067\u69cb\u6210\u3055\u308c\u308b\u30ce\u30fc\u30c9\u30bb\u30c3\u30c8\u3092\u901a\u3055\u306a\u3044\u5834\u5408\u306b\u767a\u751f\u3059\u308b\u5178\u578b\u7684\u306a\u30a8\u30e9\u30fc\u3067\u3059 + +TRANSFORM_SOURCE_UNRECOGNIZED=\ + <transform> \u5185\u3067 'xml' \u5c5e\u6027\u306e\u51e6\u7406\u4e2d\u306b\u672a\u77e5\u306e\u578b\u3068\u906d\u9047\u3057\u307e\u3057\u305f + +TRANSFORM_XSLT_UNRECOGNIZED=\ + <transform> \u5185\u3067 'xslt' \u5c5e\u6027\u306e\u51e6\u7406\u4e2d\u306b\u672a\u77e5\u306e\u578b\u3068\u906d\u9047\u3057\u307e\u3057\u305f + +UNABLE_TO_RESOLVE_ENTITY=\ + \u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u53c2\u7167\u3092\u89e3\u6c7a\u3067\u304d\u307e\u305b\u3093: "{0}" + +######################################################################### +# JSTL core TLV messages +######################################################################### + +# Parameters + +TLV_PARAMETER_ERROR=\ + TLD \u306b\u3088\u308b\u3068 "{0}" \u6709\u52b9\u30d1\u30e9\u30e1\u30fc\u30bf\u306b\u5bfe\u5fdc\u3059\u308b\u5024\u304c\u7121\u52b9\u3067\u3059 + +# Generic errors + +TLV_ILLEGAL_BODY=\ + \u5c5e\u6027\u3092\u6307\u5b9a\u3057\u307e\u3057\u305f\u304c\u3001"{0}" \u30bf\u30b0\u3067\u4e0d\u6b63\u306a\u30dc\u30c7\u30a3\u306b\u906d\u9047\u3057\u307e\u3057\u305f + +TLV_MISSING_BODY=\ + \u5c5e\u6027\u3092\u6307\u5b9a\u3057\u307e\u3057\u305f\u304c\u3001\u30dc\u30c7\u30a3\u306f "{0}" \u30bf\u30b0\u306e\u4e2d\u306b\u5fc5\u8981\u3067\u3059 + +TLV_ILLEGAL_CHILD_TAG=\ + "{0}:{1}" \u30bf\u30b0\u306b\u4e0d\u6b63\u306a\u4e0b\u4f4d\u30bf\u30b0\u304c\u3042\u308a\u307e\u3059: "{2}" \u30bf\u30b0 + +TLV_ILLEGAL_TEXT_BODY=\ + "{0}:{1}" \u30bf\u30b0\u306e\u4e2d\u306b\u4e0d\u6b63\u306a\u30c6\u30ad\u30b9\u30c8\u304c\u3042\u308a\u307e\u3059: "{2}...". + +TLV_INVALID_ATTRIBUTE=\ + "{1}" \u306b\u7121\u52b9\u306a "{0}" \u5c5e\u6027\u304c\u3042\u308a\u307e\u3059: "{2}" + +TLV_ILLEGAL_ORPHAN=\ + \u9069\u5207\u306a\u89aa\u30bf\u30b0\u306e\u5916\u5074\u306b\u3042\u308b "{0}" \u30bf\u30b0\u306e\u4f7f\u3044\u65b9\u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +TLV_PARENT_WITHOUT_SUBTAG=\ + \u4e0b\u4f4d\u3067\u3042\u308b "{1}" \u30bf\u30b0\u306e\u306a\u3044 "{0}" \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +# Errors customized to particular tags (sort of) :-) + +TLV_ILLEGAL_ORDER=\ + "{1}:{3}" \u30bf\u30b0\u3067\u306f\u3001"{1}:{2}" \u30bf\u30b0\u306e\u5f8c\u306b\u3042\u308b "{0}" \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +TLV_ILLEGAL_PARAM=\ + "{0}:{2} {3}='...'" \u30bf\u30b0\u306e\u4e2d\u306b\u3042\u308b "{0}:{1}" \u30bf\u30b0\u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +TLV_DANGLING_SCOPE=\ + "{0}" \u30bf\u30b0\u3067 'var' \u304c\u5b58\u5728\u3057\u306a\u3044\u306e\u306b 'scope' \u5c5e\u6027\u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 + +TLV_EMPTY_VAR=\ + "{0}" \u30bf\u30b0\u3067 'var' \u5c5e\u6027\u304c\u7a7a\u3067\u3059 + +SET_NO_SETTER_METHOD=\ + <set> \u306b\u304a\u3044\u3066\u3001\u30d7\u30ed\u30d1\u30c6\u30a3 "{0}" \u306b\u5bfe\u5fdc\u3059\u308b setter \u30e1\u30bd\u30c3\u30c9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093 + +IMPORT_ABS_ERROR=Problem accessing the absolute URL "{0}". {1} + +XPATH_ERROR_EVALUATING_EXPR=Error evaluating XPath expression "{0}": {1} + +XPATH_ILLEGAL_ARG_EVALUATING_EXPR=Illegal argument evaluating XPath expression "{0}": {1} + +XPATH_ERROR_XOBJECT=Error accessing data in XObject: {0} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/VersionTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/VersionTest.java new file mode 100644 index 000000000..89863c994 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/VersionTest.java @@ -0,0 +1,87 @@ +/* + * 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.taglibs.standard; + +import junit.framework.TestCase; + +public class VersionTest + extends TestCase { + private Version version = null; + + public VersionTest(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + version = new Version(); + } + + @Override + protected void tearDown() throws Exception { + version = null; + super.tearDown(); + } + + public void testVersion() { + version = new Version(); + } + + public void testGetDevelopmentVersionNum() { + int expectedReturn = 0; + int actualReturn = Version.getDevelopmentVersionNum(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testGetMaintenanceVersionNum() { + int expectedReturn = 6; + int actualReturn = Version.getMaintenanceVersionNum(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testGetMajorVersionNum() { + int expectedReturn = 1; + int actualReturn = Version.getMajorVersionNum(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testGetProduct() { + String expectedReturn = "standard-taglib"; + String actualReturn = Version.getProduct(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testGetReleaseVersionNum() { + int expectedReturn = 2; + int actualReturn = Version.getReleaseVersionNum(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testGetVersion() { + String expectedReturn = "standard-taglib 1.2.6"; + String actualReturn = Version.getVersion(); + assertEquals("return value", expectedReturn, actualReturn); + } + + public void testMain() { + String[] argv = null; + Version.main(argv); + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/functions/FunctionsTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/functions/FunctionsTest.java new file mode 100644 index 000000000..59bde70b4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/functions/FunctionsTest.java @@ -0,0 +1,137 @@ +/* + * 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.taglibs.standard.functions; + +import java.util.Arrays; +import java.util.Collections; + +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.resources.Resources; +import org.junit.Assert; +import org.junit.Test; + +import static org.apache.taglibs.standard.functions.Functions.endsWith; +import static org.apache.taglibs.standard.functions.Functions.escapeXml; +import static org.apache.taglibs.standard.functions.Functions.join; +import static org.apache.taglibs.standard.functions.Functions.length; +import static org.apache.taglibs.standard.functions.Functions.replace; +import static org.apache.taglibs.standard.functions.Functions.split; +import static org.apache.taglibs.standard.functions.Functions.substring; +import static org.apache.taglibs.standard.functions.Functions.substringAfter; +import static org.apache.taglibs.standard.functions.Functions.substringBefore; + +/** + */ +public class FunctionsTest { + + @Test + public void testEndsWith() { + Assert.assertTrue(endsWith("00", "0")); // verify bug 50057 was fixed + } + + @Test + public void testSubstring() { + Assert.assertEquals("el", substring("Hello", 1, 3)); + Assert.assertEquals("", substring("Hello", 10, 0)); + Assert.assertEquals("He", substring("Hello", -1, 2)); + Assert.assertEquals("Hello", substring("Hello", -4, -1)); + Assert.assertEquals("ello", substring("Hello", 1, -1)); + Assert.assertEquals("ello", substring("Hello", 1, 10)); + Assert.assertEquals("", substring("Hello", 3, 1)); + Assert.assertEquals("", substring("Hello", 10, 6)); + Assert.assertEquals("Hello", substring("Hello", -1, -4)); + } + + @Test + public void testSubstringAfter() { + Assert.assertEquals("lo", substringAfter("Hello", "el")); + Assert.assertEquals("", substringAfter("", "el")); + Assert.assertEquals("Hello", substringAfter("Hello", "")); + Assert.assertEquals("", substringAfter("", "lx")); + Assert.assertEquals("lo All", substringAfter("Hello All", "l")); + } + + @Test + public void testSubstringBefore() { + Assert.assertEquals("H", substringBefore("Hello", "el")); + Assert.assertEquals("", substringBefore("", "el")); + Assert.assertEquals("", substringBefore("Hello", "")); + Assert.assertEquals("", substringBefore("", "lx")); + Assert.assertEquals("He", substringBefore("Hello All", "l")); + } + + @Test + public void testReplace() { + Assert.assertEquals("Hxxlo", replace("Hello", "el", "xx")); + Assert.assertEquals("Hexxxxo", replace("Hello", "l", "xx")); + Assert.assertEquals("", replace("", "l", "xx")); + Assert.assertEquals("Heo", replace("Hello", "l", "")); + Assert.assertEquals("Hello", replace("Hello", "", "xx")); + Assert.assertEquals("Hellllo", replace("Hello", "l", "ll")); + Assert.assertEquals("Hello", replace("Hello", "x", "ll")); + } + + @Test + public void testSplit() { + Assert.assertArrayEquals(new String[]{"a", "b", "c"}, split("a:b:c", ":")); + Assert.assertArrayEquals(new String[]{"a", "b", "c"}, split("a:b/c", ":/")); + Assert.assertArrayEquals(new String[]{"a", "b", "c"}, split("a:b/c", "/:")); + Assert.assertArrayEquals(new String[]{"a", "b"}, split("a:b:", ":")); + Assert.assertArrayEquals(new String[]{"a:b:c"}, split("a:b:c", "x")); + Assert.assertArrayEquals(new String[]{""}, split("", "")); + Assert.assertArrayEquals(new String[]{""}, split("", ":")); + Assert.assertArrayEquals(new String[]{"Hello"}, split("Hello", "")); + } + + @Test + public void testJoin() { + Assert.assertEquals("a:b:c", join(new String[]{"a", "b", "c"}, ":")); + Assert.assertEquals("abc", join(new String[]{"a", "b", "c"}, "")); + Assert.assertEquals("axxbxxc", join(new String[]{"a", "b", "c"}, "xx")); + Assert.assertEquals("", join(null, "")); + Assert.assertEquals("", join(new String[]{}, ":")); + Assert.assertEquals("a:null:c", join(new String[]{"a", null, "c"}, ":")); + Assert.assertEquals("a", join(new String[]{"a"}, ":")); + Assert.assertEquals("null", join(new String[]{null}, ":")); + } + + @Test + public void testLength() throws Exception { + Assert.assertEquals(0, length(null)); + Assert.assertEquals(0, length("")); + Assert.assertEquals(3, length(new int[]{1, 2, 3})); + Assert.assertEquals(3, length(Arrays.asList(1, 2, 3))); + Assert.assertEquals(3, length(Arrays.asList(1, 2, 3).iterator())); + Assert.assertEquals(3, length(Collections.enumeration(Arrays.asList(1, 2, 3)))); + Assert.assertEquals(1, length(Collections.singletonMap("Hello", "World"))); + try { + length(3); + Assert.fail(); + } catch (JspTagException e) { + Assert.assertEquals(Resources.getMessage("PARAM_BAD_VALUE"), e.getMessage()); + } + } + + @Test + public void testEscapeXML() { + Assert.assertEquals("Hello", escapeXml("Hello")); + Assert.assertEquals("<Hello msg="world"/>", escapeXml("")); + Assert.assertEquals("<Hello msg='world'/>", escapeXml("")); + Assert.assertEquals("cats & dogs", escapeXml("cats & dogs")); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/resources/ResourcesTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/resources/ResourcesTest.java new file mode 100644 index 000000000..b68260a1d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/resources/ResourcesTest.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.resources; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +public class ResourcesTest { + + @Test + public void testMessageNoArguments() { + assertEquals("test no arguments", Resources.getMessage("TEST_NO_ARGUMENTS")); + } + + @Test + public void testMessageOneArgument() { + assertEquals("test argument one", Resources.getMessage("TEST_ONE_ARGUMENT", "one")); + } + + @Test + public void testMessageMultipleArguments() { + assertEquals("test argument one 2", Resources.getMessage("TEST_MULTIPLE_ARGUMENT", "one", 2)); + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/core/SetSupportTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/core/SetSupportTest.java new file mode 100644 index 000000000..f4c50d0ae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/core/SetSupportTest.java @@ -0,0 +1,424 @@ +/* + * 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.taglibs.standard.tag.common.core; + +import java.util.Map; + +import jakarta.el.ELContext; +import jakarta.el.ExpressionFactory; +import jakarta.el.ValueExpression; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.JspApplicationContext; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspFactory; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.BodyContent; + +import org.apache.taglibs.standard.resources.Resources; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +public class SetSupportTest { + private static String PROPERTY = "property"; + private static String VALUE = "Hello"; + private static final String VAR = "x"; + + private PageContext pageContext; + private ELContext elContext; + private VariableMapper vm; + private Bean bean; + + private SetSupport tag; + + @Before + public void setup() { + pageContext = createMock(PageContext.class); + elContext = createMock(ELContext.class); + vm = createMock(VariableMapper.class); + + expect(pageContext.getELContext()).andStubReturn(elContext); + expect(pageContext.getServletContext()).andStubReturn(null); + expect(elContext.getVariableMapper()).andStubReturn(vm); + + bean = new Bean(); + + + ExpressionFactory expressionFactory = createMock(ExpressionFactory.class); + JspApplicationContext applicationContext = createMock(JspApplicationContext.class); + JspFactory jspFactory = createMock(JspFactory.class); + expect(expressionFactory.coerceToType(VALUE, String.class)).andStubReturn(VALUE); + expect(expressionFactory.coerceToType(null, String.class)).andStubReturn(null); + expect(applicationContext.getExpressionFactory()).andStubReturn(expressionFactory); + expect(jspFactory.getJspApplicationContext(null)).andStubReturn(applicationContext); + replay(jspFactory, applicationContext, expressionFactory); + JspFactory.setDefaultFactory(jspFactory); + } + + @After + public void teardown() { + JspFactory.setDefaultFactory(null); + } + + @Test + public void testSyntax1WithNoScope() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.setAttribute(VAR, VALUE, PageContext.PAGE_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax1WithNullScope() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + tag.setScope(null); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.setAttribute(VAR, VALUE, PageContext.PAGE_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax1WithPageScope() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + tag.setScope("page"); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.setAttribute(VAR, VALUE, PageContext.PAGE_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax1WithNonPageScope() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + tag.setScope("request"); + + // verify mapper is not checked + pageContext.setAttribute(VAR, VALUE, PageContext.REQUEST_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax1WithNullValueAndNoScope() throws JspException { + tag = new MockSetSupport(null); + tag.setPageContext(pageContext); + tag.setVar(VAR); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.removeAttribute(VAR); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax1WithNullValueAndNonPageScope() throws JspException { + tag = new MockSetSupport(null); + tag.setPageContext(pageContext); + tag.setVar(VAR); + tag.setScope("request"); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.removeAttribute(VAR, PageContext.REQUEST_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testSyntax3WithMap() throws JspException { + @SuppressWarnings("unchecked") + Map target = createMock(Map.class); + tag = new MockSetSupport(VALUE, target, PROPERTY); + tag.setPageContext(pageContext); + + expect(target.put(PROPERTY, VALUE)).andStubReturn(null); + replay(target); + tag.doEndTag(); + verify(target); + } + + @Test + public void testSyntax3WithMapWhenPropertyIsNull() throws JspException { + @SuppressWarnings("unchecked") + Map target = createMock(Map.class); + tag = new MockSetSupport(VALUE, target, null); + tag.setPageContext(pageContext); + + expect(target.put(null, VALUE)).andStubReturn(null); + replay(target); + tag.doEndTag(); + verify(target); + } + + @Test + public void testSyntax3WithMapWhenValueIsNull() throws JspException { + @SuppressWarnings("unchecked") + Map target = createMock(Map.class); + tag = new MockSetSupport(null, target, PROPERTY); + tag.setPageContext(pageContext); + + expect(target.remove(PROPERTY)).andStubReturn(null); + replay(target); + tag.doEndTag(); + verify(target); + } + + @Test + public void testSyntax3WithBean() throws JspException { + tag = new MockSetSupport(VALUE, bean, PROPERTY); + tag.setPageContext(pageContext); + + tag.doEndTag(); + Assert.assertEquals(VALUE, bean.getProperty()); + } + + @Test + public void testSyntax3WithBeanAndNullValue() throws JspException { + tag = new MockSetSupport(null, bean, PROPERTY); + tag.setPageContext(pageContext); + + tag.doEndTag(); + Assert.assertNull(bean.getProperty()); + } + + @Test + public void testSyntax3WithBeanAndUndefinedProperty() throws JspException { + tag = new MockSetSupport(VALUE, bean, "undefined"); + tag.setPageContext(pageContext); + + try { + tag.doEndTag(); + } catch (JspTagException e) { + Assert.assertEquals(e.getMessage(), Resources.getMessage("SET_INVALID_PROPERTY", "undefined")); + } + } + + @Test + public void testSyntax3WithBeanAndReadOnlyProperty() throws JspException { + tag = new MockSetSupport(VALUE, bean, "readOnly"); + tag.setPageContext(pageContext); + + try { + tag.doEndTag(); + } catch (JspException e) { + Assert.assertEquals(e.getMessage(), Resources.getMessage("SET_NO_SETTER_METHOD", "readOnly")); + } + } + + @Test + public void testSyntax3WhenTargetIsNull() throws JspException { + tag = new MockSetSupport(VALUE, null, PROPERTY); + tag.setPageContext(pageContext); + + try { + tag.doEndTag(); + Assert.fail(); + } catch (JspTagException e) { + Assert.assertEquals(e.getMessage(), Resources.getMessage("SET_INVALID_TARGET")); + } + } + + /** + * Verify Bug 49526 when there is no existing variable mapping. + * + * @throws JspException if there's an error + */ + @Test + public void test49526WhenNotMapped() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + + // verify mapper is checked but that no action is taken + expect(vm.resolveVariable(VAR)).andReturn(null); + pageContext.setAttribute(VAR, VALUE, PageContext.PAGE_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + /** + * Verify Bug 49526 when there is an existing variable mapping. + * + * @throws JspException if there's an error + */ + @Test + public void test49526WhenAlreadyMapped() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + + // verify mapper is checked and the mapped variable removed + ValueExpression ve = createMock(ValueExpression.class); + expect(vm.resolveVariable(VAR)).andReturn(ve); + expect(vm.setVariable(VAR, null)).andReturn(ve); + pageContext.setAttribute(VAR, VALUE, PageContext.PAGE_SCOPE); + replay(pageContext, elContext, vm, ve); + tag.doEndTag(); + verify(pageContext, elContext, vm, ve); + } + + /** + * Verify Bug 49526 when we are not setting into the page context. + * + * @throws JspException if there's an error + */ + @Test + public void test49526WhenNotUsingPageContext() throws JspException { + tag = new MockSetSupport(VALUE); + tag.setPageContext(pageContext); + tag.setVar(VAR); + tag.setScope("request"); + + // verify mapper is not checked + pageContext.setAttribute(VAR, VALUE, PageContext.REQUEST_SCOPE); + replay(pageContext, elContext, vm); + tag.doEndTag(); + verify(pageContext, elContext, vm); + } + + @Test + public void testResultFromValueAttribute() throws JspException { + tag = new MockSetSupport(VALUE); + Assert.assertSame(VALUE, tag.getResult()); + } + + @Test + public void testResultFromNullValueAttribute() throws JspException { + tag = new MockSetSupport(null); + Assert.assertNull(tag.getResult()); + } + + @Test + public void testResultFromBodyContent() throws JspException { + tag = new MockSetSupport(); + BodyContent bodyContent = createMock(BodyContent.class); + expect(bodyContent.getString()).andStubReturn(" Hello "); + replay(bodyContent); + tag.setBodyContent(bodyContent); + Assert.assertEquals(VALUE, tag.getResult()); + } + + @Test + public void testResultFromNullBodyContent() throws JspException { + tag = new MockSetSupport(); + tag.setBodyContent(null); + Assert.assertEquals(tag.getResult(), ""); + } + + @Test + public void testResultFromEmptyBodyContent() throws JspException { + tag = new MockSetSupport(); + BodyContent bodyContent = createMock(BodyContent.class); + expect(bodyContent.getString()).andStubReturn(null); + Assert.assertEquals("", tag.getResult()); + } + + public static class MockSetSupport extends SetSupport { + private final boolean valueSpecified; + private final Object value; + private final Object target; + private final String property; + + public MockSetSupport() { + this.value = null; + this.valueSpecified = false; + this.target = null; + this.property = null; + } + + public MockSetSupport(Object value, Object target, String property) { + this.value = value; + this.valueSpecified = true; + this.target = target; + this.property = property; + } + + public MockSetSupport(Object value) { + this.value = value; + this.valueSpecified = true; + this.target = null; + this.property = null; + } + + @Override + protected boolean isValueSpecified() { + return valueSpecified; + } + + @Override + protected Object evalValue() { + return value; + } + + @Override + protected Object evalTarget() { + return target; + } + + @Override + protected String evalProperty() { + return property; + } + } + + public static class Bean { + private String property; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + + public boolean isReadOnly() { + return true; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupportTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupportTest.java new file mode 100644 index 000000000..3a829c440 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupportTest.java @@ -0,0 +1,47 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import jakarta.servlet.jsp.tagext.BodyContent; + +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + */ +public class BundleSupportTest { + + private BundleSupport tag; + + @Before + public void setup() { + tag = new BundleSupport() { + }; + } + + // test for bugzilla #49900 that bodyContent is not released + + @Test + public void testBodyContentIsRelease() { + BodyContent b = EasyMock.createMock(BodyContent.class); + tag.setBodyContent(b); + tag.release(); + Assert.assertNull(tag.getBodyContent()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtilTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtilTest.java new file mode 100644 index 000000000..a052798af --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/fmt/LocaleUtilTest.java @@ -0,0 +1,61 @@ +/* + * 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.taglibs.standard.tag.common.fmt; + +import junit.framework.Assert; +import org.junit.Test; + +import java.util.Locale; + +public class LocaleUtilTest { + + @Test + public void testLocaleWithLanguage() { + Assert.assertEquals(new Locale("fr"), LocaleUtil.parseLocale("fr", null)); + } + + @Test + public void testLocaleUsingHyphen() { + Assert.assertEquals(new Locale("en", "DE"), LocaleUtil.parseLocale("en-DE", null)); + } + + @Test + public void testLocaleUsingUnderscore() { + Assert.assertEquals(new Locale("en", "IE"), LocaleUtil.parseLocale("en_IE", null)); + Assert.assertEquals(new Locale("en", "IE"), LocaleUtil.parseLocale("en_IE")); + } + + @Test + public void testLocaleWithLanguageVariant() { + Assert.assertEquals(new Locale("fr", "", "xxx"), LocaleUtil.parseLocale("fr", "xxx")); + } + + @Test + public void testLocaleWithLanguageCountryVariant() { + Assert.assertEquals(new Locale("en", "GB", "cockney"), LocaleUtil.parseLocale("en-GB", "cockney")); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptyLanguageIsInvalid() { + LocaleUtil.parseLocale("-GB", null); + } + + @Test(expected = IllegalArgumentException.class) + public void testEmptyCountryIsInvalid() { + LocaleUtil.parseLocale("en-", null); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java new file mode 100644 index 000000000..8b44ee7a3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ExprSupportTest.java @@ -0,0 +1,106 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import java.io.InputStream; + +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; +import javax.xml.parsers.DocumentBuilder; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.apache.taglibs.standard.util.XmlUtil; +import org.w3c.dom.Document; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + */ +public class ExprSupportTest { + + private static Document test; + + private ExprSupport tag; + private PageContext pageContext; + private JspWriter out; + + @BeforeClass + public static void loadXml() throws Exception { + DocumentBuilder db = XmlUtil.newDocumentBuilder(); + InputStream is = ExprSupportTest.class.getResourceAsStream("test.xml"); + try { + test = db.parse(is); + } finally { + is.close(); + } + } + + @Before + public void setup() { + out = createMock(JspWriter.class); + pageContext = createMock(PageContext.class); + expect(pageContext.getOut()).andStubReturn(out); + tag = new ExprSupport() { + }; + tag.setPageContext(pageContext); + } + + @Test + public void testStringLiteral() throws Exception { + tag.setSelect("\"Hello\""); + out.write("Hello", 0, 5); + replay(pageContext, out); + tag.doStartTag(); + verify(pageContext, out); + } + + @Test + public void testBooleanVariable() throws Exception { + tag.setSelect("$a"); + expect(pageContext.findAttribute("a")).andReturn(Boolean.TRUE); + out.write("true", 0, 4); + replay(pageContext, out); + tag.doStartTag(); + verify(pageContext, out); + } + + @Test + public void testNumberVariable() throws Exception { + tag.setSelect("$a"); + expect(pageContext.findAttribute("a")).andReturn(12345.678); + out.write("12345.678", 0, 9); + replay(pageContext, out); + tag.doStartTag(); + verify(pageContext, out); + } + + @Test + public void testElementFromDom() throws Exception { + tag.setSelect("$doc/root/b"); + expect(pageContext.findAttribute("doc")).andReturn(test); + out.write("Hello", 0, 5); + replay(pageContext, out); + tag.doStartTag(); + verify(pageContext, out); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java new file mode 100644 index 000000000..95e443d07 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/ForEachTagTest.java @@ -0,0 +1,251 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import java.io.InputStream; + +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.IterationTag; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathFactory; +import javax.xml.xpath.XPathVariableResolver; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import org.apache.taglibs.standard.util.XmlUtil; +import org.apache.xml.dtm.DTMIterator; +import org.apache.xpath.CachedXPathAPI; +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertEquals; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.traversal.NodeIterator; + +/** + */ +public class ForEachTagTest { + private static Document test; + + @BeforeClass + public static void loadXml() throws Exception { + DocumentBuilder db = XmlUtil.newDocumentBuilder(); + InputStream is = ExprSupportTest.class.getResourceAsStream("test.xml"); + try { + test = db.parse(is); + } finally { + is.close(); + } + } + + private ForEachTag tag; + private PageContext pageContext; + + @Before + public void setup() { + pageContext = createMock(PageContext.class); + tag = new ForEachTag(); + tag.setPageContext(pageContext); + } + + @Test + public void testIteration() throws Exception { + expect(pageContext.findAttribute("doc")).andStubReturn(test); + tag.setSelect("$doc/root/a/num"); + replay(pageContext); + tag.prepare(); + XPathContext context = tag.getContext(); + Assert.assertTrue(tag.hasNext()); + Node one = (Node) tag.next(); + assertEquals("one", one.getTextContent()); + Assert.assertTrue(tag.hasNext()); + Node two = (Node) tag.next(); + assertEquals("two", two.getTextContent()); + Assert.assertTrue(tag.hasNext()); + Node three = (Node) tag.next(); + assertEquals("three", three.getTextContent()); + Assert.assertFalse(tag.hasNext()); + tag.doFinally(); + Assert.assertTrue(context.getContextNodeListsStack().isEmpty()); + verify(pageContext); + } + + @Test + public void testIterationContext() throws Exception { + expect(pageContext.findAttribute("doc")).andStubReturn(test); + tag.setSelect("$doc/root/a/num"); + replay(pageContext); + XPath dot = new XPath(".", null, null, XPath.SELECT); + XPath position = new XPath("position()", null, null, XPath.SELECT); + XPath last = new XPath("last()", null, null, XPath.SELECT); + tag.prepare(); + XPathContext context = tag.getContext(); + tag.hasNext(); + tag.next(); + assertEquals("3", last.execute(context, context.getCurrentNode(), null).str()); + assertEquals("one", dot.execute(context, context.getCurrentNode(), null).str()); + assertEquals("1", position.execute(context, context.getCurrentNode(), null).str()); + tag.hasNext(); + tag.next(); + assertEquals("two", dot.execute(context, context.getCurrentNode(), null).str()); + assertEquals("2", position.execute(context, context.getCurrentNode(), null).str()); + tag.hasNext(); + tag.next(); + assertEquals("three", dot.execute(context, context.getCurrentNode(), null).str()); + assertEquals("3", position.execute(context, context.getCurrentNode(), null).str()); + verify(pageContext); + } + + @Ignore + @Test + public void testIterationPerformance() throws Exception { + // create a large document + test = newBenchmarkDocument(200000); + + XPath dot = new XPath(".", null, null, XPath.SELECT); + expect(pageContext.findAttribute("doc")).andStubReturn(test); + tag.setSelect("$doc/root/a"); + replay(pageContext); + long time = -System.nanoTime(); + XObject result = null; + if (tag.doStartTag() == IterationTag.EVAL_BODY_INCLUDE) { + do { + XPathContext context = tag.getContext(); + result = dot.execute(context, context.getCurrentNode(), null); + } while (tag.doAfterBody() == IterationTag.EVAL_BODY_AGAIN); + tag.doFinally(); + } + time += System.nanoTime(); + System.err.println("time = " + time / 1000000 + "ms."); + assertEquals("199999", result.str()); + } + + @Ignore("Takes < 1s to run") + @Test + public void xalanPerformance() throws Exception{ + Document doc = newBenchmarkDocument(200000); + expect(pageContext.findAttribute("doc")).andStubReturn(doc); + replay(pageContext); + + XPath select = new XPath("$doc/root/a", null, null, XPath.SELECT); + XPath dot = new XPath(".", null, null, XPath.SELECT); + XObject result = null; + + long time = -System.nanoTime(); + XPathContext context = new XPathContext(false); + context.setVarStack(new JSTLVariableStack(pageContext)); + int dtm = context.getDTMHandleFromNode(XmlUtil.newEmptyDocument()); + context.pushCurrentNodeAndExpression(dtm, dtm); + + // create an iterator over the returned nodes and push into the context + XObject nodes = select.execute(context, context.getCurrentNode(), null); + DTMIterator iterator = nodes.iter(); + context.pushContextNodeList(iterator); + while (iterator.getCurrentPos() < iterator.getLength()) { + int next = iterator.nextNode(); + context.pushCurrentNode(next); + iterator.getDTM(next).getNode(next); + + result = dot.execute(context, context.getCurrentNode(), null); + + context.popCurrentNode(); + } + time += System.nanoTime(); + System.err.println("time = " + time/1000000 + "ms."); + assertEquals("199999", result.str()); + } + + @Ignore("Takes > 20s to run") + @Test + public void cachedAPIPerformance() throws Exception{ + Document doc = newBenchmarkDocument(200000); + expect(pageContext.findAttribute("doc")).andStubReturn(doc); + replay(pageContext); + + Node result = null; + CachedXPathAPI api = new CachedXPathAPI(); + api.getXPathContext().setVarStack(new JSTLVariableStack(pageContext)); + + long time = -System.nanoTime(); + NodeIterator iterator = api.selectNodeIterator(XmlUtil.newEmptyDocument(), "$doc/root/a"); + Node node = iterator.nextNode(); + while (node != null) { + result = api.selectSingleNode(node, "."); + node = iterator.nextNode(); + } + time += System.nanoTime(); + System.err.println("time = " + time/1000000 + "ms."); + assertEquals("199999", result.getTextContent()); + } + + @Ignore("Takes > 20s to run") + @Test + public void xpathPerformance() throws Exception { + final Document doc = newBenchmarkDocument(200000); + expect(pageContext.findAttribute("doc")).andStubReturn(doc); + replay(pageContext); + + XPathVariableResolver resolver = new XPathVariableResolver() { + public Object resolveVariable(QName variableName) { + return doc; + } + }; + // XPathFactory factory = XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI, "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl", null); + XPathFactory factory = XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI); + System.out.println("factory.getClass() = " + factory.getClass()); + factory.setXPathVariableResolver(resolver); + XPathExpression select = factory.newXPath().compile("$doc/root/a"); + XPathExpression dot = factory.newXPath().compile("."); + Node result = null; + + long time = -System.nanoTime(); + NodeList nodes = (NodeList) select.evaluate(XmlUtil.newEmptyDocument(), XPathConstants.NODESET); + for (int i = 0; i < nodes.getLength(); i++) { + Node context = nodes.item(i); + result = (Node) dot.evaluate(context, XPathConstants.NODE); + } + time += System.nanoTime(); + System.err.println("time = " + time/1000000 + "ms."); + assertEquals("199999", result.getTextContent()); + } + + private static Document newBenchmarkDocument(int size) { + Document doc = XmlUtil.newEmptyDocument(); + Element root = doc.createElement("root"); + doc.appendChild(root); + for (int i = 0; i < size; i++) { + Element child = doc.createElement("a"); + child.setTextContent(Integer.toString(i)); + root.appendChild(child); + } + return doc; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java new file mode 100644 index 000000000..f1980c8db --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/JSTLVariableStackTest.java @@ -0,0 +1,164 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.PageContext; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.apache.taglibs.standard.util.XmlUtil; +import org.apache.xml.utils.QName; +import org.apache.xpath.XPathContext; +import org.apache.xpath.objects.XBoolean; +import org.apache.xpath.objects.XNodeSetForDOM; +import org.apache.xpath.objects.XNumber; +import org.apache.xpath.objects.XObjectFactory; +import org.apache.xpath.objects.XString; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + */ +public class JSTLVariableStackTest { + + private JSTLVariableStack stack; + private PageContext pageContext; + private XPathContext xpathContext; + private XString hello; + + @Before + public void setup() { + pageContext = createMock(PageContext.class); + xpathContext = new XPathContext(false); + hello = (XString) XObjectFactory.create("Hello"); + stack = new JSTLVariableStack(pageContext); + + } + + @Test + public void testNoPrefix() throws TransformerException { + expect(pageContext.findAttribute("foo")).andReturn("Hello"); + replay(pageContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName(null, "foo"))); + verify(pageContext); + } + + @Test + public void testParamPrefix() throws TransformerException { + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(pageContext.getRequest()).andReturn(request); + expect(request.getParameter("foo")).andReturn("Hello"); + replay(pageContext, request); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("param", "foo"))); + verify(pageContext, request); + } + + @Test + public void testHeaderPrefix() throws TransformerException { + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(pageContext.getRequest()).andReturn(request); + expect(request.getHeader("foo")).andReturn("Hello"); + replay(pageContext, request); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("header", "foo"))); + verify(pageContext, request); + } + + @Test + public void testCookiePrefix() throws TransformerException { + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(pageContext.getRequest()).andReturn(request); + Cookie[] cookies = new Cookie[]{new Cookie("foo", "Hello")}; + expect(request.getCookies()).andReturn(cookies); + replay(pageContext, request); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("cookie", "foo"))); + verify(pageContext, request); + } + + @Test + public void testInitParamPrefix() throws TransformerException { + ServletContext servletContext = createMock(ServletContext.class); + expect(pageContext.getServletContext()).andReturn(servletContext); + expect(servletContext.getInitParameter("foo")).andReturn("Hello"); + replay(pageContext, servletContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("initParam", "foo"))); + verify(pageContext, servletContext); + } + + @Test + public void testPagePrefix() throws TransformerException { + expect(pageContext.getAttribute("foo", PageContext.PAGE_SCOPE)).andReturn("Hello"); + replay(pageContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("pageScope", "foo"))); + verify(pageContext); + } + + @Test + public void testRequestPrefix() throws TransformerException { + expect(pageContext.getAttribute("foo", PageContext.REQUEST_SCOPE)).andReturn("Hello"); + replay(pageContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("requestScope", "foo"))); + verify(pageContext); + } + + @Test + public void testSessionPrefix() throws TransformerException { + expect(pageContext.getAttribute("foo", PageContext.SESSION_SCOPE)).andReturn("Hello"); + replay(pageContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("sessionScope", "foo"))); + verify(pageContext); + } + + @Test + public void testApplicationPrefix() throws TransformerException { + expect(pageContext.getAttribute("foo", PageContext.APPLICATION_SCOPE)).andReturn("Hello"); + replay(pageContext); + Assert.assertEquals(hello, stack.getVariableOrParam(xpathContext, new QName("applicationScope", "foo"))); + verify(pageContext); + } + + @Test(expected = TransformerException.class) + public void testValueNotFound() throws TransformerException { + expect(pageContext.findAttribute("foo")).andReturn(null); + replay(pageContext); + stack.getVariableOrParam(xpathContext, new QName(null, "foo")); + Assert.fail(); + } + + @Test + public void verifyJavaToXPathTypeMapping() throws ParserConfigurationException { + Assert.assertTrue(XObjectFactory.create(Boolean.TRUE, xpathContext) instanceof XBoolean); + Assert.assertTrue(XObjectFactory.create(1234, xpathContext) instanceof XNumber); + Assert.assertTrue(XObjectFactory.create("Hello", xpathContext) instanceof XString); + + Document d = XmlUtil.newEmptyDocument(); + Element root = d.createElement("root"); + XNodeSetForDOM xo = (XNodeSetForDOM) XObjectFactory.create(root, xpathContext); + Assert.assertEquals(root, xo.object()); + + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TransformSupportTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TransformSupportTest.java new file mode 100644 index 000000000..aeee99b4c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/TransformSupportTest.java @@ -0,0 +1,58 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.JspException; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.fail; + +/** + */ +public class TransformSupportTest { + private TransformSupport tag; + + @Before + public void setup() { + tag = new TransformSupport() { + }; + } + + @Test + public void testNullTransform() { + tag.xslt = null; + try { + tag.doStartTag(); + fail(); + } catch (JspException e) { + // expected + } + } + + @Test + public void testEmptyTransform() { + tag.xslt = ""; + try { + tag.doStartTag(); + fail(); + } catch (JspException e) { + // expected + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java new file mode 100644 index 000000000..9e14afb5e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/common/xml/XalanUtilTest.java @@ -0,0 +1,72 @@ +/* + * 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.taglibs.standard.tag.common.xml; + +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.xpath.XPath; +import org.apache.xpath.XPathContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + */ +public class XalanUtilTest { + + private Tag tag; + private PageContext pageContext; + + @Before + public void setup() { + tag = createMock(Tag.class); + pageContext = createMock(PageContext.class); + } + + @Test + public void testEmptyContext() { + expect(tag.getParent()).andReturn(null); + replay(pageContext, tag); + XPathContext context = XalanUtil.getContext(tag, pageContext); + // verify current node is an empty Document + int node = context.getCurrentNode(); + Node doc = context.getDTM(node).getNode(node); + Assert.assertTrue(doc instanceof Document); + Assert.assertNull(doc.getFirstChild()); + verify(pageContext, tag); + } + + @Test + public void testContextSupportsMultipleVariables() throws Exception { + expect(tag.getParent()).andReturn(null); + expect(pageContext.findAttribute("a")).andReturn("Hello"); + expect(pageContext.getAttribute("b", PageContext.REQUEST_SCOPE)).andReturn("World"); + replay(pageContext, tag); + XPathContext context = XalanUtil.getContext(tag, pageContext); + XPath xpath = new XPath("concat($a, ' ', $requestScope:b)", null, null, XPath.SELECT); + Assert.assertEquals("Hello World", xpath.execute(context, context.getCurrentNode(), null).str()); + verify(pageContext, tag); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/rt/core/OutTagTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/rt/core/OutTagTest.java new file mode 100644 index 000000000..62f90dd5c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/tag/rt/core/OutTagTest.java @@ -0,0 +1,34 @@ +/* + * 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.taglibs.standard.tag.rt.core; + +import org.junit.Assert; +import org.junit.Test; + +/** + */ +public class OutTagTest { + + private OutTag tag = new OutTag(); + + @Test + public void testDefaults() { + Assert.assertNull(tag.evalValue()); + Assert.assertNull(tag.evalDefault()); + Assert.assertTrue(tag.evalEscapeXml()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/EscapeXMLTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/EscapeXMLTest.java new file mode 100644 index 000000000..d51b8959c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/EscapeXMLTest.java @@ -0,0 +1,221 @@ +/* + * 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.taglibs.standard.util; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import jakarta.servlet.jsp.JspWriter; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.apache.taglibs.standard.util.EscapeXML.emit; +import static org.apache.taglibs.standard.util.EscapeXML.escape; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + */ +public class EscapeXMLTest { + private JspWriter writer; + + @Before + public void setup() { + writer = createMock(JspWriter.class); + } + + @Test + public void testEscapeString() { + Assert.assertEquals("Hello", escape("Hello")); + Assert.assertEquals("<Hello msg="world"/>", escape("")); + Assert.assertEquals("<Hello msg='world'/>", escape("")); + Assert.assertEquals("cats & dogs", escape("cats & dogs")); + } + + @Test + public void testEmitInteger() throws IOException { + writer.write("1234"); + replay(writer); + emit(1234, false, writer); + verify(writer); + } + + @Test + public void testEmitNull() throws IOException { + writer.write("null"); + replay(writer); + emit((Object) null, false, writer); + verify(writer); + } + + @Test + public void testEmitStringEscaped() throws IOException { + String s = "cats & dogs"; + writer.write(s, 0, 5); + writer.write("&"); + writer.write(s, 6, 5); + replay(writer); + emit(s, true, writer); + verify(writer); + } + + @Test + public void testEmitStringUnescaped() throws IOException { + String s = "cats & dogs"; + writer.write(s); + replay(writer); + emit(s, false, writer); + verify(writer); + } + + @Test + public void testEmitEntireString() throws IOException { + writer.write("Hello World", 0, 11); + replay(writer); + emit("Hello World", writer); + verify(writer); + } + + @Test + public void testEmitEscapedStringMiddle() throws IOException { + String s = "cats & dogs"; + writer.write(s, 0, 5); + writer.write("&"); + writer.write(s, 6, 5); + replay(writer); + emit(s, writer); + verify(writer); + } + + @Test + public void testEmitEscapedStringBeginning() throws IOException { + String s = "& dogs"; + writer.write("&"); + writer.write(s, 1, 5); + replay(writer); + emit(s, writer); + verify(writer); + } + + @Test + public void testEmitEscapedStringEnd() throws IOException { + String s = "cats &"; + writer.write(s, 0, 5); + writer.write("&"); + replay(writer); + emit(s, writer); + verify(writer); + } + + @Test + public void testEmitEscapedStringAdjacent() throws IOException { + String s = "'cats'&\"dogs\""; + writer.write("'"); + writer.write(s, 1, 4); + writer.write("'"); + writer.write("&"); + writer.write("""); + writer.write(s, 8, 4); + writer.write("""); + replay(writer); + emit(s, writer); + verify(writer); + } + + @Test + public void testEmitEmptyString() throws IOException { + replay(writer); + emit("", writer); + verify(writer); + } + + @Test + public void testEmitChars() throws IOException { + char[] chars = "Hello World".toCharArray(); + writer.write(chars, 2, 5); + replay(writer); + emit(chars, 2, 5, writer); + verify(writer); + } + + @Test + public void testEmitEscapedChars() throws IOException { + char[] chars = "'cats'&\"dogs\"".toCharArray(); + writer.write("'"); + writer.write(chars, 1, 4); + writer.write("'"); + writer.write("&"); + writer.write("""); + writer.write(chars, 8, 4); + writer.write("""); + replay(writer); + emit(chars, 0, chars.length, writer); + verify(writer); + } + + @Test + public void testEmitReaderUnescaped() throws IOException { + Reader reader = new StringReader("'cats'&\"dogs\""); + expect(writer.getBufferSize()).andStubReturn(0); + writer.write(isA(char[].class), eq(0), eq(13)); + replay(writer); + emit(reader, false, writer); + verify(writer); + } + + @Test + public void testEmitReaderUnbuffered() throws IOException { + Reader reader = new StringReader("'cats'&\"dogs\""); + expect(writer.getBufferSize()).andStubReturn(0); + writer.write("'"); + writer.write(isA(char[].class), eq(1), eq(4)); + writer.write("'"); + writer.write("&"); + writer.write("""); + writer.write(isA(char[].class), eq(8), eq(4)); + writer.write("""); + replay(writer); + emit(reader, true, writer); + verify(writer); + } + + @Test + public void testEmitReaderBufferWrap() throws IOException { + Reader reader = new StringReader("'cats'&\"dogs\""); + expect(writer.getBufferSize()).andStubReturn(2); + writer.write("'"); + writer.write(isA(char[].class), eq(1), eq(1)); // 'c' + writer.write(isA(char[].class), eq(0), eq(2)); // 'at' + writer.write(isA(char[].class), eq(0), eq(1)); // 's' + writer.write("'"); + writer.write("&"); + writer.write("""); + writer.write(isA(char[].class), eq(0), eq(2)); // 'do' + writer.write(isA(char[].class), eq(0), eq(2)); // 'gs' + writer.write("""); + replay(writer); + emit(reader, true, writer); + verify(writer); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/XmlUtilTest.java b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/XmlUtilTest.java new file mode 100644 index 000000000..30cacd982 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/java/org/apache/taglibs/standard/util/XmlUtilTest.java @@ -0,0 +1,52 @@ +/* + * 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.taglibs.standard.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class XmlUtilTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void anyProtocolAllowedForAll() { + XmlUtil.checkProtocol("all", "http://example.com/foo.xml"); + } + + @Test + public void standardSchemesAllowed() { + XmlUtil.checkProtocol("http,jar:file,file", "http://example.com/foo.xml"); + XmlUtil.checkProtocol("http,jar:file,file", "file:///tmp/file"); + XmlUtil.checkProtocol("http,jar:file,file", "jar:file:///tmp/file.jar!/entry.xml"); + } + + @Test + public void notAllowedForEmptyString() { + thrown.expect(SecurityException.class); + XmlUtil.checkProtocol("", "http://example.com/foo.xml"); + } + + @Test + public void notAllowed() { + thrown.expect(SecurityException.class); + XmlUtil.checkProtocol("http,file", "https://example.com/foo.xml"); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml b/Java-base/tomcat-taglibs-standard/src/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml new file mode 100644 index 000000000..e56cbf5c8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/impl/src/test/resources/org/apache/taglibs/standard/tag/common/xml/test.xml @@ -0,0 +1,25 @@ + + + + + one + two + three + + Hello + \ No newline at end of file diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/pom.xml b/Java-base/tomcat-taglibs-standard/src/jstlel/pom.xml new file mode 100644 index 000000000..7001f3905 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/pom.xml @@ -0,0 +1,148 @@ + + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-standard-jstlel + bundle + + Apache Standard Taglib 1.0 EL Support + + + Support JSTL 1.0 tags using the original EL implementation. + + + + + org.apache.taglibs + taglibs-standard-spec + + + org.apache.taglibs + taglibs-standard-impl + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + provided + + + xalan + xalan + provided + true + + + + junit + junit + test + + + org.easymock + easymock + test + + + + + + + org.apache.felix + maven-bundle-plugin + + true + + *;version="1.2" + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../build-tools/src/main/resources/taglibs/checkstyle.xml + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + ${maven.compiler.target} + + + + + pmd + cpd + + + + + + org.codehaus.mojo + taglist-maven-plugin + 2.4 + + + org.codehaus.mojo + javancss-maven-plugin + 2.0 + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + Normal + Default + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/AndOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/AndOperator.java new file mode 100644 index 000000000..59fa1fade --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/AndOperator.java @@ -0,0 +1,96 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the and operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class AndOperator + extends BinaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final AndOperator SINGLETON = + new AndOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public AndOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "and"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + // Coerce the values to booleans + boolean left = + Coercions.coerceToBoolean(pLeft, pLogger).booleanValue(); + boolean right = + Coercions.coerceToBoolean(pRight, pLogger).booleanValue(); + + return PrimitiveObjects.getBoolean(left && right); + } + + //------------------------------------- + + /** + * Returns true if evaluation is necessary given the specified Left + * value. The And/OrOperators make use of this + */ + public boolean shouldEvaluate(Object pLeft) { + return + (pLeft instanceof Boolean) && + ((Boolean) pLeft).booleanValue() == true; + } + + //------------------------------------- + + /** + * Returns true if the operator expects its arguments to be coerced + * to Booleans. The And/Or operators set this to true. + */ + public boolean shouldCoerceToBoolean() { + return true; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArithmeticOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArithmeticOperator.java new file mode 100644 index 000000000..df76ab139 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArithmeticOperator.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This is the superclass for all binary arithmetic operators + * + * @author Nathan Abramson - Art Technology Group + */ + +public abstract class ArithmeticOperator + extends BinaryOperator { + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + return Coercions.applyArithmeticOperator(pLeft, pRight, this, pLogger); + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public abstract double apply(double pLeft, + double pRight, + Logger pLogger); + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public abstract long apply(long pLeft, + long pRight, + Logger pLogger); + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArraySuffix.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArraySuffix.java new file mode 100644 index 000000000..95e73494e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ArraySuffix.java @@ -0,0 +1,307 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; + +/** + *

Represents an operator that obtains a Map entry, an indexed + * value, a property value, or an indexed property value of an object. + * The following are the rules for evaluating this operator: + *

+ * Evaluating a[b] (assuming a.b == a["b"])
+ *   a is null
+ *     return null
+ *   b is null
+ *     return null
+ *   a is Map
+ *     !a.containsKey (b)
+ *       return null
+ *     a.get(b) == null
+ *       return null
+ *     otherwise
+ *       return a.get(b)
+ *   a is List or array
+ *     coerce b to int (using coercion rules)
+ *     coercion couldn't be performed
+ *       error
+ *     a.get(b) or Array.get(a, b) throws ArrayIndexOutOfBoundsException or IndexOutOfBoundsException
+ *       return null
+ *     a.get(b) or Array.get(a, b) throws other exception
+ *       error
+ *     return a.get(b) or Array.get(a, b)
+ *
+ *   coerce b to String
+ *   b is a readable property of a
+ *     getter throws an exception
+ *       error
+ *     otherwise
+ *       return result of getter call
+ *
+ *   otherwise
+ *     error
+ * 
+ * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class ArraySuffix + extends ValueSuffix { + //------------------------------------- + // Constants + //------------------------------------- + + // Zero-argument array + static Object[] sNoArgs = new Object[0]; + + //------------------------------------- + // Properties + //------------------------------------- + // property index + + Expression mIndex; + + public Expression getIndex() { + return mIndex; + } + + public void setIndex(Expression pIndex) { + mIndex = pIndex; + } + + //------------------------------------- + + /** + * Constructor + */ + public ArraySuffix(Expression pIndex) { + mIndex = pIndex; + } + + //------------------------------------- + + /** + * Gets the value of the index + */ + Object evaluateIndex(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + return mIndex.evaluate(pContext, pResolver, functions, defaultPrefix, + pLogger); + } + + //------------------------------------- + + /** + * Returns the operator symbol + */ + String getOperatorSymbol() { + return "[]"; + } + + //------------------------------------- + // ValueSuffix methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return "[" + mIndex.getExpressionString() + "]"; + } + + //------------------------------------- + + /** + * Evaluates the expression in the given context, operating on the + * given value. + */ + public Object evaluate(Object pValue, + Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + Object indexVal; + String indexStr; + BeanInfoProperty property; + BeanInfoIndexedProperty ixproperty; + + // Check for null value + if (pValue == null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.CANT_GET_INDEXED_VALUE_OF_NULL, + getOperatorSymbol()); + } + return null; + } + + // Evaluate the index + else if ((indexVal = evaluateIndex(pContext, pResolver, + functions, defaultPrefix, pLogger)) == + null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.CANT_GET_NULL_INDEX, + getOperatorSymbol()); + } + return null; + } + + // See if it's a Map + else if (pValue instanceof Map) { + Map val = (Map) pValue; + return val.get(indexVal); + } + + // See if it's a List or array + else if (pValue instanceof List || + pValue.getClass().isArray()) { + Integer indexObj = Coercions.coerceToInteger(indexVal, pLogger); + if (indexObj == null) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.BAD_INDEX_VALUE, + getOperatorSymbol(), + indexVal.getClass().getName()); + } + return null; + } else if (pValue instanceof List) { + try { + return ((List) pValue).get(indexObj.intValue()); + } + catch (ArrayIndexOutOfBoundsException exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.EXCEPTION_ACCESSING_LIST, + exc, + indexObj); + } + return null; + } + catch (IndexOutOfBoundsException exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.EXCEPTION_ACCESSING_LIST, + exc, + indexObj); + } + return null; + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.EXCEPTION_ACCESSING_LIST, + exc, + indexObj); + } + return null; + } + } else { + try { + return Array.get(pValue, indexObj.intValue()); + } + catch (ArrayIndexOutOfBoundsException exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.EXCEPTION_ACCESSING_ARRAY, + exc, + indexObj); + } + return null; + } + catch (IndexOutOfBoundsException exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.EXCEPTION_ACCESSING_ARRAY, + exc, + indexObj); + } + return null; + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.EXCEPTION_ACCESSING_ARRAY, + exc, + indexObj); + } + return null; + } + } + } + + // Coerce to a String for property access + + else if ((indexStr = Coercions.coerceToString(indexVal, pLogger)) == + null) { + return null; + } + + // Look for a JavaBean property + else if ((property = BeanInfoManager.getBeanInfoProperty + (pValue.getClass(), + indexStr, + pLogger)) != null && + property.getReadMethod() != null) { + try { + return property.getReadMethod().invoke(pValue, sNoArgs); + } + catch (InvocationTargetException exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ERROR_GETTING_PROPERTY, + exc.getTargetException(), + indexStr, + pValue.getClass().getName()); + } + return null; + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ERROR_GETTING_PROPERTY, + exc, + indexStr, + pValue.getClass().getName()); + } + return null; + } + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.CANT_FIND_INDEX, + indexVal, + pValue.getClass().getName(), + getOperatorSymbol()); + } + return null; + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoIndexedProperty.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoIndexedProperty.java new file mode 100644 index 000000000..2391b59d3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoIndexedProperty.java @@ -0,0 +1,87 @@ +/* + * 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.taglibs.standard.lang.jstl; + + +import java.beans.IndexedPropertyDescriptor; +import java.lang.reflect.Method; + + +/** + *

This contains the information for one indexed property in a + *

BeanInfo - IndexedPropertyDescriptor, read method, and write + * method. This class is necessary because the read/write methods in + * the IndexedPropertyDescriptor may not be accessible if the bean + * given to the introspector is not a public class. In this case, a + * publicly accessible version of the method must be found by + * searching for a public superclass/interface that declares the + * method (this searching is done by the BeanInfoManager). + * + * @author Nathan Abramson - Art Technology Group + */ +public class BeanInfoIndexedProperty { + + //------------------------------------- + // Properties + + //------------------------------------- + // property readMethod + + Method mReadMethod; + + public Method getReadMethod() { + return mReadMethod; + } + + //------------------------------------- + // property writeMethod + + Method mWriteMethod; + + public Method getWriteMethod() { + return mWriteMethod; + } + + //------------------------------------- + // property propertyDescriptor + + IndexedPropertyDescriptor mIndexedPropertyDescriptor; + + public IndexedPropertyDescriptor getIndexedPropertyDescriptor() { + return mIndexedPropertyDescriptor; + } + + //------------------------------------- + + /** + * Constructor + */ + public BeanInfoIndexedProperty + (Method pReadMethod, + Method pWriteMethod, + IndexedPropertyDescriptor pIndexedPropertyDescriptor) + { + mReadMethod = pReadMethod; + mWriteMethod = pWriteMethod; + mIndexedPropertyDescriptor = pIndexedPropertyDescriptor; + } + + //------------------------------------- +} + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoManager.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoManager.java new file mode 100644 index 000000000..0dda71204 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoManager.java @@ -0,0 +1,369 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.beans.BeanInfo; +import java.beans.EventSetDescriptor; +import java.beans.IndexedPropertyDescriptor; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +/** + *

Manages the BeanInfo for one class - contains the BeanInfo, and + * also a mapping from property name to BeanInfoProperty. There are + * also static methods for accessing the BeanInfoManager for a class - + * those mappings are cached permanently so that once the + * BeanInfoManager is calculated, it doesn't have to be calculated + * again. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class BeanInfoManager { + //------------------------------------- + // Properties + //------------------------------------- + // property beanClass + + Class mBeanClass; + + public Class getBeanClass() { + return mBeanClass; + } + + //------------------------------------- + // Member variables + //------------------------------------- + + // The BeanInfo + BeanInfo mBeanInfo; + + // Mapping from property name to BeanInfoProperty + Map mPropertyByName; + + // Mapping from property name to BeanInfoIndexedProperty + Map mIndexedPropertyByName; + + // Mapping from event set name to event set descriptor + Map mEventSetByName; + + // Flag if this is initialized + boolean mInitialized; + + // The global mapping from class to BeanInfoManager + static Map mBeanInfoManagerByClass = new HashMap(); + + //------------------------------------- + + /** + * Constructor + */ + BeanInfoManager(Class pBeanClass) { + mBeanClass = pBeanClass; + } + + //------------------------------------- + + /** + * Returns the BeanInfoManager for the specified class + */ + public static BeanInfoManager getBeanInfoManager(Class pClass) { + BeanInfoManager ret = (BeanInfoManager) + mBeanInfoManagerByClass.get(pClass); + if (ret == null) { + ret = createBeanInfoManager(pClass); + } + return ret; + } + + //------------------------------------- + + /** + * Creates and registers the BeanInfoManager for the given class if + * it isn't already registered. + */ + static synchronized BeanInfoManager createBeanInfoManager(Class pClass) { + // Because this method is synchronized statically, the + // BeanInfoManager is not initialized at this time (otherwise it + // could end up being a bottleneck for the entire system). It is + // put into the map in an uninitialized state. The first time + // someone tries to use it, it will be initialized (with proper + // synchronizations in place to make sure it is only initialized + // once). + + BeanInfoManager ret = (BeanInfoManager) + mBeanInfoManagerByClass.get(pClass); + if (ret == null) { + ret = new BeanInfoManager(pClass); + mBeanInfoManagerByClass.put(pClass, ret); + } + return ret; + } + + //------------------------------------- + + /** + * Returns the BeanInfoProperty for the specified property in the + * given class, or null if not found. + */ + public static BeanInfoProperty getBeanInfoProperty + (Class pClass, + String pPropertyName, + Logger pLogger) + throws ELException { + return getBeanInfoManager(pClass).getProperty(pPropertyName, pLogger); + } + + //------------------------------------- + + /** + * Returns the BeanInfoIndexedProperty for the specified property in + * the given class, or null if not found. + */ + public static BeanInfoIndexedProperty getBeanInfoIndexedProperty + (Class pClass, + String pIndexedPropertyName, + Logger pLogger) + throws ELException { + return getBeanInfoManager + (pClass).getIndexedProperty(pIndexedPropertyName, pLogger); + } + + //------------------------------------- + + /** + * Makes sure that this class has been initialized, and synchronizes + * the initialization if it's required. + */ + void checkInitialized(Logger pLogger) + throws ELException { + if (!mInitialized) { + synchronized (this) { + if (!mInitialized) { + initialize(pLogger); + mInitialized = true; + } + } + } + } + + //------------------------------------- + + /** + * Initializes by mapping property names to BeanInfoProperties + */ + void initialize(Logger pLogger) + throws ELException { + try { + mBeanInfo = Introspector.getBeanInfo(mBeanClass); + + mPropertyByName = new HashMap(); + mIndexedPropertyByName = new HashMap(); + PropertyDescriptor[] pds = mBeanInfo.getPropertyDescriptors(); + for (int i = 0; pds != null && i < pds.length; i++) { + // Treat as both an indexed property and a normal property + PropertyDescriptor pd = pds[i]; + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd; + Method readMethod = getPublicMethod(ipd.getIndexedReadMethod()); + Method writeMethod = getPublicMethod(ipd.getIndexedWriteMethod()); + BeanInfoIndexedProperty property = new BeanInfoIndexedProperty + (readMethod, + writeMethod, + ipd); + + mIndexedPropertyByName.put(ipd.getName(), property); + } + + Method readMethod = getPublicMethod(pd.getReadMethod()); + Method writeMethod = getPublicMethod(pd.getWriteMethod()); + BeanInfoProperty property = new BeanInfoProperty + (readMethod, + writeMethod, + pd); + + mPropertyByName.put(pd.getName(), property); + } + + mEventSetByName = new HashMap(); + EventSetDescriptor[] esds = mBeanInfo.getEventSetDescriptors(); + for (int i = 0; esds != null && i < esds.length; i++) { + EventSetDescriptor esd = esds[i]; + mEventSetByName.put(esd.getName(), esd); + } + } + catch (IntrospectionException exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.EXCEPTION_GETTING_BEANINFO, + exc, + mBeanClass.getName()); + } + } + } + + //------------------------------------- + + /** + * Returns the BeanInfo for the class + */ + BeanInfo getBeanInfo(Logger pLogger) + throws ELException { + checkInitialized(pLogger); + return mBeanInfo; + } + + //------------------------------------- + + /** + * Returns the BeanInfoProperty for the given property name, or null + * if not found. + */ + public BeanInfoProperty getProperty(String pPropertyName, + Logger pLogger) + throws ELException { + checkInitialized(pLogger); + return (BeanInfoProperty) mPropertyByName.get(pPropertyName); + } + + //------------------------------------- + + /** + * Returns the BeanInfoIndexedProperty for the given property name, + * or null if not found. + */ + public BeanInfoIndexedProperty getIndexedProperty + (String pIndexedPropertyName, + Logger pLogger) + throws ELException { + checkInitialized(pLogger); + return (BeanInfoIndexedProperty) + mIndexedPropertyByName.get(pIndexedPropertyName); + } + + //------------------------------------- + + /** + * Returns the EventSetDescriptor for the given event set name, or + * null if not found. + */ + public EventSetDescriptor getEventSet(String pEventSetName, + Logger pLogger) + throws ELException { + checkInitialized(pLogger); + return (EventSetDescriptor) mEventSetByName.get(pEventSetName); + } + + //------------------------------------- + // Finding the public version of a method - if a PropertyDescriptor + // is obtained for a non-public class that implements a public + // interface, the read/write methods will be for the class, and + // therefore inaccessible. To correct this, a version of the same + // method must be found in a superclass or interface. + //------------------------------------- + + /** + * Returns a publicly-accessible version of the given method, by + * searching for a public declaring class. + */ + static Method getPublicMethod(Method pMethod) { + if (pMethod == null) { + return null; + } + + // See if the method is already available from a public class + Class cl = pMethod.getDeclaringClass(); + if (Modifier.isPublic(cl.getModifiers())) { + return pMethod; + } + + // Otherwise, try to find a public class that declares the method + Method ret = getPublicMethod(cl, pMethod); + if (ret != null) { + return ret; + } else { + return pMethod; + } + } + + //------------------------------------- + + /** + * If the given class is public and has a Method that declares the + * same name and arguments as the given method, then that method is + * returned. Otherwise the superclass and interfaces are searched + * recursively. + */ + static Method getPublicMethod(Class pClass, + Method pMethod) { + // See if this is a public class declaring the method + if (Modifier.isPublic(pClass.getModifiers())) { + try { + Method m; + try { + m = pClass.getDeclaredMethod(pMethod.getName(), + pMethod.getParameterTypes()); + } catch (java.security.AccessControlException ex) { + // kludge to accommodate J2EE RI's default settings + // TODO: see if we can simply replace + // getDeclaredMethod() with getMethod() ...? + m = pClass.getMethod(pMethod.getName(), + pMethod.getParameterTypes()); + } + if (Modifier.isPublic(m.getModifiers())) { + return m; + } + } + catch (NoSuchMethodException exc) { + } + } + + // Search the interfaces + { + Class[] interfaces = pClass.getInterfaces(); + if (interfaces != null) { + for (int i = 0; i < interfaces.length; i++) { + Method m = getPublicMethod(interfaces[i], pMethod); + if (m != null) { + return m; + } + } + } + } + + // Search the superclass + { + Class superclass = pClass.getSuperclass(); + if (superclass != null) { + Method m = getPublicMethod(superclass, pMethod); + if (m != null) { + return m; + } + } + } + + return null; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoProperty.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoProperty.java new file mode 100644 index 000000000..563b20e2d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BeanInfoProperty.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 org.apache.taglibs.standard.lang.jstl; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Method; + +/** + *

This contains the information for one property in a BeanInfo - + * PropertyDescriptor, read method, and write method. This class is + * necessary because the read/write methods in the PropertyDescriptor + * may not be accessible if the bean given to the introspector is not + * a public class. In this case, a publicly accessible version of the + * method must be found by searching for a public superclass/interface + * that declares the method (this searching is done by the + * BeanInfoManager). + * + * @author Nathan Abramson - Art Technology Group + */ + +public class BeanInfoProperty { + //------------------------------------- + // Properties + //------------------------------------- + // property readMethod + + Method mReadMethod; + + public Method getReadMethod() { + return mReadMethod; + } + + //------------------------------------- + // property writeMethod + + Method mWriteMethod; + + public Method getWriteMethod() { + return mWriteMethod; + } + + //------------------------------------- + // property propertyDescriptor + + PropertyDescriptor mPropertyDescriptor; + + public PropertyDescriptor getPropertyDescriptor() { + return mPropertyDescriptor; + } + + //------------------------------------- + + /** + * Constructor + */ + public BeanInfoProperty(Method pReadMethod, + Method pWriteMethod, + PropertyDescriptor pPropertyDescriptor) { + mReadMethod = pReadMethod; + mWriteMethod = pWriteMethod; + mPropertyDescriptor = pPropertyDescriptor; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperator.java new file mode 100644 index 000000000..d172fff34 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperator.java @@ -0,0 +1,76 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This is the superclass for all binary operators + * + * @author Nathan Abramson - Art Technology Group + */ + +public abstract class BinaryOperator { + //------------------------------------- + + /** + * Constructor + */ + public BinaryOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public abstract String getOperatorSymbol(); + + //------------------------------------- + + /** + * Applies the operator to the given pair of values + */ + public abstract Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException; + + //------------------------------------- + + /** + * Returns true if evaluation is necessary given the specified Left + * value. The And/OrOperators make use of this + */ + public boolean shouldEvaluate(Object pLeft) { + return true; + } + + //------------------------------------- + + /** + * Returns true if the operator expects its arguments to be coerced + * to Booleans. The And/Or operators set this to true. + */ + public boolean shouldCoerceToBoolean() { + return false; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperatorExpression.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperatorExpression.java new file mode 100644 index 000000000..f8fa55109 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BinaryOperatorExpression.java @@ -0,0 +1,145 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.List; +import java.util.Map; + +/** + *

An expression representing a binary operator on a value + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class BinaryOperatorExpression + extends Expression { + //------------------------------------- + // Properties + //------------------------------------- + // property expression + + Expression mExpression; + + public Expression getExpression() { + return mExpression; + } + + public void setExpression(Expression pExpression) { + mExpression = pExpression; + } + + //------------------------------------- + // property operators + + List mOperators; + + public List getOperators() { + return mOperators; + } + + public void setOperators(List pOperators) { + mOperators = pOperators; + } + + //------------------------------------- + // property expressions + + List mExpressions; + + public List getExpressions() { + return mExpressions; + } + + public void setExpressions(List pExpressions) { + mExpressions = pExpressions; + } + + //------------------------------------- + + /** + * Constructor + */ + public BinaryOperatorExpression(Expression pExpression, + List pOperators, + List pExpressions) { + mExpression = pExpression; + mOperators = pOperators; + mExpressions = pExpressions; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + StringBuilder buf = new StringBuilder(); + buf.append("("); + buf.append(mExpression.getExpressionString()); + for (int i = 0; i < mOperators.size(); i++) { + BinaryOperator operator = (BinaryOperator) mOperators.get(i); + Expression expression = (Expression) mExpressions.get(i); + buf.append(" "); + buf.append(operator.getOperatorSymbol()); + buf.append(" "); + buf.append(expression.getExpressionString()); + } + buf.append(")"); + + return buf.toString(); + } + + //------------------------------------- + + /** + * Evaluates to the literal value + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + Object value = mExpression.evaluate(pContext, pResolver, functions, + defaultPrefix, pLogger); + for (int i = 0; i < mOperators.size(); i++) { + BinaryOperator operator = (BinaryOperator) mOperators.get(i); + + // For the And/Or operators, we need to coerce to a boolean + // before testing if we shouldEvaluate + if (operator.shouldCoerceToBoolean()) { + value = Coercions.coerceToBoolean(value, pLogger); + } + + if (operator.shouldEvaluate(value)) { + Expression expression = (Expression) mExpressions.get(i); + Object nextValue = expression.evaluate(pContext, pResolver, + functions, defaultPrefix, + pLogger); + + value = operator.apply(value, nextValue, pContext, pLogger); + } + } + return value; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BooleanLiteral.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BooleanLiteral.java new file mode 100644 index 000000000..b3fccda6e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/BooleanLiteral.java @@ -0,0 +1,68 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

An expression representing a boolean literal value + * + * @author Nathan Abramson - Art Technology Group + */ + +public class BooleanLiteral + extends Literal { + //------------------------------------- + // Member variables + //------------------------------------- + + public static final BooleanLiteral TRUE = new BooleanLiteral("true"); + public static final BooleanLiteral FALSE = new BooleanLiteral("false"); + + //------------------------------------- + + /** + * Constructor + */ + public BooleanLiteral(String pToken) { + super(getValueFromToken(pToken)); + } + + //------------------------------------- + + /** + * Parses the given token into the literal value + */ + static Object getValueFromToken(String pToken) { + return + ("true".equals(pToken)) ? + Boolean.TRUE : + Boolean.FALSE; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return (getValue() == Boolean.TRUE) ? "true" : "false"; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Coercions.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Coercions.java new file mode 100644 index 000000000..cc96a7027 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Coercions.java @@ -0,0 +1,918 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; + +/** + *

This class contains the logic for coercing data types before + * operators are applied to them. + *

The following is the list of rules applied for various type + * conversions. + *

+ * Applying arithmetic operator
+ *   Binary operator - A {+,-,*} B
+ *     if A and B are null
+ *       return 0
+ *     if A or B is Float, Double, or String containing ".", "e", or "E"
+ *       coerce both A and B to Double
+ *       apply operator
+ *     otherwise
+ *       coerce both A and B to Long
+ *       apply operator
+ *     if operator results in exception (such as divide by 0), error
+ *
+ *   Binary operator - A {/,div} B
+ *     if A and B are null
+ *       return 0
+ *     otherwise
+ *       coerce both A and B to Double
+ *       apply operator
+ *     if operator results in exception (such as divide by 0), error
+ *
+ *   Binary operator - A {%,mod} B
+ *     if A and B are null
+ *       return 0
+ *     if A or B is Float, Double, or String containing ".", "e" or "E"
+ *       coerce both to Double
+ *       apply operator
+ *     otherwise
+ *       coerce both A and B to Long
+ *       apply operator
+ *     if operator results in exception (such as divide by 0), error
+ *
+ *   Unary minus operator - -A
+ *     if A is null
+ *       return 0
+ *     if A is String
+ *       if A contains ".", "e", or "E"
+ *         coerce to Double, apply operator
+ *       otherwise
+ *         coerce to a Long and apply operator
+ *     if A is Byte,Short,Integer,Long,Float,Double
+ *       retain type, apply operator
+ *     if operator results in exception, error
+ *     otherwise
+ *       error
+ *
+ * Applying "empty" operator - empty A
+ *   if A is null
+ *     return true
+ *   if A is zero-length String
+ *     return true
+ *   if A is zero-length array
+ *     return true
+ *   if A is List and ((List) A).isEmpty()
+ *     return true
+ *   if A is Map and ((Map) A).isEmpty()
+ *     return true
+ *   otherwise
+ *     return false
+ *
+ * Applying logical operators
+ *   Binary operator - A {and,or} B
+ *     coerce both A and B to Boolean, apply operator
+ *   NOTE - operator stops as soon as expression can be determined, i.e.,
+ *     A and B and C and D - if B is false, then only A and B is evaluated
+ *   Unary not operator - not A
+ *     coerce A to Boolean, apply operator
+ *
+ * Applying relational operator
+ *   A {<,>,<=,>=,lt,gt,lte,gte} B
+ *     if A==B
+ *       if operator is >= or <=
+ *         return true
+ *       otherwise
+ *         return false
+ *     if A or B is null
+ *       return false
+ *     if A or B is Float or Double
+ *       coerce both A and B to Double
+ *       apply operator
+ *     if A or B is Byte,Short,Character,Integer,Long
+ *       coerce both A and B to Long
+ *       apply operator
+ *     if A or B is String
+ *       coerce both A and B to String, compare lexically
+ *     if A is Comparable
+ *       if A.compareTo (B) throws exception
+ *         error
+ *       otherwise
+ *         use result of A.compareTo(B)
+ *     if B is Comparable
+ *       if B.compareTo (A) throws exception
+ *         error
+ *       otherwise
+ *         use result of B.compareTo(A)
+ *     otherwise
+ *       error
+ *
+ * Applying equality operator
+ *   A {==,!=} B
+ *     if A==B
+ *       apply operator
+ *     if A or B is null
+ *       return false for ==, true for !=
+ *     if A or B is Float or Double
+ *       coerce both A and B to Double
+ *       apply operator
+ *     if A or B is Byte,Short,Character,Integer,Long
+ *       coerce both A and B to Long
+ *       apply operator
+ *     if A or B is Boolean
+ *       coerce both A and B to Boolean
+ *       apply operator
+ *     if A or B is String
+ *       coerce both A and B to String, compare lexically
+ *     otherwise
+ *       if an error occurs while calling A.equals(B)
+ *         error
+ *       apply operator to result of A.equals(B)
+ *
+ * coercions
+ *
+ *   coerce A to String
+ *     A is String
+ *       return A
+ *     A is null
+ *       return ""
+ *     A.toString throws exception
+ *       error
+ *     otherwise
+ *       return A.toString
+ *
+ *   coerce A to primitive Number type N
+ *     A is null or ""
+ *       return 0
+ *     A is Character
+ *       convert to short, apply following rules
+ *     A is Boolean
+ *       error
+ *     A is Number type N
+ *       return A
+ *     A is Number with less precision than N
+ *       coerce quietly
+ *     A is Number with greater precision than N
+ *       coerce quietly
+ *     A is String
+ *       new N.valueOf(A) throws exception
+ *         error
+ *       return N.valueOf(A)
+ *     otherwise
+ *       error
+ *
+ *   coerce A to Character should be
+ *     A is null or ""
+ *       return (char) 0
+ *     A is Character
+ *       return A
+ *     A is Boolean
+ *       error
+ *     A is Number with less precision than short
+ *       coerce quietly - return (char) A
+ *     A is Number with greater precision than short
+ *       coerce quietly - return (char) A
+ *     A is String
+ *       return A.charAt (0)
+ *     otherwise
+ *       error
+ *
+ *   coerce A to Boolean
+ *     A is null or ""
+ *       return false
+ *     A is Boolean
+ *       return A
+ *     A is String
+ *       Boolean.valueOf(A) throws exception
+ *         error
+ *       return Boolean.valueOf(A)
+ *     otherwise
+ *       error
+ *
+ *   coerce A to any other type T
+ *     A is null
+ *       return null
+ *     A is assignable to T
+ *       coerce quietly
+ *     A is String
+ *       T has no PropertyEditor
+ *         if A is "", return null
+ *         otherwise error
+ *       T's PropertyEditor throws exception
+ *         if A is "", return null
+ *         otherwise error
+ *       otherwise
+ *         apply T's PropertyEditor
+ *     otherwise
+ *       error
+ * 
+ * + * @author Nathan Abramson - Art Technology Group + */ + +public class Coercions { + //------------------------------------- + + /** + * Coerces the given value to the specified class. + */ + public static Object coerce(Object pValue, + Class pClass, + Logger pLogger) + throws ELException { + if (pClass == String.class) { + return coerceToString(pValue, pLogger); + } else if (isPrimitiveNumberClass(pClass)) { + return coerceToPrimitiveNumber(pValue, pClass, pLogger); + } else if (pClass == Character.class || + pClass == Character.TYPE) { + return coerceToCharacter(pValue, pLogger); + } else if (pClass == Boolean.class || + pClass == Boolean.TYPE) { + return coerceToBoolean(pValue, pLogger); + } else { + return coerceToObject(pValue, pClass, pLogger); + } + } + + //------------------------------------- + + /** + * Returns true if the given class is Byte, Short, Integer, Long, + * Float, Double + */ + static boolean isPrimitiveNumberClass(Class pClass) { + return + pClass == Byte.class || + pClass == Byte.TYPE || + pClass == Short.class || + pClass == Short.TYPE || + pClass == Integer.class || + pClass == Integer.TYPE || + pClass == Long.class || + pClass == Long.TYPE || + pClass == Float.class || + pClass == Float.TYPE || + pClass == Double.class || + pClass == Double.TYPE; + } + + //------------------------------------- + + /** + * Coerces the specified value to a String + */ + public static String coerceToString(Object pValue, + Logger pLogger) + throws ELException { + if (pValue == null) { + return ""; + } else if (pValue instanceof String) { + return (String) pValue; + } else { + try { + return pValue.toString(); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError(Constants.TOSTRING_EXCEPTION, + exc, + pValue.getClass().getName()); + } + return ""; + } + } + } + + //------------------------------------- + + /** + * Coerces a value to the given primitive number class + */ + public static Number coerceToPrimitiveNumber(Object pValue, + Class pClass, + Logger pLogger) + throws ELException { + if (pValue == null || + "".equals(pValue)) { + return coerceToPrimitiveNumber(0, pClass); + } else if (pValue instanceof Character) { + char val = ((Character) pValue).charValue(); + return coerceToPrimitiveNumber((short) val, pClass); + } else if (pValue instanceof Boolean) { + if (pLogger.isLoggingError()) { + pLogger.logError(Constants.BOOLEAN_TO_NUMBER, + pValue, + pClass.getName()); + } + return coerceToPrimitiveNumber(0, pClass); + } else if (pValue.getClass() == pClass) { + return (Number) pValue; + } else if (pValue instanceof Number) { + return coerceToPrimitiveNumber((Number) pValue, pClass); + } else if (pValue instanceof String) { + try { + return coerceToPrimitiveNumber((String) pValue, pClass); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.STRING_TO_NUMBER_EXCEPTION, + (String) pValue, + pClass.getName()); + } + return coerceToPrimitiveNumber(0, pClass); + } + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COERCE_TO_NUMBER, + pValue.getClass().getName(), + pClass.getName()); + } + return coerceToPrimitiveNumber(0, pClass); + } + } + + //------------------------------------- + + /** + * Coerces a value to an Integer, returning null if the coercion + * isn't possible. + */ + public static Integer coerceToInteger(Object pValue, + Logger pLogger) + throws ELException { + if (pValue == null) { + return null; + } else if (pValue instanceof Character) { + return PrimitiveObjects.getInteger + ((int) (((Character) pValue).charValue())); + } else if (pValue instanceof Boolean) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning(Constants.BOOLEAN_TO_NUMBER, + pValue, + Integer.class.getName()); + } + return PrimitiveObjects.getInteger + (((Boolean) pValue).booleanValue() ? 1 : 0); + } else if (pValue instanceof Integer) { + return (Integer) pValue; + } else if (pValue instanceof Number) { + return PrimitiveObjects.getInteger(((Number) pValue).intValue()); + } else if (pValue instanceof String) { + try { + return Integer.valueOf((String) pValue); + } + catch (Exception exc) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.STRING_TO_NUMBER_EXCEPTION, + (String) pValue, + Integer.class.getName()); + } + return null; + } + } else { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.COERCE_TO_NUMBER, + pValue.getClass().getName(), + Integer.class.getName()); + } + return null; + } + } + + //------------------------------------- + + /** + * Coerces a long to the given primitive number class + */ + static Number coerceToPrimitiveNumber(long pValue, + Class pClass) + throws ELException { + if (pClass == Byte.class || pClass == Byte.TYPE) { + return PrimitiveObjects.getByte((byte) pValue); + } else if (pClass == Short.class || pClass == Short.TYPE) { + return PrimitiveObjects.getShort((short) pValue); + } else if (pClass == Integer.class || pClass == Integer.TYPE) { + return PrimitiveObjects.getInteger((int) pValue); + } else if (pClass == Long.class || pClass == Long.TYPE) { + return PrimitiveObjects.getLong((long) pValue); + } else if (pClass == Float.class || pClass == Float.TYPE) { + return PrimitiveObjects.getFloat((float) pValue); + } else if (pClass == Double.class || pClass == Double.TYPE) { + return PrimitiveObjects.getDouble((double) pValue); + } else { + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- + + /** + * Coerces a double to the given primitive number class + */ + static Number coerceToPrimitiveNumber(double pValue, + Class pClass) + throws ELException { + if (pClass == Byte.class || pClass == Byte.TYPE) { + return PrimitiveObjects.getByte((byte) pValue); + } else if (pClass == Short.class || pClass == Short.TYPE) { + return PrimitiveObjects.getShort((short) pValue); + } else if (pClass == Integer.class || pClass == Integer.TYPE) { + return PrimitiveObjects.getInteger((int) pValue); + } else if (pClass == Long.class || pClass == Long.TYPE) { + return PrimitiveObjects.getLong((long) pValue); + } else if (pClass == Float.class || pClass == Float.TYPE) { + return PrimitiveObjects.getFloat((float) pValue); + } else if (pClass == Double.class || pClass == Double.TYPE) { + return PrimitiveObjects.getDouble((double) pValue); + } else { + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- + + /** + * Coerces a Number to the given primitive number class + */ + static Number coerceToPrimitiveNumber(Number pValue, + Class pClass) + throws ELException { + if (pClass == Byte.class || pClass == Byte.TYPE) { + return PrimitiveObjects.getByte(pValue.byteValue()); + } else if (pClass == Short.class || pClass == Short.TYPE) { + return PrimitiveObjects.getShort(pValue.shortValue()); + } else if (pClass == Integer.class || pClass == Integer.TYPE) { + return PrimitiveObjects.getInteger(pValue.intValue()); + } else if (pClass == Long.class || pClass == Long.TYPE) { + return PrimitiveObjects.getLong(pValue.longValue()); + } else if (pClass == Float.class || pClass == Float.TYPE) { + return PrimitiveObjects.getFloat(pValue.floatValue()); + } else if (pClass == Double.class || pClass == Double.TYPE) { + return PrimitiveObjects.getDouble(pValue.doubleValue()); + } else { + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- + + /** + * Coerces a String to the given primitive number class + */ + static Number coerceToPrimitiveNumber(String pValue, + Class pClass) + throws ELException { + if (pClass == Byte.class || pClass == Byte.TYPE) { + return Byte.valueOf(pValue); + } else if (pClass == Short.class || pClass == Short.TYPE) { + return Short.valueOf(pValue); + } else if (pClass == Integer.class || pClass == Integer.TYPE) { + return Integer.valueOf(pValue); + } else if (pClass == Long.class || pClass == Long.TYPE) { + return Long.valueOf(pValue); + } else if (pClass == Float.class || pClass == Float.TYPE) { + return Float.valueOf(pValue); + } else if (pClass == Double.class || pClass == Double.TYPE) { + return Double.valueOf(pValue); + } else { + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- + + /** + * Coerces a value to a Character + */ + public static Character coerceToCharacter(Object pValue, + Logger pLogger) + throws ELException { + if (pValue == null || + "".equals(pValue)) { + return PrimitiveObjects.getCharacter((char) 0); + } else if (pValue instanceof Character) { + return (Character) pValue; + } else if (pValue instanceof Boolean) { + if (pLogger.isLoggingError()) { + pLogger.logError(Constants.BOOLEAN_TO_CHARACTER, pValue); + } + return PrimitiveObjects.getCharacter((char) 0); + } else if (pValue instanceof Number) { + return PrimitiveObjects.getCharacter + ((char) ((Number) pValue).shortValue()); + } else if (pValue instanceof String) { + String str = (String) pValue; + return PrimitiveObjects.getCharacter(str.charAt(0)); + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COERCE_TO_CHARACTER, + pValue.getClass().getName()); + } + return PrimitiveObjects.getCharacter((char) 0); + } + } + + //------------------------------------- + + /** + * Coerces a value to a Boolean + */ + public static Boolean coerceToBoolean(Object pValue, + Logger pLogger) + throws ELException { + if (pValue == null || + "".equals(pValue)) { + return Boolean.FALSE; + } else if (pValue instanceof Boolean) { + return (Boolean) pValue; + } else if (pValue instanceof String) { + String str = (String) pValue; + try { + return Boolean.valueOf(str); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.STRING_TO_BOOLEAN, + exc, + (String) pValue); + } + return Boolean.FALSE; + } + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COERCE_TO_BOOLEAN, + pValue.getClass().getName()); + } + return Boolean.TRUE; + } + } + + //------------------------------------- + + /** + * Coerces a value to the specified Class that is not covered by any + * of the above cases + */ + public static Object coerceToObject(Object pValue, + Class pClass, + Logger pLogger) + throws ELException { + if (pValue == null) { + return null; + } else if (pClass.isAssignableFrom(pValue.getClass())) { + return pValue; + } else if (pValue instanceof String) { + String str = (String) pValue; + PropertyEditor pe = PropertyEditorManager.findEditor(pClass); + if (pe == null) { + if ("".equals(str)) { + return null; + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.NO_PROPERTY_EDITOR, + str, + pClass.getName()); + } + return null; + } + } + try { + pe.setAsText(str); + return pe.getValue(); + } + catch (IllegalArgumentException exc) { + if ("".equals(str)) { + return null; + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.PROPERTY_EDITOR_ERROR, + exc, + pValue, + pClass.getName()); + } + return null; + } + } + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COERCE_TO_OBJECT, + pValue.getClass().getName(), + pClass.getName()); + } + return null; + } + } + + //------------------------------------- + // Applying operators + //------------------------------------- + + /** + * Performs all of the necessary type conversions, then calls on the + * appropriate operator. + */ + public static Object applyArithmeticOperator + (Object pLeft, + Object pRight, + ArithmeticOperator pOperator, + Logger pLogger) + throws ELException { + if (pLeft == null && + pRight == null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.ARITH_OP_NULL, + pOperator.getOperatorSymbol()); + } + return PrimitiveObjects.getInteger(0); + } else if (isFloatingPointType(pLeft) || + isFloatingPointType(pRight) || + isFloatingPointString(pLeft) || + isFloatingPointString(pRight)) { + double left = + coerceToPrimitiveNumber(pLeft, Double.class, pLogger). + doubleValue(); + double right = + coerceToPrimitiveNumber(pRight, Double.class, pLogger). + doubleValue(); + return + PrimitiveObjects.getDouble(pOperator.apply(left, right, pLogger)); + } else { + long left = + coerceToPrimitiveNumber(pLeft, Long.class, pLogger). + longValue(); + long right = + coerceToPrimitiveNumber(pRight, Long.class, pLogger). + longValue(); + return + PrimitiveObjects.getLong(pOperator.apply(left, right, pLogger)); + } + } + + //------------------------------------- + + /** + * Performs all of the necessary type conversions, then calls on the + * appropriate operator. + */ + public static Object applyRelationalOperator + (Object pLeft, + Object pRight, + RelationalOperator pOperator, + Logger pLogger) + throws ELException { + if (isFloatingPointType(pLeft) || + isFloatingPointType(pRight)) { + double left = + coerceToPrimitiveNumber(pLeft, Double.class, pLogger). + doubleValue(); + double right = + coerceToPrimitiveNumber(pRight, Double.class, pLogger). + doubleValue(); + return + PrimitiveObjects.getBoolean(pOperator.apply(left, right, pLogger)); + } else if (isIntegerType(pLeft) || + isIntegerType(pRight)) { + long left = + coerceToPrimitiveNumber(pLeft, Long.class, pLogger). + longValue(); + long right = + coerceToPrimitiveNumber(pRight, Long.class, pLogger). + longValue(); + return + PrimitiveObjects.getBoolean(pOperator.apply(left, right, pLogger)); + } else if (pLeft instanceof String || + pRight instanceof String) { + String left = coerceToString(pLeft, pLogger); + String right = coerceToString(pRight, pLogger); + return + PrimitiveObjects.getBoolean(pOperator.apply(left, right, pLogger)); + } else if (pLeft instanceof Comparable) { + try { + int result = ((Comparable) pLeft).compareTo(pRight); + return + PrimitiveObjects.getBoolean + (pOperator.apply(result, -result, pLogger)); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COMPARABLE_ERROR, + exc, + pLeft.getClass().getName(), + (pRight == null) ? "null" : pRight.getClass().getName(), + pOperator.getOperatorSymbol()); + } + return Boolean.FALSE; + } + } else if (pRight instanceof Comparable) { + try { + int result = ((Comparable) pRight).compareTo(pLeft); + return + PrimitiveObjects.getBoolean + (pOperator.apply(-result, result, pLogger)); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.COMPARABLE_ERROR, + exc, + pRight.getClass().getName(), + (pLeft == null) ? "null" : pLeft.getClass().getName(), + pOperator.getOperatorSymbol()); + } + return Boolean.FALSE; + } + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ARITH_OP_BAD_TYPE, + pOperator.getOperatorSymbol(), + pLeft.getClass().getName(), + pRight.getClass().getName()); + } + return Boolean.FALSE; + } + } + + //------------------------------------- + + /** + * Performs all of the necessary type conversions, then calls on the + * appropriate operator. + */ + public static Object applyEqualityOperator + (Object pLeft, + Object pRight, + EqualityOperator pOperator, + Logger pLogger) + throws ELException { + if (pLeft == pRight) { + return PrimitiveObjects.getBoolean(pOperator.apply(true, pLogger)); + } else if (pLeft == null || + pRight == null) { + return PrimitiveObjects.getBoolean(pOperator.apply(false, pLogger)); + } else if (isFloatingPointType(pLeft) || + isFloatingPointType(pRight)) { + double left = + coerceToPrimitiveNumber(pLeft, Double.class, pLogger). + doubleValue(); + double right = + coerceToPrimitiveNumber(pRight, Double.class, pLogger). + doubleValue(); + return + PrimitiveObjects.getBoolean + (pOperator.apply(left == right, pLogger)); + } else if (isIntegerType(pLeft) || + isIntegerType(pRight)) { + long left = + coerceToPrimitiveNumber(pLeft, Long.class, pLogger). + longValue(); + long right = + coerceToPrimitiveNumber(pRight, Long.class, pLogger). + longValue(); + return + PrimitiveObjects.getBoolean + (pOperator.apply(left == right, pLogger)); + } else if (pLeft instanceof Boolean || + pRight instanceof Boolean) { + boolean left = coerceToBoolean(pLeft, pLogger).booleanValue(); + boolean right = coerceToBoolean(pRight, pLogger).booleanValue(); + return + PrimitiveObjects.getBoolean + (pOperator.apply(left == right, pLogger)); + } else if (pLeft instanceof String || + pRight instanceof String) { + String left = coerceToString(pLeft, pLogger); + String right = coerceToString(pRight, pLogger); + return + PrimitiveObjects.getBoolean + (pOperator.apply(left.equals(right), pLogger)); + } else { + try { + return + PrimitiveObjects.getBoolean + (pOperator.apply(pLeft.equals(pRight), pLogger)); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ERROR_IN_EQUALS, + exc, + pLeft.getClass().getName(), + pRight.getClass().getName(), + pOperator.getOperatorSymbol()); + } + return Boolean.FALSE; + } + } + } + + //------------------------------------- + + /** + * Returns true if the given Object is of a floating point type + */ + public static boolean isFloatingPointType(Object pObject) { + return + pObject != null && + isFloatingPointType(pObject.getClass()); + } + + //------------------------------------- + + /** + * Returns true if the given class is of a floating point type + */ + public static boolean isFloatingPointType(Class pClass) { + return + pClass == Float.class || + pClass == Float.TYPE || + pClass == Double.class || + pClass == Double.TYPE; + } + + //------------------------------------- + + /** + * Returns true if the given string might contain a floating point + * number - i.e., it contains ".", "e", or "E" + */ + public static boolean isFloatingPointString(Object pObject) { + if (pObject instanceof String) { + String str = (String) pObject; + int len = str.length(); + for (int i = 0; i < len; i++) { + char ch = str.charAt(i); + if (ch == '.' || + ch == 'e' || + ch == 'E') { + return true; + } + } + return false; + } else { + return false; + } + } + + //------------------------------------- + + /** + * Returns true if the given Object is of an integer type + */ + public static boolean isIntegerType(Object pObject) { + return + pObject != null && + isIntegerType(pObject.getClass()); + } + + //------------------------------------- + + /** + * Returns true if the given class is of an integer type + */ + public static boolean isIntegerType(Class pClass) { + return + pClass == Byte.class || + pClass == Byte.TYPE || + pClass == Short.class || + pClass == Short.TYPE || + pClass == Character.class || + pClass == Character.TYPE || + pClass == Integer.class || + pClass == Integer.TYPE || + pClass == Long.class || + pClass == Long.TYPE; + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ComplexValue.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ComplexValue.java new file mode 100644 index 000000000..39e544beb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ComplexValue.java @@ -0,0 +1,118 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.List; +import java.util.Map; + +/** + *

Represents a dynamic value, which consists of a prefix and an + * optional set of ValueSuffix elements. A prefix is something like + * an identifier, and a suffix is something like a "property of" or + * "indexed element of" operator. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class ComplexValue + extends Expression { + //------------------------------------- + // Properties + //------------------------------------- + // property prefix + + Expression mPrefix; + + public Expression getPrefix() { + return mPrefix; + } + + public void setPrefix(Expression pPrefix) { + mPrefix = pPrefix; + } + + //------------------------------------- + // property suffixes + + List mSuffixes; + + public List getSuffixes() { + return mSuffixes; + } + + public void setSuffixes(List pSuffixes) { + mSuffixes = pSuffixes; + } + + //------------------------------------- + + /** + * Constructor + */ + public ComplexValue(Expression pPrefix, + List pSuffixes) { + mPrefix = pPrefix; + mSuffixes = pSuffixes; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + StringBuilder buf = new StringBuilder(); + buf.append(mPrefix.getExpressionString()); + + for (int i = 0; mSuffixes != null && i < mSuffixes.size(); i++) { + ValueSuffix suffix = (ValueSuffix) mSuffixes.get(i); + buf.append(suffix.getExpressionString()); + } + + return buf.toString(); + } + + //------------------------------------- + + /** + * Evaluates by evaluating the prefix, then applying the suffixes + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + Object ret = mPrefix.evaluate(pContext, pResolver, functions, + defaultPrefix, pLogger); + + // Apply the suffixes + for (int i = 0; mSuffixes != null && i < mSuffixes.size(); i++) { + ValueSuffix suffix = (ValueSuffix) mSuffixes.get(i); + ret = suffix.evaluate(ret, pContext, pResolver, functions, + defaultPrefix, pLogger); + } + + return ret; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Constants.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Constants.java new file mode 100644 index 000000000..4759488ae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Constants.java @@ -0,0 +1,199 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + *

This contains all of the non-public constants, including + * messsage strings read from the resource file. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class Constants { + //------------------------------------- + // Resources + + static ResourceBundle sResources = + ResourceBundle.getBundle("org.apache.taglibs.standard.lang.jstl.Resources"); + + //------------------------------------- + // Messages from the resource bundle + //------------------------------------- + + public static final String EXCEPTION_GETTING_BEANINFO = + getStringResource("EXCEPTION_GETTING_BEANINFO"); + + public static final String NULL_EXPRESSION_STRING = + getStringResource("NULL_EXPRESSION_STRING"); + + public static final String PARSE_EXCEPTION = + getStringResource("PARSE_EXCEPTION"); + + public static final String CANT_GET_PROPERTY_OF_NULL = + getStringResource("CANT_GET_PROPERTY_OF_NULL"); + + public static final String NO_SUCH_PROPERTY = + getStringResource("NO_SUCH_PROPERTY"); + + public static final String NO_GETTER_METHOD = + getStringResource("NO_GETTER_METHOD"); + + public static final String ERROR_GETTING_PROPERTY = + getStringResource("ERROR_GETTING_PROPERTY"); + + public static final String CANT_GET_INDEXED_VALUE_OF_NULL = + getStringResource("CANT_GET_INDEXED_VALUE_OF_NULL"); + + public static final String CANT_GET_NULL_INDEX = + getStringResource("CANT_GET_NULL_INDEX"); + + public static final String NULL_INDEX = + getStringResource("NULL_INDEX"); + + public static final String BAD_INDEX_VALUE = + getStringResource("BAD_INDEX_VALUE"); + + public static final String EXCEPTION_ACCESSING_LIST = + getStringResource("EXCEPTION_ACCESSING_LIST"); + + public static final String EXCEPTION_ACCESSING_ARRAY = + getStringResource("EXCEPTION_ACCESSING_ARRAY"); + + public static final String CANT_FIND_INDEX = + getStringResource("CANT_FIND_INDEX"); + + public static final String TOSTRING_EXCEPTION = + getStringResource("TOSTRING_EXCEPTION"); + + public static final String BOOLEAN_TO_NUMBER = + getStringResource("BOOLEAN_TO_NUMBER"); + + public static final String STRING_TO_NUMBER_EXCEPTION = + getStringResource("STRING_TO_NUMBER_EXCEPTION"); + + public static final String COERCE_TO_NUMBER = + getStringResource("COERCE_TO_NUMBER"); + + public static final String BOOLEAN_TO_CHARACTER = + getStringResource("BOOLEAN_TO_CHARACTER"); + + public static final String EMPTY_STRING_TO_CHARACTER = + getStringResource("EMPTY_STRING_TO_CHARACTER"); + + public static final String COERCE_TO_CHARACTER = + getStringResource("COERCE_TO_CHARACTER"); + + public static final String NULL_TO_BOOLEAN = + getStringResource("NULL_TO_BOOLEAN"); + + public static final String STRING_TO_BOOLEAN = + getStringResource("STRING_TO_BOOLEAN"); + + public static final String COERCE_TO_BOOLEAN = + getStringResource("COERCE_TO_BOOLEAN"); + + public static final String COERCE_TO_OBJECT = + getStringResource("COERCE_TO_OBJECT"); + + public static final String NO_PROPERTY_EDITOR = + getStringResource("NO_PROPERTY_EDITOR"); + + public static final String PROPERTY_EDITOR_ERROR = + getStringResource("PROPERTY_EDITOR_ERROR"); + + public static final String ARITH_OP_NULL = + getStringResource("ARITH_OP_NULL"); + + public static final String ARITH_OP_BAD_TYPE = + getStringResource("ARITH_OP_BAD_TYPE"); + + public static final String ARITH_ERROR = + getStringResource("ARITH_ERROR"); + + public static final String ERROR_IN_EQUALS = + getStringResource("ERROR_IN_EQUALS"); + + public static final String UNARY_OP_BAD_TYPE = + getStringResource("UNARY_OP_BAD_TYPE"); + + public static final String NAMED_VALUE_NOT_FOUND = + getStringResource("NAMED_VALUE_NOT_FOUND"); + + public static final String CANT_GET_INDEXED_PROPERTY = + getStringResource("CANT_GET_INDEXED_PROPERTY"); + + public static final String COMPARABLE_ERROR = + getStringResource("COMPARABLE_ERROR"); + + public static final String BAD_IMPLICIT_OBJECT = + getStringResource("BAD_IMPLICIT_OBJECT"); + + public static final String ATTRIBUTE_EVALUATION_EXCEPTION = + getStringResource("ATTRIBUTE_EVALUATION_EXCEPTION"); + + public static final String ATTRIBUTE_PARSE_EXCEPTION = + getStringResource("ATTRIBUTE_PARSE_EXCEPTION"); + + public static final String UNKNOWN_FUNCTION = + getStringResource("UNKNOWN_FUNCTION"); + + public static final String INAPPROPRIATE_FUNCTION_ARG_COUNT = + getStringResource("INAPPROPRIATE_FUNCTION_ARG_COUNT"); + + public static final String FUNCTION_INVOCATION_ERROR = + getStringResource("FUNCTION_INVOCATION_ERROR"); + + + //------------------------------------- + // Getting resources + //------------------------------------- + + /** + * + * + **/ + public static String getStringResource(String pResourceName) + throws MissingResourceException { + try { + String ret = sResources.getString(pResourceName); + if (ret == null) { + String str = "ERROR: Unable to load resource " + pResourceName; + System.err.println(str); + throw new MissingResourceException + (str, + "org.apache.taglibs.standard.lang.jstl.Constants", + pResourceName); + } else { + return ret; + } + } + catch (MissingResourceException exc) { + System.err.println("ERROR: Unable to load resource " + + pResourceName + + ": " + + exc); + throw exc; + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/DivideOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/DivideOperator.java new file mode 100644 index 000000000..6ebe51400 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/DivideOperator.java @@ -0,0 +1,97 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the divide operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class DivideOperator + extends BinaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final DivideOperator SINGLETON = + new DivideOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public DivideOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "/"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == null && + pRight == null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.ARITH_OP_NULL, + getOperatorSymbol()); + } + return PrimitiveObjects.getInteger(0); + } + + double left = + Coercions.coerceToPrimitiveNumber(pLeft, Double.class, pLogger). + doubleValue(); + double right = + Coercions.coerceToPrimitiveNumber(pRight, Double.class, pLogger). + doubleValue(); + + try { + return PrimitiveObjects.getDouble(left / right); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ARITH_ERROR, + getOperatorSymbol(), + "" + left, + "" + right); + } + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java new file mode 100644 index 000000000..0afe6ef59 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java @@ -0,0 +1,524 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.io.Reader; +import java.io.StringReader; +import java.text.MessageFormat; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import jakarta.servlet.jsp.PageContext; + +import org.apache.taglibs.standard.lang.jstl.parser.ELParser; +import org.apache.taglibs.standard.lang.jstl.parser.ParseException; +import org.apache.taglibs.standard.lang.jstl.parser.Token; +import org.apache.taglibs.standard.lang.jstl.parser.TokenMgrError; + +/** + *

This is the main class for evaluating expression Strings. An + * expression String is a String that may contain expressions of the + * form ${...}. Multiple expressions may appear in the same + * expression String. In such a case, the expression String's value + * is computed by concatenating the String values of those evaluated + * expressions and any intervening non-expression text, then + * converting the resulting String to the expected type using the + * PropertyEditor mechanism. + *

In the special case where the expression String is a single + * expression, the value of the expression String is determined by + * evaluating the expression, without any intervening conversion to a + * String. + *

The evaluator maintains a cache mapping expression Strings to + * their parsed results. For expression Strings containing no + * expression elements, it maintains a cache mapping + * ExpectedType/ExpressionString to parsed value, so that static + * expression Strings won't have to go through a conversion step every + * time they are used. All instances of the evaluator share the same + * cache. The cache may be bypassed by setting a flag on the + * evaluator's constructor. + *

The evaluator must be passed a VariableResolver in its + * constructor. The VariableResolver is used to resolve variable + * names encountered in expressions, and can also be used to implement + * "implicit objects" that are always present in the namespace. + * Different applications will have different policies for variable + * lookups and implicit objects - these differences can be + * encapsulated in the VariableResolver passed to the evaluator's + * constructor. + *

Most VariableResolvers will need to perform their resolution + * against some context. For example, a JSP environment needs a + * PageContext to resolve variables. The evaluate() method takes a + * generic Object context which is eventually passed to the + * VariableResolver - the VariableResolver is responsible for casting + * the context to the proper type. + *

Once an evaluator instance has been constructed, it may be used + * multiple times, and may be used by multiple simultaneous Threads. + * In other words, an evaluator instance is well-suited for use as a + * singleton. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ +public class ELEvaluator { + //------------------------------------- + // Properties + //------------------------------------- + + //------------------------------------- + // Member variables + //------------------------------------- + + /** + * Name of configuration setting for maximum number of entries in the + * cached expression string map + */ + private static final String EXPR_CACHE_PARAM + = "org.apache.taglibs.standard.lang.jstl.exprCacheSize"; + /** + * Default maximum cache size + */ + private static final int MAX_SIZE = 100; + + /** + * The mapping from expression String to its parsed form (String, + * Expression, or ExpressionString) + *

Using LRU Map with a maximum capacity to avoid out of bound map + * growth. + *

NOTE: use LinkedHashmap if a dependency on J2SE 1.4+ is ok + */ + private static Map sCachedExpressionStrings = null; + + /** + * The mapping from ExpectedType to Maps mapping literal String to + * parsed value * + */ + private static final Map sCachedExpectedTypes = new HashMap(); + + /** + * The static Logger * + */ + static Logger sLogger = new Logger(System.out); + + /** + * The VariableResolver * + */ + VariableResolver mResolver; + + /** + * Flag if the cache should be bypassed * + */ + private volatile boolean mBypassCache; + + /** + * The PageContext * + */ + // TODO: Find a better way to override the expression cache size that does not need this field. + PageContext pageContext; + + + //------------------------------------- + + /** + * Constructor + * + * @param pResolver the object that should be used to resolve + * variable names encountered in expressions. If null, all variable + * references will resolve to null. + */ + public ELEvaluator(VariableResolver pResolver) { + mResolver = pResolver; + } + + //------------------------------------- + + /** + * Enable cache bypass + * + * @param pBypassCache flag indicating cache should be bypassed + */ + public void setBypassCache(boolean pBypassCache) { + mBypassCache = pBypassCache; + } + + //------------------------------------- + + /** + * Evaluates the given expression String + * + * @param pExpressionString the expression String to be evaluated + * @param pContext the context passed to the VariableResolver for + * resolving variable names + * @param pExpectedType the type to which the evaluated expression + * should be coerced + * @return the expression String evaluated to the given expected + * type + */ + public Object evaluate(String pExpressionString, + Object pContext, + Class pExpectedType, + Map functions, + String defaultPrefix) + throws ELException { + return evaluate(pExpressionString, + pContext, + pExpectedType, + functions, + defaultPrefix, + sLogger); + } + + //------------------------------------- + + /** + * Evaluates the given expression string + */ + Object evaluate(String pExpressionString, + Object pContext, + Class pExpectedType, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + // Check for null expression strings + if (pExpressionString == null) { + throw new ELException + (Constants.NULL_EXPRESSION_STRING); + } + + // Set the PageContext; + pageContext = (PageContext) pContext; + + // Get the parsed version of the expression string + Object parsedValue = parseExpressionString(pExpressionString); + + // Evaluate differently based on the parsed type + if (parsedValue instanceof String) { + // Convert the String, and cache the conversion + String strValue = (String) parsedValue; + return convertStaticValueToExpectedType(strValue, + pExpectedType, + pLogger); + } else if (parsedValue instanceof Expression) { + // Evaluate the expression and convert + Object value = + ((Expression) parsedValue).evaluate(pContext, + mResolver, + functions, + defaultPrefix, + pLogger); + return convertToExpectedType(value, + pExpectedType, + pLogger); + } else if (parsedValue instanceof ExpressionString) { + // Evaluate the expression/string list and convert + String strValue = + ((ExpressionString) parsedValue).evaluate(pContext, + mResolver, + functions, + defaultPrefix, + pLogger); + return convertToExpectedType(strValue, + pExpectedType, + pLogger); + } else { + // This should never be reached + return null; + } + } + + //------------------------------------- + + /** + * Gets the parsed form of the given expression string. If the + * parsed form is cached (and caching is not bypassed), return the + * cached form, otherwise parse and cache the value. Returns either + * a String, Expression, or ExpressionString. + */ + public Object parseExpressionString(String pExpressionString) + throws ELException { + // See if it's an empty String + if (pExpressionString.length() == 0) { + return ""; + } + + if (mBypassCache) { + return parseExpressionUncached(pExpressionString); + } + + Map cache = getOrCreateExpressionStringMap(pageContext); + + // See if it's in the cache + Object ret = cache.get(pExpressionString); + if (ret != null) { + return ret; + } + + ret = parseExpressionUncached(pExpressionString); + cache.put(pExpressionString, ret); + return ret; + } + + /** + * Parse an expression string bypassing the cache. + * + * This allows expressions to be validated at translation time without polluting the cache. + * + * @param pExpressionString the text to parse + * @return the parse result + * @throws ELException if there was a problem parsing the expression text + */ + public Object parseExpressionUncached(String pExpressionString) throws ELException { + try { + Reader r = new StringReader(pExpressionString); + ELParser parser = new ELParser(r); + return parser.ExpressionString(); + } catch (ParseException exc) { + throw new ELException(formatParseException(pExpressionString, exc)); + } catch (TokenMgrError exc) { + // Note - this should never be reached, since the parser is + // constructed to tokenize any input (illegal inputs get + // parsed to or + // + throw new ELException(exc.getMessage()); + } + } + + //------------------------------------- + + /** + * Converts the given value to the specified expected type. + */ + Object convertToExpectedType(Object pValue, + Class pExpectedType, + Logger pLogger) + throws ELException { + return Coercions.coerce(pValue, + pExpectedType, + pLogger); + } + + //------------------------------------- + + /** + * Converts the given String, specified as a static expression + * string, to the given expected type. The conversion is cached. + */ + Object convertStaticValueToExpectedType(String pValue, + Class pExpectedType, + Logger pLogger) + throws ELException { + // See if the value is already of the expected type + if (pExpectedType == String.class || + pExpectedType == Object.class) { + return pValue; + } + + // Find the cached value + Map valueByString = getOrCreateExpectedTypeMap(pExpectedType); + if (!mBypassCache && + valueByString.containsKey(pValue)) { + return valueByString.get(pValue); + } else { + // Convert from a String + Object ret = Coercions.coerce(pValue, pExpectedType, pLogger); + valueByString.put(pValue, ret); + return ret; + } + } + + //------------------------------------- + + /** + * Creates or returns the Map that maps string literals to parsed + * values for the specified expected type. + */ + static Map getOrCreateExpectedTypeMap(Class pExpectedType) { + synchronized (sCachedExpectedTypes) { + Map ret = (Map) sCachedExpectedTypes.get(pExpectedType); + if (ret == null) { + ret = Collections.synchronizedMap(new HashMap()); + sCachedExpectedTypes.put(pExpectedType, ret); + } + return ret; + } + } + + //------------------------------------- + + /** + * Creates LRU map of expression strings. If context parameter + * specifying cache size is present use that as the maximum size + * of the LRU map otherwise use default. + * + * TODO: Using the context parameter means the cache is sized based on the configuration + * of the first web application that calls this. This might be a problem if this jar is + * installed in the application server's classpath rather than the application's. + */ + private static synchronized Map getOrCreateExpressionStringMap(PageContext pageContext) { + if (sCachedExpressionStrings == null) { + + final int maxSize; + if ((pageContext != null) && (pageContext.getServletContext() != null)) { + String value = pageContext.getServletContext().getInitParameter(EXPR_CACHE_PARAM); + if (value != null) { + maxSize = Integer.valueOf(value); + } else { + maxSize = MAX_SIZE; + } + } else { + maxSize = MAX_SIZE; + } + + // fall through if it couldn't find the parameter + sCachedExpressionStrings = Collections.synchronizedMap(new LinkedHashMap() { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxSize; + } + }); + } + return sCachedExpressionStrings; + } + + //------------------------------------- + // Formatting ParseException + //------------------------------------- + + /** + * Formats a ParseException into an error message suitable for + * displaying on a web page + */ + static String formatParseException(String pExpressionString, + ParseException pExc) { + // Generate the String of expected tokens + StringBuilder expectedBuf = new StringBuilder(); + int maxSize = 0; + boolean printedOne = false; + + if (pExc.expectedTokenSequences == null) { + return pExc.toString(); + } + + for (int i = 0; i < pExc.expectedTokenSequences.length; i++) { + if (maxSize < pExc.expectedTokenSequences[i].length) { + maxSize = pExc.expectedTokenSequences[i].length; + } + for (int j = 0; j < pExc.expectedTokenSequences[i].length; j++) { + if (printedOne) { + expectedBuf.append(", "); + } + expectedBuf.append + (pExc.tokenImage[pExc.expectedTokenSequences[i][j]]); + printedOne = true; + } + } + String expected = expectedBuf.toString(); + + // Generate the String of encountered tokens + StringBuilder encounteredBuf = new StringBuilder(); + Token tok = pExc.currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) { + encounteredBuf.append(" "); + } + if (tok.kind == 0) { + encounteredBuf.append(pExc.tokenImage[0]); + break; + } + encounteredBuf.append(addEscapes(tok.image)); + tok = tok.next; + } + String encountered = encounteredBuf.toString(); + + // Format the error message + return MessageFormat.format + (Constants.PARSE_EXCEPTION, + new Object[]{ + expected, + encountered, + }); + } + + //------------------------------------- + + /** + * Used to convert raw characters to their escaped version when + * these raw version cannot be used as part of an ASCII string + * literal. + */ + static String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case 0: + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + //------------------------------------- + // Testing methods + //------------------------------------- + + /** + * Parses the given expression string, then converts it back to a + * String in its canonical form. This is used to test parsing. + */ + public String parseAndRender(String pExpressionString) + throws ELException { + Object val = parseExpressionString(pExpressionString); + if (val instanceof String) { + return (String) val; + } else if (val instanceof Expression) { + return "${" + ((Expression) val).getExpressionString() + "}"; + } else if (val instanceof ExpressionString) { + return ((ExpressionString) val).getExpressionString(); + } else { + return ""; + } + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELException.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELException.java new file mode 100644 index 000000000..f45fa9969 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELException.java @@ -0,0 +1,99 @@ +/* + * 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.taglibs.standard.lang.jstl; + + +/** + * Represents any of the exception conditions that arise during the + * operation evaluation of the evaluator. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class ELException + extends Exception { + //------------------------------------- + // Member variables + //------------------------------------- + + Throwable mRootCause; + + //------------------------------------- + + /** + * Constructor + */ + public ELException() { + super(); + } + + //------------------------------------- + + /** + * Constructor + */ + public ELException(String pMessage) { + super(pMessage); + } + + //------------------------------------- + + /** + * Constructor + */ + public ELException(Throwable pRootCause) { + mRootCause = pRootCause; + } + + //------------------------------------- + + /** + * Constructor + */ + public ELException(String pMessage, + Throwable pRootCause) { + super(pMessage); + mRootCause = pRootCause; + } + + //------------------------------------- + + /** + * Returns the root cause + */ + public Throwable getRootCause() { + return mRootCause; + } + + //------------------------------------- + + /** + * String representation + */ + public String toString() { + if (getMessage() == null) { + return mRootCause.toString(); + } else if (mRootCause == null) { + return getMessage(); + } else { + return getMessage() + ": " + mRootCause; + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELParser.jj b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELParser.jj new file mode 100644 index 000000000..71d788220 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ELParser.jj @@ -0,0 +1,815 @@ +/* + * 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. + */ + +/***************************************** + * OPTIONS * + *****************************************/ + +options { + JAVA_UNICODE_ESCAPE = false; + UNICODE_INPUT = true; + STATIC = false; +} + +/***************************************** + * PARSER JAVA CODE * + *****************************************/ + +PARSER_BEGIN(ELParser) + +/* + * 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.taglibs.standard.lang.jstl.parser; + +import org.apache.taglibs.standard.lang.jstl.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Generated EL parser. + * + * @author Nathan Abramson + * @author Shawn Bayern + */ + +public class ELParser { + + public static void main(String args[]) + throws ParseException + { + ELParser parser = new ELParser (System.in); + parser.ExpressionString (); + } + +} + +PARSER_END(ELParser) + + +/***************************************** + * TOKENS * + *****************************************/ + + +/***************************************** +/** Tokens appearing outside of an ${...} construct **/ + + TOKEN: +{ + < NON_EXPRESSION_TEXT: + (~["$"])+ | ("$" (~["{", "$"])+) | "$" + > +| + < START_EXPRESSION: "${" > : IN_EXPRESSION +} + +/***************************************** +/** Tokens appearing inside of an ${...} construct **/ + +/* WHITE SPACE */ + + SKIP : +{ + " " +| "\t" +| "\n" +| "\r" +} + + TOKEN : +{ +/* Literals */ + + < INTEGER_LITERAL: ["0"-"9"] (["0"-"9"])* > +| + < FLOATING_POINT_LITERAL: + (["0"-"9"])+ "." (["0"-"9"])* ()? + | "." (["0"-"9"])+ ()? + | (["0"-"9"])+ + > +| + < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > +| + < STRING_LITERAL: + ("\"" ((~["\"","\\"]) | ("\\" ( ["\\","\""] )))* "\"") | + ("\'" ((~["\'","\\"]) | ("\\" ( ["\\","\'"] )))* "\'") + > +| + < BADLY_ESCAPED_STRING_LITERAL: + ("\"" (~["\"","\\"])* ("\\" ( ~["\\","\""] ))) | + ("\'" (~["\'","\\"])* ("\\" ( ~["\\","\'"] ))) + > + +/* Reserved Words and Symbols */ + +| < TRUE: "true" > +| < FALSE: "false" > +| < NULL: "null" > +| < END_EXPRESSION: "}" > : DEFAULT +| < DOT: "." > +| < GT1: ">" > +| < GT2: "gt" > +| < LT1: "<" > +| < LT2: "lt" > +| < EQ1: "==" > +| < EQ2: "eq" > +| < LE1: "<=" > +| < LE2: "le" > +| < GE1: ">=" > +| < GE2: "ge" > +| < NE1: "!=" > +| < NE2: "ne" > +| < LPAREN: "(" > +| < RPAREN: ")" > +| < COMMA: "," > +| < COLON: ":" > +| < LBRACKET: "[" > +| < RBRACKET: "]" > +| < PLUS: "+" > +| < MINUS: "-" > +| < MULTIPLY: "*" > +| < DIVIDE1: "/" > +| < DIVIDE2: "div" > +| < MODULUS1: "%" > +| < MODULUS2: "mod" > +| < NOT1: "not" > +| < NOT2: "!" > +| < AND1: "and" > +| < AND2: "&&" > +| < OR1: "or" > +| < OR2: "||" > +| < EMPTY: "empty" > + + +/* Identifiers */ + +| < IDENTIFIER: (|) (|)* > +| < #IMPL_OBJ_START: "#" > +| + < #LETTER: + [ + "\u0024", + "\u0041"-"\u005a", + "\u005f", + "\u0061"-"\u007a", + "\u00c0"-"\u00d6", + "\u00d8"-"\u00f6", + "\u00f8"-"\u00ff", + "\u0100"-"\u1fff", + "\u3040"-"\u318f", + "\u3300"-"\u337f", + "\u3400"-"\u3d2d", + "\u4e00"-"\u9fff", + "\uf900"-"\ufaff" + ] + > +| + < #DIGIT: + [ + "\u0030"-"\u0039", + "\u0660"-"\u0669", + "\u06f0"-"\u06f9", + "\u0966"-"\u096f", + "\u09e6"-"\u09ef", + "\u0a66"-"\u0a6f", + "\u0ae6"-"\u0aef", + "\u0b66"-"\u0b6f", + "\u0be7"-"\u0bef", + "\u0c66"-"\u0c6f", + "\u0ce6"-"\u0cef", + "\u0d66"-"\u0d6f", + "\u0e50"-"\u0e59", + "\u0ed0"-"\u0ed9", + "\u1040"-"\u1049" + ] + > + +/* This is used to catch any non-matching tokens, so as to avoid any + TokenMgrErrors */ +| < ILLEGAL_CHARACTER: (~[]) > +} + + +/***************************************** + * GRAMMAR PRODUCTIONS * + *****************************************/ + +/** + * + * Returns a String if the expression string is a single String, an + * Expression if the expression string is a single Expression, an + * ExpressionString if it's a mixture of both. + **/ +Object ExpressionString () : +{ + Object ret = ""; + List elems = null; + Object elem; +} +{ + /** Try to optimize for the case of a single expression or String **/ + (ret = AttrValueString () | ret = AttrValueExpression ()) + + + /** If there's more than one, then switch to using a List **/ + ( + (elem = AttrValueString () | elem = AttrValueExpression ()) + { + if (elems == null) { + elems = new ArrayList (); + elems.add (ret); + } + elems.add (elem); + } + )* + + { + if (elems != null) { + ret = new ExpressionString (elems.toArray ()); + } + return ret; + } +} + + +String AttrValueString () : +{ + Token t; +} +{ + t = + { return t.image; } +} + + +Expression AttrValueExpression () : +{ + Expression exp; +} +{ + exp = Expression () + { return exp; } +} + + +Expression Expression () : +{ + Expression ret; +} +{ + ret = OrExpression () + { return ret; } +} + + +Expression OrExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = AndExpression () + + ( + ( + ( | ) { operator = OrOperator.SINGLETON; } + ) + expression = AndExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression AndExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = EqualityExpression () + + ( + ( + ( | ) { operator = AndOperator.SINGLETON; } + ) + expression = EqualityExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression EqualityExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = RelationalExpression () + + ( + ( + ( | ) { operator = EqualsOperator.SINGLETON; } + | ( | ) { operator = NotEqualsOperator.SINGLETON; } + ) + expression = RelationalExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression RelationalExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = AddExpression () + + ( + ( + ( | ) { operator = LessThanOperator.SINGLETON; } + | ( | ) { operator = GreaterThanOperator.SINGLETON; } + | ( | ) { operator = GreaterThanOrEqualsOperator.SINGLETON; } + | ( | ) { operator = LessThanOrEqualsOperator.SINGLETON; } + ) + expression = AddExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression AddExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = MultiplyExpression () + + ( + ( + { operator = PlusOperator.SINGLETON; } + | { operator = MinusOperator.SINGLETON; } + ) + expression = MultiplyExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression MultiplyExpression () : +{ + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; +} +{ + startExpression = UnaryExpression () + + ( + ( + { operator = MultiplyOperator.SINGLETON; } + | ( | ) { operator = DivideOperator.SINGLETON; } + | ( | ) { operator = ModulusOperator.SINGLETON; } + ) + expression = UnaryExpression () + + { + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + )* + + { + if (operators != null) { + return new BinaryOperatorExpression (startExpression, + operators, + expressions); + } + else { + return startExpression; + } + } +} + + +Expression UnaryExpression () : +{ + Expression expression; + UnaryOperator singleOperator = null; + UnaryOperator operator; + List operators = null; +} +{ + ( + ( + ( | ) { operator = NotOperator.SINGLETON; } + | { operator = UnaryMinusOperator.SINGLETON; } + | { operator = EmptyOperator.SINGLETON; } + ) + { + if (singleOperator == null) { + singleOperator = operator; + } + else if (operators == null) { + operators = new ArrayList (); + operators.add (singleOperator); + operators.add (operator); + } + else { + operators.add (operator); + } + } + )* + + expression = Value () + + { + if (operators != null) { + return new UnaryOperatorExpression (null, operators, expression); + } + else if (singleOperator != null) { + return new UnaryOperatorExpression (singleOperator, null, expression); + } + else { + return expression; + } + } +} + + +Expression Value () : +{ + Expression prefix; + ValueSuffix suffix; + List suffixes = null; +} +{ + prefix = ValuePrefix () + (suffix = ValueSuffix () + { + if (suffixes == null) { + suffixes = new ArrayList (); + } + suffixes.add (suffix); + } + )* + + { + if (suffixes == null) { + return prefix; + } + else { + return new ComplexValue (prefix, suffixes); + } + } +} + + +/** + * This is an element that can start a value + **/ +Expression ValuePrefix () : +{ + Expression ret; +} +{ + ( + ret = Literal () + | ret = Expression () + | LOOKAHEAD(QualifiedName() ) ret = FunctionInvocation () + | ret = NamedValue () + ) + { return ret; } +} + + +NamedValue NamedValue () : +{ + Token t; +} +{ + t = { return new NamedValue (t.image); } +} + + +FunctionInvocation FunctionInvocation () : +{ + String qualifiedName; + List argumentList = new ArrayList(); + Expression exp; +} +{ + ( + qualifiedName = QualifiedName() + + ( + ( + exp = Expression () + { + argumentList.add(exp); + } + ) + ( + + exp = Expression () + { + argumentList.add(exp); + } + )* + )? + + ) + { + String allowed = System.getProperty("javax.servlet.jsp.functions.allowed"); + if (allowed == null || !allowed.equalsIgnoreCase("true")) + throw new ParseException("EL functions are not supported."); + return new FunctionInvocation(qualifiedName, argumentList); + } +} + + +ValueSuffix ValueSuffix () : +{ + ValueSuffix suffix; +} +{ + ( + suffix = PropertySuffix () + | suffix = ArraySuffix () + ) + + { return suffix; } +} + + +PropertySuffix PropertySuffix () : +{ + Token t; + String property; +} +{ + + (property = Identifier ()) + + { + return new PropertySuffix (property); + } +} + + +ArraySuffix ArraySuffix () : +{ + Expression index; +} +{ + + index = Expression () + + + { + return new ArraySuffix (index); + } +} + + +Literal Literal () : +{ + Literal ret; +} +{ + ( + ret = BooleanLiteral () + | ret = IntegerLiteral () + | ret = FloatingPointLiteral () + | ret = StringLiteral () + | ret = NullLiteral () + ) + { return ret; } +} + + +BooleanLiteral BooleanLiteral () : +{ +} +{ + { return BooleanLiteral.TRUE; } + | { return BooleanLiteral.FALSE; } +} + + +StringLiteral StringLiteral () : +{ + Token t; +} +{ + t = + { return StringLiteral.fromToken (t.image); } +} + + +IntegerLiteral IntegerLiteral () : +{ + Token t; +} +{ + t = + { return new IntegerLiteral (t.image); } +} + + +FloatingPointLiteral FloatingPointLiteral () : +{ + Token t; +} +{ + t = + { return new FloatingPointLiteral (t.image); } +} + + +NullLiteral NullLiteral () : +{ +} +{ + + { return NullLiteral.SINGLETON; } +} + + +String Identifier () : +{ + Token t; +} +{ + ( + t = + ) + { return t.image; } +} + +String QualifiedName () : +{ + String prefix = null, localPart = null; +} +{ + ( + ( + LOOKAHEAD(Identifier() ) + prefix = Identifier () + + )? + localPart = Identifier () + ) + { + if (prefix == null) + return localPart; + else + return prefix + ":" + localPart; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EmptyOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EmptyOperator.java new file mode 100644 index 000000000..1c568d45c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EmptyOperator.java @@ -0,0 +1,165 @@ +/* + * 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.taglibs.standard.lang.jstl; + + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + + +/** + *

The implementation of the empty operator + * + * @author Nathan Abramson - Art Technology Group + */ + + +public class EmptyOperator + + extends UnaryOperator + +{ + + //------------------------------------- + + // Singleton + + //------------------------------------- + + + public static final EmptyOperator SINGLETON = + + new EmptyOperator(); + + + //------------------------------------- + + /** + * Constructor + */ + + public EmptyOperator() + + { + + } + + + //------------------------------------- + + // Expression methods + + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + + public String getOperatorSymbol() + + { + + return "empty"; + + } + + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + + public Object apply(Object pValue, + + Object pContext, + + Logger pLogger) + + throws ELException + + { + + // See if the value is null + + if (pValue == null) { + + return PrimitiveObjects.getBoolean(true); + + } + + + // See if the value is a zero-length String + + else if ("".equals(pValue)) { + + return PrimitiveObjects.getBoolean(true); + + } + + + // See if the value is a zero-length array + + else if (pValue.getClass().isArray() && + + Array.getLength(pValue) == 0) { + + return PrimitiveObjects.getBoolean(true); + + } + + + // See if the value is an empty Collection + + else if (pValue instanceof Collection && + + ((Collection) pValue).isEmpty()) { + + return PrimitiveObjects.getBoolean(true); + + } + + + // See if the value is an empty Map + + else if (pValue instanceof Map && + + ((Map) pValue).isEmpty()) { + + return PrimitiveObjects.getBoolean(true); + + } + + + // Otherwise, not empty + + else { + + return PrimitiveObjects.getBoolean(false); + + } + + } + + + //------------------------------------- + +} + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EnumeratedMap.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EnumeratedMap.java new file mode 100644 index 000000000..571e53aeb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EnumeratedMap.java @@ -0,0 +1,175 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + *

This is a Map implementation driven by a data source that only + * provides an enumeration of keys and a getValue(key) method. This + * class must be subclassed to implement those methods. + *

Some of the methods may incur a performance penalty that + * involves enumerating the entire data source. In these cases, the + * Map will try to save the results of that enumeration, but only if + * the underlying data source is immutable. + * + * @author Nathan Abramson - Art Technology Group + */ +public abstract class EnumeratedMap + implements Map { + //------------------------------------- + // Member variables + //------------------------------------- + + Map mMap; + + //------------------------------------- + + public void clear() { + throw new UnsupportedOperationException(); + } + + //------------------------------------- + + public boolean containsKey(Object pKey) { + return getValue(pKey) != null; + } + + //------------------------------------- + + public boolean containsValue(Object pValue) { + return getAsMap().containsValue(pValue); + } + + //------------------------------------- + + public Set entrySet() { + return getAsMap().entrySet(); + } + + //------------------------------------- + + public Object get(Object pKey) { + return getValue(pKey); + } + + //------------------------------------- + + public boolean isEmpty() { + return !enumerateKeys().hasMoreElements(); + } + + //------------------------------------- + + public Set keySet() { + return getAsMap().keySet(); + } + + //------------------------------------- + + public Object put(Object pKey, Object pValue) { + throw new UnsupportedOperationException(); + } + + //------------------------------------- + + public void putAll(Map pMap) { + throw new UnsupportedOperationException(); + } + + //------------------------------------- + + public Object remove(Object pKey) { + throw new UnsupportedOperationException(); + } + + //------------------------------------- + + public int size() { + return getAsMap().size(); + } + + //------------------------------------- + + public Collection values() { + return getAsMap().values(); + } + + //------------------------------------- + // Abstract methods + //------------------------------------- + + /** + * Returns an enumeration of the keys + */ + public abstract Enumeration enumerateKeys(); + + //------------------------------------- + + /** + * Returns true if it is possible for this data source to change + */ + public abstract boolean isMutable(); + + //------------------------------------- + + /** + * Returns the value associated with the given key, or null if not + * found. + */ + public abstract Object getValue(Object pKey); + + //------------------------------------- + + /** + * Converts the MapSource to a Map. If the map is not mutable, this + * is cached + */ + public Map getAsMap() { + if (mMap != null) { + return mMap; + } else { + Map m = convertToMap(); + if (!isMutable()) { + mMap = m; + } + return m; + } + } + + //------------------------------------- + + /** + * Converts to a Map + */ + Map convertToMap() { + Map ret = new HashMap(); + for (Enumeration e = enumerateKeys(); e.hasMoreElements();) { + Object key = e.nextElement(); + Object value = getValue(key); + ret.put(key, value); + } + return ret; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualityOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualityOperator.java new file mode 100644 index 000000000..073a0092d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualityOperator.java @@ -0,0 +1,51 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This is the superclass for all equality operators (==, !=) + * + * @author Nathan Abramson - Art Technology Group + */ + +public abstract class EqualityOperator + extends BinaryOperator { + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + return Coercions.applyEqualityOperator(pLeft, pRight, this, pLogger); + } + + //------------------------------------- + + /** + * Applies the operator given the fact that the two elements are + * equal. + */ + public abstract boolean apply(boolean pAreEqual, + Logger pLogger); + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualsOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualsOperator.java new file mode 100644 index 000000000..db1542e33 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/EqualsOperator.java @@ -0,0 +1,66 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the equals operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class EqualsOperator + extends EqualityOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final EqualsOperator SINGLETON = + new EqualsOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public EqualsOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "=="; + } + + //------------------------------------- + + /** + * Applies the operator given the fact that the two elements are + * equal. + */ + public boolean apply(boolean pAreEqual, + Logger pLogger) { + return pAreEqual; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Evaluator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Evaluator.java new file mode 100644 index 000000000..99c97a84d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Evaluator.java @@ -0,0 +1,159 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.text.MessageFormat; +import java.util.Map; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluator; + +/** + *

This is the expression evaluator "adapter" that customizes it + * for use with the JSP Standard Tag Library. It uses a + * VariableResolver implementation that looks up variables from the + * PageContext and also implements its implicit objects. It also + * wraps ELExceptions in JspExceptions that describe the attribute + * name and value causing the error. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class Evaluator + implements ExpressionEvaluator { + //------------------------------------- + // Properties + //------------------------------------- + + //------------------------------------- + // Member variables + //------------------------------------- + + /** + * The singleton instance of the evaluator * + */ + static ELEvaluator sEvaluator = + new ELEvaluator + (new JSTLVariableResolver()); + + //------------------------------------- + // ExpressionEvaluator methods + //------------------------------------- + + /** + * Translation time validation of an attribute value. This method + * will return a null String if the attribute value is valid; + * otherwise an error message. + */ + public String validate(String pAttributeName, + String pAttributeValue) { + try { + sEvaluator.parseExpressionUncached(pAttributeValue); + return null; + } + catch (ELException exc) { + return + MessageFormat.format + (Constants.ATTRIBUTE_PARSE_EXCEPTION, + "" + pAttributeName, + "" + pAttributeValue, + exc.getMessage()); + } + } + + //------------------------------------- + + /** + * Evaluates the expression at request time + */ + public Object evaluate(String pAttributeName, + String pAttributeValue, + Class pExpectedType, + Tag pTag, + PageContext pPageContext, + Map functions, + String defaultPrefix) + throws JspException { + try { + return sEvaluator.evaluate + (pAttributeValue, + pPageContext, + pExpectedType, + functions, + defaultPrefix); + } + catch (ELException exc) { + throw new JspException + (MessageFormat.format + (Constants.ATTRIBUTE_EVALUATION_EXCEPTION, + "" + pAttributeName, + "" + pAttributeValue, + exc.getMessage(), + exc.getRootCause()), exc.getRootCause()); + } + } + + /** + * Conduit to old-style call for convenience. + */ + public Object evaluate(String pAttributeName, + String pAttributeValue, + Class pExpectedType, + Tag pTag, + PageContext pPageContext) + throws JspException { + return evaluate(pAttributeName, + pAttributeValue, + pExpectedType, + pTag, + pPageContext, + null, + null); + } + + + //------------------------------------- + // Testing methods + //------------------------------------- + + /** + * Parses the given attribute value, then converts it back to a + * String in its canonical form. + */ + public static String parseAndRender(String pAttributeValue) + throws JspException { + try { + return sEvaluator.parseAndRender(pAttributeValue); + } + catch (ELException exc) { + throw new JspException + (MessageFormat.format + (Constants.ATTRIBUTE_PARSE_EXCEPTION, + "test", + "" + pAttributeValue, + exc.getMessage())); + } + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Expression.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Expression.java new file mode 100644 index 000000000..175341f73 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Expression.java @@ -0,0 +1,56 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

The abstract class from which all expression types + * derive. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public abstract class Expression { + //------------------------------------- + // Member variables + //------------------------------------- + + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public abstract String getExpressionString(); + + //------------------------------------- + + /** + * Evaluates the expression in the given context + */ + public abstract Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException; + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ExpressionString.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ExpressionString.java new file mode 100644 index 000000000..cae523fa5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ExpressionString.java @@ -0,0 +1,109 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

Represents an expression String consisting of a mixture of + * Strings and Expressions. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class ExpressionString { + //------------------------------------- + // Properties + //------------------------------------- + // property elements + + Object[] mElements; + + public Object[] getElements() { + return mElements; + } + + public void setElements(Object[] pElements) { + mElements = pElements; + } + + //------------------------------------- + + /** + * Constructor + */ + public ExpressionString(Object[] pElements) { + mElements = pElements; + } + + //------------------------------------- + + /** + * Evaluates the expression string by evaluating each element, + * converting it to a String (using toString, or "" for null values) + * and concatenating the results into a single String. + */ + public String evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < mElements.length; i++) { + Object elem = mElements[i]; + if (elem instanceof String) { + buf.append((String) elem); + } else if (elem instanceof Expression) { + Object val = + ((Expression) elem).evaluate(pContext, + pResolver, + functions, + defaultPrefix, + pLogger); + if (val != null) { + buf.append(val.toString()); + } + } + } + return buf.toString(); + } + + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < mElements.length; i++) { + Object elem = mElements[i]; + if (elem instanceof String) { + buf.append((String) elem); + } else if (elem instanceof Expression) { + buf.append("${"); + buf.append(((Expression) elem).getExpressionString()); + buf.append("}"); + } + } + return buf.toString(); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FloatingPointLiteral.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FloatingPointLiteral.java new file mode 100644 index 000000000..b2068cf14 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FloatingPointLiteral.java @@ -0,0 +1,59 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

An expression representing a floating point literal value. The + * value is stored internally as a double. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class FloatingPointLiteral + extends Literal { + //------------------------------------- + + /** + * Constructor + */ + public FloatingPointLiteral(String pToken) { + super(getValueFromToken(pToken)); + } + + //------------------------------------- + + /** + * Parses the given token into the literal value + */ + static Object getValueFromToken(String pToken) { + return new Double(pToken); + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return getValue().toString(); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FunctionInvocation.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FunctionInvocation.java new file mode 100644 index 000000000..117196e95 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/FunctionInvocation.java @@ -0,0 +1,159 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + *

Represents a function call.

+ * + * @author Shawn Bayern (in the style of Nathan's other classes) + */ + +public class FunctionInvocation + extends Expression { + //------------------------------------- + // Properties + //------------------------------------- + // property index + + private String functionName; + private List argumentList; + + public String getFunctionName() { + return functionName; + } + + public void setFunctionName(String f) { + functionName = f; + } + + public List getArgumentList() { + return argumentList; + } + + public void setArgumentList(List l) { + argumentList = l; + } + + //------------------------------------- + + /** + * Constructor + */ + public FunctionInvocation(String functionName, List argumentList) { + this.functionName = functionName; + this.argumentList = argumentList; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + StringBuilder b = new StringBuilder(); + b.append(functionName); + b.append("("); + Iterator i = argumentList.iterator(); + while (i.hasNext()) { + b.append(((Expression) i.next()).getExpressionString()); + if (i.hasNext()) { + b.append(", "); + } + } + b.append(")"); + return b.toString(); + } + + + //------------------------------------- + + /** + * Evaluates by looking up the name in the VariableResolver + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + + // if the Map is null, then the function is invalid + if (functions == null) { + pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName); + } + + // normalize function name against default prefix + String functionName = this.functionName; + if (functionName.indexOf(":") == -1) { + if (defaultPrefix == null) { + pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName); + } + functionName = defaultPrefix + ":" + functionName; + } + + // ensure that the function's name is mapped + Method target = (Method) functions.get(functionName); + if (target == null) { + pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName); + } + + // ensure that the number of arguments matches the number of parameters + Class[] params = target.getParameterTypes(); + if (params.length != argumentList.size()) { + pLogger.logError(Constants.INAPPROPRIATE_FUNCTION_ARG_COUNT, + new Integer(params.length), + new Integer(argumentList.size())); + } + + // now, walk through each parameter, evaluating and casting its argument + Object[] arguments = new Object[argumentList.size()]; + for (int i = 0; i < params.length; i++) { + // evaluate + arguments[i] = ((Expression) argumentList.get(i)).evaluate(pContext, + pResolver, + functions, + defaultPrefix, + pLogger); + // coerce + arguments[i] = Coercions.coerce(arguments[i], params[i], pLogger); + } + + // finally, invoke the target method, which we know to be static + try { + return (target.invoke(null, arguments)); + } catch (InvocationTargetException ex) { + pLogger.logError(Constants.FUNCTION_INVOCATION_ERROR, + ex.getTargetException(), + functionName); + return null; + } catch (Exception ex) { + pLogger.logError(Constants.FUNCTION_INVOCATION_ERROR, ex, functionName); + return null; + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOperator.java new file mode 100644 index 000000000..a6db1ff37 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOperator.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the greater than operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class GreaterThanOperator + extends RelationalOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final GreaterThanOperator SINGLETON = + new GreaterThanOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public GreaterThanOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return ">"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == pRight) { + return Boolean.FALSE; + } else if (pLeft == null || + pRight == null) { + return Boolean.FALSE; + } else { + return super.apply(pLeft, pRight, pContext, pLogger); + } + } + + //------------------------------------- + + /** + * Applies the operator to the given double values + */ + public boolean apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft > pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given long values + */ + public boolean apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft > pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given String values + */ + public boolean apply(String pLeft, + String pRight, + Logger pLogger) { + return pLeft.compareTo(pRight) > 0; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOrEqualsOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOrEqualsOperator.java new file mode 100644 index 000000000..05c2a5196 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/GreaterThanOrEqualsOperator.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the greater than or equals operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class GreaterThanOrEqualsOperator + extends RelationalOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final GreaterThanOrEqualsOperator SINGLETON = + new GreaterThanOrEqualsOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public GreaterThanOrEqualsOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return ">="; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == pRight) { + return Boolean.TRUE; + } else if (pLeft == null || + pRight == null) { + return Boolean.FALSE; + } else { + return super.apply(pLeft, pRight, pContext, pLogger); + } + } + + //------------------------------------- + + /** + * Applies the operator to the given double values + */ + public boolean apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft >= pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given long values + */ + public boolean apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft >= pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given String values + */ + public boolean apply(String pLeft, + String pRight, + Logger pLogger) { + return pLeft.compareTo(pRight) >= 0; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ImplicitObjects.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ImplicitObjects.java new file mode 100644 index 000000000..8bb6cee02 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ImplicitObjects.java @@ -0,0 +1,588 @@ +/* + * 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.taglibs.standard.lang.jstl; + + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.PageContext; + + +/** + *

This class is used to generate the implicit Map and List objects + * that wrap various elements of the PageContext. It also returns the + * correct implicit object for a given implicit object name. + * + * @author Nathan Abramson - Art Technology Group + */ +public class ImplicitObjects +{ + //------------------------------------- + // Constants + //------------------------------------- + + static final String sAttributeName = + "org.apache.taglibs.standard.ImplicitObjects"; + + //------------------------------------- + // Member variables + //------------------------------------- + + PageContext mContext; + + Map mPage; + + Map mRequest; + + Map mSession; + + Map mApplication; + + Map mParam; + + Map mParams; + + Map mHeader; + + Map mHeaders; + + Map mInitParam; + + Map mCookie; + + //------------------------------------- + + /** + * Constructor + */ + public ImplicitObjects(PageContext pContext) + { + mContext = pContext; + } + + //------------------------------------- + + /** + * Finds the ImplicitObjects associated with the PageContext, + * creating it if it doesn't yet exist. + */ + public static ImplicitObjects getImplicitObjects(PageContext pContext) + { + ImplicitObjects objs = + (ImplicitObjects) + pContext.getAttribute(sAttributeName, + PageContext.PAGE_SCOPE); + if (objs == null) { + objs = new ImplicitObjects(pContext); + pContext.setAttribute(sAttributeName, + objs, + PageContext.PAGE_SCOPE); + } + return objs; + } + + //------------------------------------- + + /** + * Returns the Map that "wraps" page-scoped attributes + */ + public Map getPageScopeMap() + { + if (mPage == null) { + mPage = createPageScopeMap(mContext); + } + return mPage; + } + + //------------------------------------- + + /** + * Returns the Map that "wraps" request-scoped attributes + */ + public Map getRequestScopeMap() + { + if (mRequest == null) { + mRequest = createRequestScopeMap(mContext); + } + return mRequest; + } + + //------------------------------------- + + /** + * Returns the Map that "wraps" session-scoped attributes + */ + public Map getSessionScopeMap() + { + if (mSession == null) { + mSession = createSessionScopeMap(mContext); + } + return mSession; + } + + //------------------------------------- + /** + * Returns the Map that "wraps" application-scoped attributes + */ + public Map getApplicationScopeMap() + { + if (mApplication == null) { + mApplication = createApplicationScopeMap(mContext); + } + return mApplication; + } + + //------------------------------------- + + /** + * Returns the Map that maps parameter name to a single parameter + * values. + */ + public Map getParamMap() + { + if (mParam == null) { + mParam = createParamMap(mContext); + } + return mParam; + } + + //------------------------------------- + + /** + * Returns the Map that maps parameter name to an array of parameter + * values. + */ + public Map getParamsMap() + { + if (mParams == null) { + mParams = createParamsMap(mContext); + } + return mParams; + } + + //------------------------------------- + + /** + * Returns the Map that maps header name to a single header + * values. + */ + public Map getHeaderMap() + { + if (mHeader == null) { + mHeader = createHeaderMap(mContext); + } + return mHeader; + } + + //------------------------------------- + + /** + * Returns the Map that maps header name to an array of header + * values. + */ + public Map getHeadersMap() + { + if (mHeaders == null) { + mHeaders = createHeadersMap(mContext); + } + return mHeaders; + } + + //------------------------------------- + + /** + * Returns the Map that maps init parameter name to a single init + * parameter values. + */ + public Map getInitParamMap() + { + if (mInitParam == null) { + mInitParam = createInitParamMap(mContext); + } + return mInitParam; + } + + //------------------------------------- + + /** + * Returns the Map that maps cookie name to the first matching + * Cookie in request.getCookies(). + */ + public Map getCookieMap() + { + if (mCookie == null) { + mCookie = createCookieMap(mContext); + } + return mCookie; + } + + //------------------------------------- + // Methods for generating wrapper maps + //------------------------------------- + + /** + * Creates the Map that "wraps" page-scoped attributes + */ + public static Map createPageScopeMap(PageContext pContext) + { + final PageContext context = pContext; + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return context.getAttributeNamesInScope + (PageContext.PAGE_SCOPE); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return context.getAttribute + ((String) pKey, + PageContext.PAGE_SCOPE); + } else { + return null; + } + } + + public boolean isMutable() + { + return true; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that "wraps" request-scoped attributes + */ + public static Map createRequestScopeMap(PageContext pContext) + { + final PageContext context = pContext; + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return context.getAttributeNamesInScope + (PageContext.REQUEST_SCOPE); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return context.getAttribute + ((String) pKey, + PageContext.REQUEST_SCOPE); + } else { + return null; + } + } + + public boolean isMutable() + { + return true; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that "wraps" session-scoped attributes + */ + public static Map createSessionScopeMap(PageContext pContext) + { + final PageContext context = pContext; + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return context.getAttributeNamesInScope + (PageContext.SESSION_SCOPE); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return context.getAttribute + ((String) pKey, + PageContext.SESSION_SCOPE); + } else { + return null; + } + } + + public boolean isMutable() + { + return true; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that "wraps" application-scoped attributes + */ + public static Map createApplicationScopeMap(PageContext pContext) + { + final PageContext context = pContext; + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return context.getAttributeNamesInScope + (PageContext.APPLICATION_SCOPE); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return context.getAttribute + ((String) pKey, + PageContext.APPLICATION_SCOPE); + } else { + return null; + } + } + + public boolean isMutable() + { + return true; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps parameter name to single parameter + * value. + */ + public static Map createParamMap(PageContext pContext) + { + final HttpServletRequest request = + (HttpServletRequest) pContext.getRequest(); + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return request.getParameterNames(); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return request.getParameter((String) pKey); + } else { + return null; + } + } + + public boolean isMutable() + { + return false; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps parameter name to an array of parameter + * values. + */ + public static Map createParamsMap(PageContext pContext) + { + final HttpServletRequest request = + (HttpServletRequest) pContext.getRequest(); + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return request.getParameterNames(); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return request.getParameterValues((String) pKey); + } else { + return null; + } + } + + public boolean isMutable() + { + return false; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps header name to single header + * value. + */ + public static Map createHeaderMap(PageContext pContext) + { + final HttpServletRequest request = + (HttpServletRequest) pContext.getRequest(); + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return request.getHeaderNames(); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return request.getHeader((String) pKey); + } else { + return null; + } + } + + public boolean isMutable() + { + return false; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps header name to an array of header + * values. + */ + public static Map createHeadersMap(PageContext pContext) + { + final HttpServletRequest request = + (HttpServletRequest) pContext.getRequest(); + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return request.getHeaderNames(); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + // Drain the header enumeration + List l = new ArrayList(); + Enumeration enum_ = request.getHeaders((String) pKey); + if (enum_ != null) { + while (enum_.hasMoreElements()) { + l.add(enum_.nextElement()); + } + } + String[] ret = (String[]) l.toArray(new String[l.size()]); + return ret; + } else { + return null; + } + } + + public boolean isMutable() + { + return false; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps init parameter name to single init + * parameter value. + */ + public static Map createInitParamMap(PageContext pContext) + { + final ServletContext context = pContext.getServletContext(); + + return new EnumeratedMap() + { + public Enumeration enumerateKeys() + { + return context.getInitParameterNames(); + } + + public Object getValue(Object pKey) + { + if (pKey instanceof String) { + return context.getInitParameter((String) pKey); + } else { + return null; + } + } + + public boolean isMutable() + { + return false; + } + }; + } + + //------------------------------------- + + /** + * Creates the Map that maps cookie name to the first matching + * Cookie in request.getCookies(). + */ + public static Map createCookieMap(PageContext pContext) + { + // Read all the cookies and construct the entire map + HttpServletRequest request = (HttpServletRequest) pContext.getRequest(); + Cookie[] cookies = request.getCookies(); + Map ret = new HashMap(); + + for (int i = 0; cookies != null && i < cookies.length; i++) { + Cookie cookie = cookies[i]; + if (cookie != null) { + String name = cookie.getName(); + if (!ret.containsKey(name)) { + ret.put(name, cookie); + } + } + } + return ret; + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerDivideOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerDivideOperator.java new file mode 100644 index 000000000..1a2870c5e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerDivideOperator.java @@ -0,0 +1,97 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the integer divide operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class IntegerDivideOperator + extends BinaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final IntegerDivideOperator SINGLETON = + new IntegerDivideOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public IntegerDivideOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "idiv"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == null && + pRight == null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.ARITH_OP_NULL, + getOperatorSymbol()); + } + return PrimitiveObjects.getInteger(0); + } + + long left = + Coercions.coerceToPrimitiveNumber(pLeft, Long.class, pLogger). + longValue(); + long right = + Coercions.coerceToPrimitiveNumber(pRight, Long.class, pLogger). + longValue(); + + try { + return PrimitiveObjects.getLong(left / right); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ARITH_ERROR, + getOperatorSymbol(), + "" + left, + "" + right); + } + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerLiteral.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerLiteral.java new file mode 100644 index 000000000..57cfd2f88 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/IntegerLiteral.java @@ -0,0 +1,59 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

An expression representing an integer literal value. The value + * is stored internally as a long. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class IntegerLiteral + extends Literal { + //------------------------------------- + + /** + * Constructor + */ + public IntegerLiteral(String pToken) { + super(getValueFromToken(pToken)); + } + + //------------------------------------- + + /** + * Parses the given token into the literal value + */ + static Object getValueFromToken(String pToken) { + return new Long(pToken); + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return getValue().toString(); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/JSTLVariableResolver.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/JSTLVariableResolver.java new file mode 100644 index 000000000..b3a64ab98 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/JSTLVariableResolver.java @@ -0,0 +1,95 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import jakarta.servlet.jsp.PageContext; + +/** + *

This is the JSTL-specific implementation of VariableResolver. + * It looks up variable references in the PageContext, and also + * recognizes references to implicit objects. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class JSTLVariableResolver + implements VariableResolver { + //------------------------------------- + + /** + * Resolves the specified variable within the given context. + * Returns null if the variable is not found. + */ + public Object resolveVariable(String pName, + Object pContext) + throws ELException { + PageContext ctx = (PageContext) pContext; + + // Check for implicit objects + if ("pageContext".equals(pName)) { + return ctx; + } else if ("pageScope".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getPageScopeMap(); + } else if ("requestScope".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getRequestScopeMap(); + } else if ("sessionScope".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getSessionScopeMap(); + } else if ("applicationScope".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getApplicationScopeMap(); + } else if ("param".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getParamMap(); + } else if ("paramValues".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getParamsMap(); + } else if ("header".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getHeaderMap(); + } else if ("headerValues".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getHeadersMap(); + } else if ("initParam".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getInitParamMap(); + } else if ("cookie".equals(pName)) { + return ImplicitObjects. + getImplicitObjects(ctx). + getCookieMap(); + } + + // Otherwise, just look it up in the page context + else { + return ctx.findAttribute(pName); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOperator.java new file mode 100644 index 000000000..27a06350c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOperator.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the less than operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class LessThanOperator + extends RelationalOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final LessThanOperator SINGLETON = + new LessThanOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public LessThanOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "<"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == pRight) { + return Boolean.FALSE; + } else if (pLeft == null || + pRight == null) { + return Boolean.FALSE; + } else { + return super.apply(pLeft, pRight, pContext, pLogger); + } + } + + //------------------------------------- + + /** + * Applies the operator to the given double values + */ + public boolean apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft < pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given long values + */ + public boolean apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft < pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given String values + */ + public boolean apply(String pLeft, + String pRight, + Logger pLogger) { + return pLeft.compareTo(pRight) < 0; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOrEqualsOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOrEqualsOperator.java new file mode 100644 index 000000000..07d7a4584 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/LessThanOrEqualsOperator.java @@ -0,0 +1,108 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the less than or equals operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class LessThanOrEqualsOperator + extends RelationalOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final LessThanOrEqualsOperator SINGLETON = + new LessThanOrEqualsOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public LessThanOrEqualsOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "<="; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == pRight) { + return Boolean.TRUE; + } else if (pLeft == null || + pRight == null) { + return Boolean.FALSE; + } else { + return super.apply(pLeft, pRight, pContext, pLogger); + } + } + + //------------------------------------- + + /** + * Applies the operator to the given double values + */ + public boolean apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft <= pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given long values + */ + public boolean apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft <= pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given String values + */ + public boolean apply(String pLeft, + String pRight, + Logger pLogger) { + return pLeft.compareTo(pRight) <= 0; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Literal.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Literal.java new file mode 100644 index 000000000..6bafac798 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Literal.java @@ -0,0 +1,72 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

An expression representing a literal value + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public abstract class Literal + extends Expression { + //------------------------------------- + // Properties + //------------------------------------- + // property value + + Object mValue; + + public Object getValue() { + return mValue; + } + + public void setValue(Object pValue) { + mValue = pValue; + } + + //------------------------------------- + + /** + * Constructor + */ + public Literal(Object pValue) { + mValue = pValue; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Evaluates to the literal value + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + return mValue; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Logger.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Logger.java new file mode 100644 index 000000000..30c2bd50c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/Logger.java @@ -0,0 +1,737 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.io.PrintStream; +import java.text.MessageFormat; + +/** + *

The evaluator may pass an instance of this class to operators + * and expressions during evaluation. They should use this to log any + * warning or error messages that might come up. This allows all of + * our logging policies to be concentrated in one class. + *

Errors are conditions that are severe enough to abort operation. + * Warnings are conditions through which the operation may continue, + * but which should be reported to the developer. + * + * @author Nathan Abramson - Art Technology Group + */ +public class Logger { + //------------------------------------- + // Member variables + //------------------------------------- + + PrintStream mOut; + + //------------------------------------- + + /** + * Constructor + * + * @param pOut the PrintStream to which warnings should be printed + */ + public Logger(PrintStream pOut) { + mOut = pOut; + } + + //------------------------------------- + + /** + * Returns true if the application should even bother to try logging + * a warning. + */ + public boolean isLoggingWarning() { + return false; + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pMessage, + Throwable pRootCause) + throws ELException { + if (isLoggingWarning()) { + if (mOut != null) { + if (pMessage == null) { + mOut.println(pRootCause); + } else if (pRootCause == null) { + mOut.println(pMessage); + } else { + mOut.println(pMessage + ": " + pRootCause); + } + } + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate) + throws ELException { + if (isLoggingWarning()) { + logWarning(pTemplate, null); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(Throwable pRootCause) + throws ELException { + if (isLoggingWarning()) { + logWarning(null, pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0, + Object pArg1) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4, + Object pArg5) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + "" + pArg5, + })); + } + } + + //------------------------------------- + + /** + * Logs a warning + */ + public void logWarning(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4, + Object pArg5) + throws ELException { + if (isLoggingWarning()) { + logWarning + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + "" + pArg5, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Returns true if the application should even bother to try logging + * an error. + */ + public boolean isLoggingError() { + return true; + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pMessage, + Throwable pRootCause) + throws ELException { + if (isLoggingError()) { + if (pMessage == null) { + throw new ELException(pRootCause); + } else if (pRootCause == null) { + throw new ELException(pMessage); + } else { + throw new ELException(pMessage, pRootCause); + } + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate) + throws ELException { + if (isLoggingError()) { + logError(pTemplate, null); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(Throwable pRootCause) + throws ELException { + if (isLoggingError()) { + logError(null, pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0, + Object pArg1) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + }), + pRootCause); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4, + Object pArg5) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + "" + pArg5, + })); + } + } + + //------------------------------------- + + /** + * Logs an error + */ + public void logError(String pTemplate, + Throwable pRootCause, + Object pArg0, + Object pArg1, + Object pArg2, + Object pArg3, + Object pArg4, + Object pArg5) + throws ELException { + if (isLoggingError()) { + logError + (MessageFormat.format + (pTemplate, + new Object[]{ + "" + pArg0, + "" + pArg1, + "" + pArg2, + "" + pArg3, + "" + pArg4, + "" + pArg5, + }), + pRootCause); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MinusOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MinusOperator.java new file mode 100644 index 000000000..e5b57b68c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MinusOperator.java @@ -0,0 +1,77 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the minus operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class MinusOperator + extends ArithmeticOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final MinusOperator SINGLETON = + new MinusOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public MinusOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "-"; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public double apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft - pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public long apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft - pRight; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ModulusOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ModulusOperator.java new file mode 100644 index 000000000..ab9daf438 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ModulusOperator.java @@ -0,0 +1,125 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the modulus operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class ModulusOperator + extends BinaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final ModulusOperator SINGLETON = + new ModulusOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public ModulusOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "%"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + if (pLeft == null && + pRight == null) { + if (pLogger.isLoggingWarning()) { + pLogger.logWarning + (Constants.ARITH_OP_NULL, + getOperatorSymbol()); + } + return PrimitiveObjects.getInteger(0); + } + + if ((pLeft != null && + (Coercions.isFloatingPointType(pLeft) || + Coercions.isFloatingPointString(pLeft))) || + (pRight != null && + (Coercions.isFloatingPointType(pRight) || + Coercions.isFloatingPointString(pRight)))) { + double left = + Coercions.coerceToPrimitiveNumber(pLeft, Double.class, pLogger). + doubleValue(); + double right = + Coercions.coerceToPrimitiveNumber(pRight, Double.class, pLogger). + doubleValue(); + + try { + return PrimitiveObjects.getDouble(left % right); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ARITH_ERROR, + getOperatorSymbol(), + "" + left, + "" + right); + } + return PrimitiveObjects.getInteger(0); + } + } else { + long left = + Coercions.coerceToPrimitiveNumber(pLeft, Long.class, pLogger). + longValue(); + long right = + Coercions.coerceToPrimitiveNumber(pRight, Long.class, pLogger). + longValue(); + + try { + return PrimitiveObjects.getLong(left % right); + } + catch (Exception exc) { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.ARITH_ERROR, + getOperatorSymbol(), + "" + left, + "" + right); + } + return PrimitiveObjects.getInteger(0); + } + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MultiplyOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MultiplyOperator.java new file mode 100644 index 000000000..bbf6a7241 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/MultiplyOperator.java @@ -0,0 +1,77 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the multiply operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class MultiplyOperator + extends ArithmeticOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final MultiplyOperator SINGLETON = + new MultiplyOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public MultiplyOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "*"; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public double apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft * pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public long apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft * pRight; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NamedValue.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NamedValue.java new file mode 100644 index 000000000..8bfdce6a6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NamedValue.java @@ -0,0 +1,86 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

Represents a name that can be used as the first element of a + * value. + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class NamedValue + extends Expression { + //------------------------------------- + // Constants + //------------------------------------- + + //------------------------------------- + // Properties + //------------------------------------- + // property name + + String mName; + + public String getName() { + return mName; + } + + //------------------------------------- + + /** + * Constructor + */ + public NamedValue(String pName) { + mName = pName; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return StringLiteral.toIdentifierToken(mName); + } + + //------------------------------------- + + /** + * Evaluates by looking up the name in the VariableResolver + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + if (pResolver == null) { + return null; + } else { + return pResolver.resolveVariable(mName, pContext); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotEqualsOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotEqualsOperator.java new file mode 100644 index 000000000..a416d808e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotEqualsOperator.java @@ -0,0 +1,66 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the not equals operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class NotEqualsOperator + extends EqualityOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final NotEqualsOperator SINGLETON = + new NotEqualsOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public NotEqualsOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "!="; + } + + //------------------------------------- + + /** + * Applies the operator given the fact that the two elements are + * equal. + */ + public boolean apply(boolean pAreEqual, + Logger pLogger) { + return !pAreEqual; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotOperator.java new file mode 100644 index 000000000..7b770535a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NotOperator.java @@ -0,0 +1,70 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the not operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class NotOperator + extends UnaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final NotOperator SINGLETON = + new NotOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public NotOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "not"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pValue, + Object pContext, + Logger pLogger) + throws ELException { + // Coerce the value to a boolean + boolean val = Coercions.coerceToBoolean(pValue, pLogger).booleanValue(); + + return PrimitiveObjects.getBoolean(!val); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NullLiteral.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NullLiteral.java new file mode 100644 index 000000000..6bbd9ad53 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/NullLiteral.java @@ -0,0 +1,55 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

An expression representing a null literal value + * + * @author Nathan Abramson - Art Technology Group + */ + +public class NullLiteral + extends Literal { + //------------------------------------- + // Member variables + //------------------------------------- + + public static final NullLiteral SINGLETON = new NullLiteral(); + + //------------------------------------- + + /** + * Constructor + */ + public NullLiteral() { + super(null); + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return "null"; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/OrOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/OrOperator.java new file mode 100644 index 000000000..f648cb6e4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/OrOperator.java @@ -0,0 +1,96 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the or operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class OrOperator + extends BinaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final OrOperator SINGLETON = + new OrOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public OrOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "or"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + // Coerce the values to booleans + boolean left = + Coercions.coerceToBoolean(pLeft, pLogger).booleanValue(); + boolean right = + Coercions.coerceToBoolean(pRight, pLogger).booleanValue(); + + return PrimitiveObjects.getBoolean(left || right); + } + + //------------------------------------- + + /** + * Returns true if evaluation is necessary given the specified Left + * value. The And/OrOperators make use of this + */ + public boolean shouldEvaluate(Object pLeft) { + return + (pLeft instanceof Boolean) && + ((Boolean) pLeft).booleanValue() == false; + } + + //------------------------------------- + + /** + * Returns true if the operator expects its arguments to be coerced + * to Booleans. The And/Or operators set this to true. + */ + public boolean shouldCoerceToBoolean() { + return true; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PlusOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PlusOperator.java new file mode 100644 index 000000000..821060a4a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PlusOperator.java @@ -0,0 +1,77 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the plus operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class PlusOperator + extends ArithmeticOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final PlusOperator SINGLETON = + new PlusOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public PlusOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "+"; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public double apply(double pLeft, + double pRight, + Logger pLogger) { + return pLeft + pRight; + } + + //------------------------------------- + + /** + * Applies the operator to the given double values, returning a double + */ + public long apply(long pLeft, + long pRight, + Logger pLogger) { + return pLeft + pRight; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PrimitiveObjects.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PrimitiveObjects.java new file mode 100644 index 000000000..abc39a2f8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PrimitiveObjects.java @@ -0,0 +1,226 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This converts primitive values to their Object counterparts. + * For bytes and chars, values from 0 to 255 are cached. For shorts, + * ints, and longs, values -1000 to 1000 are cached. + * + * @author Nathan Abramson - Art Technology Group + */ + +class PrimitiveObjects { + //------------------------------------- + // Constants + //------------------------------------- + + static int BYTE_LOWER_BOUND = 0; + static int BYTE_UPPER_BOUND = 255; + static int CHARACTER_LOWER_BOUND = 0; + static int CHARACTER_UPPER_BOUND = 255; + static int SHORT_LOWER_BOUND = -1000; + static int SHORT_UPPER_BOUND = 1000; + static int INTEGER_LOWER_BOUND = -1000; + static int INTEGER_UPPER_BOUND = 1000; + static int LONG_LOWER_BOUND = -1000; + static int LONG_UPPER_BOUND = 1000; + + //------------------------------------- + // Member variables + //------------------------------------- + + static Byte[] mBytes = createBytes(); + static Character[] mCharacters = createCharacters(); + static Short[] mShorts = createShorts(); + static Integer[] mIntegers = createIntegers(); + static Long[] mLongs = createLongs(); + + //------------------------------------- + // Getting primitive values + //------------------------------------- + + public static Boolean getBoolean(boolean pValue) { + return + pValue ? + Boolean.TRUE : + Boolean.FALSE; + } + + //------------------------------------- + + public static Byte getByte(byte pValue) { + if (pValue >= BYTE_LOWER_BOUND && + pValue <= BYTE_UPPER_BOUND) { + return mBytes[((int) pValue) - BYTE_LOWER_BOUND]; + } else { + return new Byte(pValue); + } + } + + //------------------------------------- + + public static Character getCharacter(char pValue) { + if (pValue >= CHARACTER_LOWER_BOUND && + pValue <= CHARACTER_UPPER_BOUND) { + return mCharacters[((int) pValue) - CHARACTER_LOWER_BOUND]; + } else { + return new Character(pValue); + } + } + + //------------------------------------- + + public static Short getShort(short pValue) { + if (pValue >= SHORT_LOWER_BOUND && + pValue <= SHORT_UPPER_BOUND) { + return mShorts[((int) pValue) - SHORT_LOWER_BOUND]; + } else { + return new Short(pValue); + } + } + + //------------------------------------- + + public static Integer getInteger(int pValue) { + if (pValue >= INTEGER_LOWER_BOUND && + pValue <= INTEGER_UPPER_BOUND) { + return mIntegers[((int) pValue) - INTEGER_LOWER_BOUND]; + } else { + return new Integer(pValue); + } + } + + //------------------------------------- + + public static Long getLong(long pValue) { + if (pValue >= LONG_LOWER_BOUND && + pValue <= LONG_UPPER_BOUND) { + return mLongs[((int) pValue) - LONG_LOWER_BOUND]; + } else { + return new Long(pValue); + } + } + + //------------------------------------- + + public static Float getFloat(float pValue) { + return new Float(pValue); + } + + //------------------------------------- + + public static Double getDouble(double pValue) { + return new Double(pValue); + } + + //------------------------------------- + // Object class equivalents of primitive classes + //------------------------------------- + + /** + * If the given class is a primitive class, returns the object + * version of that class. Otherwise, the class is just returned. + */ + public static Class getPrimitiveObjectClass(Class pClass) { + if (pClass == Boolean.TYPE) { + return Boolean.class; + } else if (pClass == Byte.TYPE) { + return Byte.class; + } else if (pClass == Short.TYPE) { + return Short.class; + } else if (pClass == Character.TYPE) { + return Character.class; + } else if (pClass == Integer.TYPE) { + return Integer.class; + } else if (pClass == Long.TYPE) { + return Long.class; + } else if (pClass == Float.TYPE) { + return Float.class; + } else if (pClass == Double.TYPE) { + return Double.class; + } else { + return pClass; + } + } + + //------------------------------------- + // Initializing the cached values + //------------------------------------- + + static Byte[] createBytes() { + int len = BYTE_UPPER_BOUND - BYTE_LOWER_BOUND + 1; + Byte[] ret = new Byte[len]; + byte val = (byte) BYTE_LOWER_BOUND; + for (int i = 0; i < len; i++, val++) { + ret[i] = new Byte(val); + } + return ret; + } + + //------------------------------------- + + static Character[] createCharacters() { + int len = CHARACTER_UPPER_BOUND - CHARACTER_LOWER_BOUND + 1; + Character[] ret = new Character[len]; + char val = (char) CHARACTER_LOWER_BOUND; + for (int i = 0; i < len; i++, val++) { + ret[i] = new Character(val); + } + return ret; + } + + //------------------------------------- + + static Short[] createShorts() { + int len = SHORT_UPPER_BOUND - SHORT_LOWER_BOUND + 1; + Short[] ret = new Short[len]; + short val = (short) SHORT_LOWER_BOUND; + for (int i = 0; i < len; i++, val++) { + ret[i] = new Short(val); + } + return ret; + } + + //------------------------------------- + + static Integer[] createIntegers() { + int len = INTEGER_UPPER_BOUND - INTEGER_LOWER_BOUND + 1; + Integer[] ret = new Integer[len]; + int val = (int) INTEGER_LOWER_BOUND; + for (int i = 0; i < len; i++, val++) { + ret[i] = new Integer(val); + } + return ret; + } + + //------------------------------------- + + static Long[] createLongs() { + int len = LONG_UPPER_BOUND - LONG_LOWER_BOUND + 1; + Long[] ret = new Long[len]; + long val = (long) LONG_LOWER_BOUND; + for (int i = 0; i < len; i++, val++) { + ret[i] = new Long(val); + } + return ret; + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PropertySuffix.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PropertySuffix.java new file mode 100644 index 000000000..348f4726b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/PropertySuffix.java @@ -0,0 +1,93 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

Represents an operator that obtains the value of another value's + * property. This is a specialization of ArraySuffix - a.b is + * equivalent to a["b"] + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class PropertySuffix + extends ArraySuffix { + //------------------------------------- + // Properties + //------------------------------------- + // property name + + String mName; + + public String getName() { + return mName; + } + + public void setName(String pName) { + mName = pName; + } + + //------------------------------------- + + /** + * Constructor + */ + public PropertySuffix(String pName) { + super(null); + mName = pName; + } + + //------------------------------------- + + /** + * Gets the value of the index + */ + Object evaluateIndex(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + return mName; + } + + //------------------------------------- + + /** + * Returns the operator symbol + */ + String getOperatorSymbol() { + return "."; + } + + //------------------------------------- + // ValueSuffix methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return "." + StringLiteral.toIdentifierToken(mName); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/RelationalOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/RelationalOperator.java new file mode 100644 index 000000000..6efab3adf --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/RelationalOperator.java @@ -0,0 +1,70 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This is the superclass for all relational operators (except == + * or !=) + * + * @author Nathan Abramson - Art Technology Group + */ + +public abstract class RelationalOperator + extends BinaryOperator { + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pLeft, + Object pRight, + Object pContext, + Logger pLogger) + throws ELException { + return Coercions.applyRelationalOperator(pLeft, pRight, this, pLogger); + } + + //------------------------------------- + + /** + * Applies the operator to the given double values + */ + public abstract boolean apply(double pLeft, + double pRight, + Logger pLogger); + + //------------------------------------- + + /** + * Applies the operator to the given long values + */ + public abstract boolean apply(long pLeft, + long pRight, + Logger pLogger); + + //------------------------------------- + + /** + * Applies the operator to the given String values + */ + public abstract boolean apply(String pLeft, + String pRight, + Logger pLogger); + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/StringLiteral.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/StringLiteral.java new file mode 100644 index 000000000..3940d1063 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/StringLiteral.java @@ -0,0 +1,167 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

An expression representing a String literal value. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class StringLiteral + extends Literal { + //------------------------------------- + + /** + * Constructor + */ + StringLiteral(Object pValue) { + super(pValue); + } + + //------------------------------------- + + /** + * Returns a StringLiteral parsed from the given token (enclosed by + * single or double quotes) + */ + public static StringLiteral fromToken(String pToken) { + return new StringLiteral(getValueFromToken(pToken)); + } + + //------------------------------------- + + /** + * Returns a StringLiteral with the given string value + */ + public static StringLiteral fromLiteralValue(String pValue) { + return new StringLiteral(pValue); + } + + //------------------------------------- + + /** + * Parses the given token into the literal value + */ + public static String getValueFromToken(String pToken) { + StringBuilder buf = new StringBuilder(); + int len = pToken.length() - 1; + boolean escaping = false; + for (int i = 1; i < len; i++) { + char ch = pToken.charAt(i); + if (escaping) { + buf.append(ch); + escaping = false; + } else if (ch == '\\') { + escaping = true; + } else { + buf.append(ch); + } + } + return buf.toString(); + } + + //------------------------------------- + + /** + * Converts the specified value to a String token, using " as the + * enclosing quotes and escaping any characters that need escaping. + */ + public static String toStringToken(String pValue) { + // See if any escaping is needed + if (pValue.indexOf('\"') < 0 && + pValue.indexOf('\\') < 0) { + return "\"" + pValue + "\""; + } + + // Escaping is needed + else { + StringBuilder buf = new StringBuilder(); + buf.append('\"'); + int len = pValue.length(); + for (int i = 0; i < len; i++) { + char ch = pValue.charAt(i); + if (ch == '\\') { + buf.append('\\'); + buf.append('\\'); + } else if (ch == '\"') { + buf.append('\\'); + buf.append('\"'); + } else { + buf.append(ch); + } + } + buf.append('\"'); + return buf.toString(); + } + } + + //------------------------------------- + + /** + * Converts the specified value to an identifier token, escaping it + * as a string literal if necessary. + */ + public static String toIdentifierToken(String pValue) { + // See if it's a valid java identifier + if (isJavaIdentifier(pValue)) { + return pValue; + } + + // Return as a String literal + else { + return toStringToken(pValue); + } + } + + //------------------------------------- + + /** + * Returns true if the specified value is a legal java identifier + */ + static boolean isJavaIdentifier(String pValue) { + int len = pValue.length(); + if (len == 0) { + return false; + } else { + if (!Character.isJavaIdentifierStart(pValue.charAt(0))) { + return false; + } else { + for (int i = 1; i < len; i++) { + if (!Character.isJavaIdentifierPart(pValue.charAt(i))) { + return false; + } + } + return true; + } + } + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + return toStringToken((String) getValue()); + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryMinusOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryMinusOperator.java new file mode 100644 index 000000000..54edcd6d7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryMinusOperator.java @@ -0,0 +1,118 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

The implementation of the unary minus operator + * + * @author Nathan Abramson - Art Technology Group + */ + +public class UnaryMinusOperator + extends UnaryOperator { + //------------------------------------- + // Singleton + //------------------------------------- + + public static final UnaryMinusOperator SINGLETON = + new UnaryMinusOperator(); + + //------------------------------------- + + /** + * Constructor + */ + public UnaryMinusOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public String getOperatorSymbol() { + return "-"; + } + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public Object apply(Object pValue, + Object pContext, + Logger pLogger) + throws ELException { + if (pValue == null) { + /* + if (pLogger.isLoggingWarning ()) { + pLogger.logWarning + (Constants.ARITH_OP_NULL, + getOperatorSymbol ()); + } + */ + return PrimitiveObjects.getInteger(0); + } else if (pValue instanceof String) { + if (Coercions.isFloatingPointString(pValue)) { + double dval = + ((Number) + (Coercions.coerceToPrimitiveNumber + (pValue, Double.class, pLogger))). + doubleValue(); + return PrimitiveObjects.getDouble(-dval); + } else { + long lval = + ((Number) + (Coercions.coerceToPrimitiveNumber + (pValue, Long.class, pLogger))). + longValue(); + return PrimitiveObjects.getLong(-lval); + } + } else if (pValue instanceof Byte) { + return PrimitiveObjects.getByte + ((byte) -(((Byte) pValue).byteValue())); + } else if (pValue instanceof Short) { + return PrimitiveObjects.getShort + ((short) -(((Short) pValue).shortValue())); + } else if (pValue instanceof Integer) { + return PrimitiveObjects.getInteger + ((int) -(((Integer) pValue).intValue())); + } else if (pValue instanceof Long) { + return PrimitiveObjects.getLong + ((long) -(((Long) pValue).longValue())); + } else if (pValue instanceof Float) { + return PrimitiveObjects.getFloat + ((float) -(((Float) pValue).floatValue())); + } else if (pValue instanceof Double) { + return PrimitiveObjects.getDouble + ((double) -(((Double) pValue).doubleValue())); + } else { + if (pLogger.isLoggingError()) { + pLogger.logError + (Constants.UNARY_OP_BAD_TYPE, + getOperatorSymbol(), + pValue.getClass().getName()); + } + return PrimitiveObjects.getInteger(0); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperator.java new file mode 100644 index 000000000..8fe24256d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperator.java @@ -0,0 +1,55 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This is the superclass for all unary operators + * + * @author Nathan Abramson - Art Technology Group + */ + +public abstract class UnaryOperator { + //------------------------------------- + + /** + * Constructor + */ + public UnaryOperator() { + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the symbol representing the operator + */ + public abstract String getOperatorSymbol(); + + //------------------------------------- + + /** + * Applies the operator to the given value + */ + public abstract Object apply(Object pValue, + Object pContext, + Logger pLogger) + throws ELException; + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperatorExpression.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperatorExpression.java new file mode 100644 index 000000000..a4fc419a6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/UnaryOperatorExpression.java @@ -0,0 +1,137 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.List; +import java.util.Map; + +/** + *

An expression representing one or more unary operators on a + * value + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public class UnaryOperatorExpression + extends Expression { + //------------------------------------- + // Properties + //------------------------------------- + // property operator + + UnaryOperator mOperator; + + public UnaryOperator getOperator() { + return mOperator; + } + + public void setOperator(UnaryOperator pOperator) { + mOperator = pOperator; + } + + //------------------------------------- + // property operators + + List mOperators; + + public List getOperators() { + return mOperators; + } + + public void setOperators(List pOperators) { + mOperators = pOperators; + } + + //------------------------------------- + // property expression + + Expression mExpression; + + public Expression getExpression() { + return mExpression; + } + + public void setExpression(Expression pExpression) { + mExpression = pExpression; + } + + //------------------------------------- + + /** + * Constructor + */ + public UnaryOperatorExpression(UnaryOperator pOperator, + List pOperators, + Expression pExpression) { + mOperator = pOperator; + mOperators = pOperators; + mExpression = pExpression; + } + + //------------------------------------- + // Expression methods + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public String getExpressionString() { + StringBuilder buf = new StringBuilder(); + buf.append("("); + if (mOperator != null) { + buf.append(mOperator.getOperatorSymbol()); + buf.append(" "); + } else { + for (int i = 0; i < mOperators.size(); i++) { + UnaryOperator operator = (UnaryOperator) mOperators.get(i); + buf.append(operator.getOperatorSymbol()); + buf.append(" "); + } + } + buf.append(mExpression.getExpressionString()); + buf.append(")"); + return buf.toString(); + } + + //------------------------------------- + + /** + * Evaluates to the literal value + */ + public Object evaluate(Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException { + Object value = mExpression.evaluate(pContext, pResolver, functions, + defaultPrefix, pLogger); + if (mOperator != null) { + value = mOperator.apply(value, pContext, pLogger); + } else { + for (int i = mOperators.size() - 1; i >= 0; i--) { + UnaryOperator operator = (UnaryOperator) mOperators.get(i); + value = operator.apply(value, pContext, pLogger); + } + } + return value; + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ValueSuffix.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ValueSuffix.java new file mode 100644 index 000000000..61d8d6b84 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/ValueSuffix.java @@ -0,0 +1,54 @@ +/* + * 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.taglibs.standard.lang.jstl; + +import java.util.Map; + +/** + *

Represents an element that can appear as a suffix in a complex + * value, such as a property or index operator, or a method call (should + * they ever need to be supported). + * + * @author Nathan Abramson - Art Technology Group + * @author Shawn Bayern + */ + +public abstract class ValueSuffix { + //------------------------------------- + + /** + * Returns the expression in the expression language syntax + */ + public abstract String getExpressionString(); + + //------------------------------------- + + /** + * Evaluates the expression in the given context, operating on the + * given value. + */ + public abstract Object evaluate(Object pValue, + Object pContext, + VariableResolver pResolver, + Map functions, + String defaultPrefix, + Logger pLogger) + throws ELException; + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/VariableResolver.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/VariableResolver.java new file mode 100644 index 000000000..62ebdf847 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/VariableResolver.java @@ -0,0 +1,47 @@ +/* + * 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.taglibs.standard.lang.jstl; + +/** + *

This class is used to customize the way the evaluator resolves + * variable references. For example, instances of this class can + * implement their own variable lookup mechanisms, or introduce the + * notion of "implicit variables" which override any other variables. + * An instance of this class should be passed to the evaluator's + * constructor. + *

Whenever the evaluator is invoked, it is passed a "context" + * Object from the application. For example, in a JSP environment, + * the "context" is a PageContext. That context object is eventually + * passed to this class, so that this class has a context in which to + * resolve variables. + * + * @author Nathan Abramson - Art Technology Group + */ +public interface VariableResolver { + //------------------------------------- + + /** + * Resolves the specified variable within the given context. + * Returns null if the variable is not found. + */ + public Object resolveVariable(String pName, + Object pContext) + throws ELException; + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParser.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParser.java new file mode 100644 index 000000000..c1a140f66 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParser.java @@ -0,0 +1,1205 @@ +/* Generated By:JavaCC: Do not edit this line. ELParser.java */ +package org.apache.taglibs.standard.lang.jstl.parser; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.taglibs.standard.lang.jstl.AndOperator; +import org.apache.taglibs.standard.lang.jstl.ArraySuffix; +import org.apache.taglibs.standard.lang.jstl.BinaryOperator; +import org.apache.taglibs.standard.lang.jstl.BinaryOperatorExpression; +import org.apache.taglibs.standard.lang.jstl.BooleanLiteral; +import org.apache.taglibs.standard.lang.jstl.ComplexValue; +import org.apache.taglibs.standard.lang.jstl.DivideOperator; +import org.apache.taglibs.standard.lang.jstl.EmptyOperator; +import org.apache.taglibs.standard.lang.jstl.EqualsOperator; +import org.apache.taglibs.standard.lang.jstl.Expression; +import org.apache.taglibs.standard.lang.jstl.ExpressionString; +import org.apache.taglibs.standard.lang.jstl.FloatingPointLiteral; +import org.apache.taglibs.standard.lang.jstl.FunctionInvocation; +import org.apache.taglibs.standard.lang.jstl.GreaterThanOperator; +import org.apache.taglibs.standard.lang.jstl.GreaterThanOrEqualsOperator; +import org.apache.taglibs.standard.lang.jstl.IntegerLiteral; +import org.apache.taglibs.standard.lang.jstl.LessThanOperator; +import org.apache.taglibs.standard.lang.jstl.LessThanOrEqualsOperator; +import org.apache.taglibs.standard.lang.jstl.Literal; +import org.apache.taglibs.standard.lang.jstl.MinusOperator; +import org.apache.taglibs.standard.lang.jstl.ModulusOperator; +import org.apache.taglibs.standard.lang.jstl.MultiplyOperator; +import org.apache.taglibs.standard.lang.jstl.NamedValue; +import org.apache.taglibs.standard.lang.jstl.NotEqualsOperator; +import org.apache.taglibs.standard.lang.jstl.NotOperator; +import org.apache.taglibs.standard.lang.jstl.NullLiteral; +import org.apache.taglibs.standard.lang.jstl.OrOperator; +import org.apache.taglibs.standard.lang.jstl.PlusOperator; +import org.apache.taglibs.standard.lang.jstl.PropertySuffix; +import org.apache.taglibs.standard.lang.jstl.StringLiteral; +import org.apache.taglibs.standard.lang.jstl.UnaryMinusOperator; +import org.apache.taglibs.standard.lang.jstl.UnaryOperator; +import org.apache.taglibs.standard.lang.jstl.UnaryOperatorExpression; +import org.apache.taglibs.standard.lang.jstl.ValueSuffix; + +/** + * Generated EL parser. + * + * @author Nathan Abramson + * @author Shawn Bayern + */ + +@SuppressWarnings("all") // Ignore warnings in generated code +public class ELParser implements ELParserConstants { + + public static void main(String args[]) + throws ParseException + { + ELParser parser = new ELParser (System.in); + parser.ExpressionString (); + } + +/***************************************** + * GRAMMAR PRODUCTIONS * + *****************************************/ + +/** + * + * Returns a String if the expression string is a single String, an + * Expression if the expression string is a single Expression, an + * ExpressionString if it's a mixture of both. + **/ + final public Object ExpressionString() throws ParseException { + Object ret = ""; + List elems = null; + Object elem; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NON_EXPRESSION_TEXT: + ret = AttrValueString(); + break; + case START_EXPRESSION: + ret = AttrValueExpression(); + break; + default: + jj_la1[0] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + label_1: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NON_EXPRESSION_TEXT: + case START_EXPRESSION: + ; + break; + default: + jj_la1[1] = jj_gen; + break label_1; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NON_EXPRESSION_TEXT: + elem = AttrValueString(); + break; + case START_EXPRESSION: + elem = AttrValueExpression(); + break; + default: + jj_la1[2] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + if (elems == null) { + elems = new ArrayList (); + elems.add (ret); + } + elems.add (elem); + } + if (elems != null) { + ret = new ExpressionString (elems.toArray ()); + } + {if (true) return ret;} + throw new Error("Missing return statement in function"); + } + + final public String AttrValueString() throws ParseException { + Token t; + t = jj_consume_token(NON_EXPRESSION_TEXT); + {if (true) return t.image;} + throw new Error("Missing return statement in function"); + } + + final public Expression AttrValueExpression() throws ParseException { + Expression exp; + jj_consume_token(START_EXPRESSION); + exp = Expression(); + jj_consume_token(END_EXPRESSION); + {if (true) return exp;} + throw new Error("Missing return statement in function"); + } + + final public Expression Expression() throws ParseException { + Expression ret; + ret = OrExpression(); + {if (true) return ret;} + throw new Error("Missing return statement in function"); + } + + final public Expression OrExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = AndExpression(); + label_2: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case OR1: + case OR2: + ; + break; + default: + jj_la1[3] = jj_gen; + break label_2; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case OR1: + jj_consume_token(OR1); + break; + case OR2: + jj_consume_token(OR2); + break; + default: + jj_la1[4] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = OrOperator.SINGLETON; + expression = AndExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression AndExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = EqualityExpression(); + label_3: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case AND1: + case AND2: + ; + break; + default: + jj_la1[5] = jj_gen; + break label_3; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case AND1: + jj_consume_token(AND1); + break; + case AND2: + jj_consume_token(AND2); + break; + default: + jj_la1[6] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = AndOperator.SINGLETON; + expression = EqualityExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression EqualityExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = RelationalExpression(); + label_4: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ1: + case EQ2: + case NE1: + case NE2: + ; + break; + default: + jj_la1[7] = jj_gen; + break label_4; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ1: + case EQ2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case EQ1: + jj_consume_token(EQ1); + break; + case EQ2: + jj_consume_token(EQ2); + break; + default: + jj_la1[8] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = EqualsOperator.SINGLETON; + break; + case NE1: + case NE2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NE1: + jj_consume_token(NE1); + break; + case NE2: + jj_consume_token(NE2); + break; + default: + jj_la1[9] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = NotEqualsOperator.SINGLETON; + break; + default: + jj_la1[10] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + expression = RelationalExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression RelationalExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = AddExpression(); + label_5: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case GT1: + case GT2: + case LT1: + case LT2: + case LE1: + case LE2: + case GE1: + case GE2: + ; + break; + default: + jj_la1[11] = jj_gen; + break label_5; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LT1: + case LT2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LT1: + jj_consume_token(LT1); + break; + case LT2: + jj_consume_token(LT2); + break; + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = LessThanOperator.SINGLETON; + break; + case GT1: + case GT2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case GT1: + jj_consume_token(GT1); + break; + case GT2: + jj_consume_token(GT2); + break; + default: + jj_la1[13] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = GreaterThanOperator.SINGLETON; + break; + case GE1: + case GE2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case GE1: + jj_consume_token(GE1); + break; + case GE2: + jj_consume_token(GE2); + break; + default: + jj_la1[14] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = GreaterThanOrEqualsOperator.SINGLETON; + break; + case LE1: + case LE2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case LE1: + jj_consume_token(LE1); + break; + case LE2: + jj_consume_token(LE2); + break; + default: + jj_la1[15] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = LessThanOrEqualsOperator.SINGLETON; + break; + default: + jj_la1[16] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + expression = AddExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression AddExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = MultiplyExpression(); + label_6: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + case MINUS: + ; + break; + default: + jj_la1[17] = jj_gen; + break label_6; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case PLUS: + jj_consume_token(PLUS); + operator = PlusOperator.SINGLETON; + break; + case MINUS: + jj_consume_token(MINUS); + operator = MinusOperator.SINGLETON; + break; + default: + jj_la1[18] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + expression = MultiplyExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression MultiplyExpression() throws ParseException { + Expression startExpression; + BinaryOperator operator; + Expression expression; + List operators = null; + List expressions = null; + startExpression = UnaryExpression(); + label_7: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case MULTIPLY: + case DIVIDE1: + case DIVIDE2: + case MODULUS1: + case MODULUS2: + ; + break; + default: + jj_la1[19] = jj_gen; + break label_7; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case MULTIPLY: + jj_consume_token(MULTIPLY); + operator = MultiplyOperator.SINGLETON; + break; + case DIVIDE1: + case DIVIDE2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DIVIDE1: + jj_consume_token(DIVIDE1); + break; + case DIVIDE2: + jj_consume_token(DIVIDE2); + break; + default: + jj_la1[20] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = DivideOperator.SINGLETON; + break; + case MODULUS1: + case MODULUS2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case MODULUS1: + jj_consume_token(MODULUS1); + break; + case MODULUS2: + jj_consume_token(MODULUS2); + break; + default: + jj_la1[21] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = ModulusOperator.SINGLETON; + break; + default: + jj_la1[22] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + expression = UnaryExpression(); + if (operators == null) { + operators = new ArrayList (); + expressions = new ArrayList (); + } + operators.add (operator); + expressions.add (expression); + } + if (operators != null) { + {if (true) return new BinaryOperatorExpression (startExpression, + operators, + expressions);} + } + else { + {if (true) return startExpression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression UnaryExpression() throws ParseException { + Expression expression; + UnaryOperator singleOperator = null; + UnaryOperator operator; + List operators = null; + label_8: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case MINUS: + case NOT1: + case NOT2: + case EMPTY: + ; + break; + default: + jj_la1[23] = jj_gen; + break label_8; + } + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NOT1: + case NOT2: + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case NOT1: + jj_consume_token(NOT1); + break; + case NOT2: + jj_consume_token(NOT2); + break; + default: + jj_la1[24] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + operator = NotOperator.SINGLETON; + break; + case MINUS: + jj_consume_token(MINUS); + operator = UnaryMinusOperator.SINGLETON; + break; + case EMPTY: + jj_consume_token(EMPTY); + operator = EmptyOperator.SINGLETON; + break; + default: + jj_la1[25] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + if (singleOperator == null) { + singleOperator = operator; + } + else if (operators == null) { + operators = new ArrayList (); + operators.add (singleOperator); + operators.add (operator); + } + else { + operators.add (operator); + } + } + expression = Value(); + if (operators != null) { + {if (true) return new UnaryOperatorExpression (null, operators, expression);} + } + else if (singleOperator != null) { + {if (true) return new UnaryOperatorExpression (singleOperator, null, expression);} + } + else { + {if (true) return expression;} + } + throw new Error("Missing return statement in function"); + } + + final public Expression Value() throws ParseException { + Expression prefix; + ValueSuffix suffix; + List suffixes = null; + prefix = ValuePrefix(); + label_9: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DOT: + case LBRACKET: + ; + break; + default: + jj_la1[26] = jj_gen; + break label_9; + } + suffix = ValueSuffix(); + if (suffixes == null) { + suffixes = new ArrayList (); + } + suffixes.add (suffix); + } + if (suffixes == null) { + {if (true) return prefix;} + } + else { + {if (true) return new ComplexValue (prefix, suffixes);} + } + throw new Error("Missing return statement in function"); + } + +/** + * This is an element that can start a value + **/ + final public Expression ValuePrefix() throws ParseException { + Expression ret; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case STRING_LITERAL: + case TRUE: + case FALSE: + case NULL: + ret = Literal(); + break; + case LPAREN: + jj_consume_token(LPAREN); + ret = Expression(); + jj_consume_token(RPAREN); + break; + default: + jj_la1[27] = jj_gen; + if (jj_2_1(2147483647)) { + ret = FunctionInvocation(); + } else { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case IDENTIFIER: + ret = NamedValue(); + break; + default: + jj_la1[28] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + } + } + {if (true) return ret;} + throw new Error("Missing return statement in function"); + } + + final public NamedValue NamedValue() throws ParseException { + Token t; + t = jj_consume_token(IDENTIFIER); + {if (true) return new NamedValue (t.image);} + throw new Error("Missing return statement in function"); + } + + final public FunctionInvocation FunctionInvocation() throws ParseException { + String qualifiedName; + List argumentList = new ArrayList(); + Expression exp; + qualifiedName = QualifiedName(); + jj_consume_token(LPAREN); + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case INTEGER_LITERAL: + case FLOATING_POINT_LITERAL: + case STRING_LITERAL: + case TRUE: + case FALSE: + case NULL: + case LPAREN: + case MINUS: + case NOT1: + case NOT2: + case EMPTY: + case IDENTIFIER: + exp = Expression(); + argumentList.add(exp); + label_10: + while (true) { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case COMMA: + ; + break; + default: + jj_la1[29] = jj_gen; + break label_10; + } + jj_consume_token(COMMA); + exp = Expression(); + argumentList.add(exp); + } + break; + default: + jj_la1[30] = jj_gen; + ; + } + jj_consume_token(RPAREN); + String allowed = System.getProperty("jakarta.servlet.jsp.functions.allowed"); + if (allowed == null || !allowed.equalsIgnoreCase("true")) + {if (true) throw new ParseException("EL functions are not supported.");} + {if (true) return new FunctionInvocation(qualifiedName, argumentList);} + throw new Error("Missing return statement in function"); + } + + final public ValueSuffix ValueSuffix() throws ParseException { + ValueSuffix suffix; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case DOT: + suffix = PropertySuffix(); + break; + case LBRACKET: + suffix = ArraySuffix(); + break; + default: + jj_la1[31] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + {if (true) return suffix;} + throw new Error("Missing return statement in function"); + } + + final public PropertySuffix PropertySuffix() throws ParseException { + Token t; + String property; + jj_consume_token(DOT); + property = Identifier(); + {if (true) return new PropertySuffix (property);} + throw new Error("Missing return statement in function"); + } + + final public ArraySuffix ArraySuffix() throws ParseException { + Expression index; + jj_consume_token(LBRACKET); + index = Expression(); + jj_consume_token(RBRACKET); + {if (true) return new ArraySuffix (index);} + throw new Error("Missing return statement in function"); + } + + final public Literal Literal() throws ParseException { + Literal ret; + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TRUE: + case FALSE: + ret = BooleanLiteral(); + break; + case INTEGER_LITERAL: + ret = IntegerLiteral(); + break; + case FLOATING_POINT_LITERAL: + ret = FloatingPointLiteral(); + break; + case STRING_LITERAL: + ret = StringLiteral(); + break; + case NULL: + ret = NullLiteral(); + break; + default: + jj_la1[32] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + {if (true) return ret;} + throw new Error("Missing return statement in function"); + } + + final public BooleanLiteral BooleanLiteral() throws ParseException { + switch ((jj_ntk==-1)?jj_ntk():jj_ntk) { + case TRUE: + jj_consume_token(TRUE); + {if (true) return BooleanLiteral.TRUE;} + break; + case FALSE: + jj_consume_token(FALSE); + {if (true) return BooleanLiteral.FALSE;} + break; + default: + jj_la1[33] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); + } + + final public StringLiteral StringLiteral() throws ParseException { + Token t; + t = jj_consume_token(STRING_LITERAL); + {if (true) return StringLiteral.fromToken (t.image);} + throw new Error("Missing return statement in function"); + } + + final public IntegerLiteral IntegerLiteral() throws ParseException { + Token t; + t = jj_consume_token(INTEGER_LITERAL); + {if (true) return new IntegerLiteral (t.image);} + throw new Error("Missing return statement in function"); + } + + final public FloatingPointLiteral FloatingPointLiteral() throws ParseException { + Token t; + t = jj_consume_token(FLOATING_POINT_LITERAL); + {if (true) return new FloatingPointLiteral (t.image);} + throw new Error("Missing return statement in function"); + } + + final public NullLiteral NullLiteral() throws ParseException { + jj_consume_token(NULL); + {if (true) return NullLiteral.SINGLETON;} + throw new Error("Missing return statement in function"); + } + + final public String Identifier() throws ParseException { + Token t; + t = jj_consume_token(IDENTIFIER); + {if (true) return t.image;} + throw new Error("Missing return statement in function"); + } + + final public String QualifiedName() throws ParseException { + String prefix = null, localPart = null; + if (jj_2_2(2147483647)) { + prefix = Identifier(); + jj_consume_token(COLON); + } else { + ; + } + localPart = Identifier(); + if (prefix == null) + {if (true) return localPart;} + else + {if (true) return prefix + ":" + localPart;} + throw new Error("Missing return statement in function"); + } + + final private boolean jj_2_1(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + boolean retval = !jj_3_1(); + jj_save(0, xla); + return retval; + } + + final private boolean jj_2_2(int xla) { + jj_la = xla; jj_lastpos = jj_scanpos = token; + boolean retval = !jj_3_2(); + jj_save(1, xla); + return retval; + } + + final private boolean jj_3R_13() { + if (jj_3R_12()) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + if (jj_scan_token(COLON)) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + return false; + } + + final private boolean jj_3_2() { + if (jj_3R_12()) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + if (jj_scan_token(COLON)) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + return false; + } + + final private boolean jj_3_1() { + if (jj_3R_11()) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + if (jj_scan_token(LPAREN)) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + return false; + } + + final private boolean jj_3R_12() { + if (jj_scan_token(IDENTIFIER)) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + return false; + } + + final private boolean jj_3R_11() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_13()) jj_scanpos = xsp; + else if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + if (jj_3R_12()) return true; + if (jj_la == 0 && jj_scanpos == jj_lastpos) return false; + return false; + } + + public ELParserTokenManager token_source; + SimpleCharStream jj_input_stream; + public Token token, jj_nt; + private int jj_ntk; + private Token jj_scanpos, jj_lastpos; + private int jj_la; + public boolean lookingAhead = false; + private boolean jj_semLA; + private int jj_gen; + final private int[] jj_la1 = new int[34]; + final private int[] jj_la1_0 = {0x6,0x6,0x6,0x0,0x0,0x0,0x0,0x18600000,0x600000,0x18000000,0x18600000,0x79e0000,0x180000,0x60000,0x6000000,0x1800000,0x79e0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10000,0x20007580,0x0,0x80000000,0x20007580,0x10000,0x7580,0x3000,}; + final private int[] jj_la1_1 = {0x0,0x0,0x0,0xc000,0xc000,0x3000,0x3000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18,0x18,0x3e0,0xc0,0x300,0x3e0,0x10c10,0xc00,0x10c10,0x2,0x0,0x20000,0x0,0x30c10,0x2,0x0,0x0,}; + final private JJCalls[] jj_2_rtns = new JJCalls[2]; + private boolean jj_rescan = false; + private int jj_gc = 0; + + public ELParser(java.io.InputStream stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new ELParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + public void ReInit(java.io.InputStream stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + public ELParser(java.io.Reader stream) { + jj_input_stream = new SimpleCharStream(stream, 1, 1); + token_source = new ELParserTokenManager(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + public void ReInit(java.io.Reader stream) { + jj_input_stream.ReInit(stream, 1, 1); + token_source.ReInit(jj_input_stream); + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + public ELParser(ELParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + public void ReInit(ELParserTokenManager tm) { + token_source = tm; + token = new Token(); + jj_ntk = -1; + jj_gen = 0; + for (int i = 0; i < 34; i++) jj_la1[i] = -1; + for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); + } + + final private Token jj_consume_token(int kind) throws ParseException { + Token oldToken; + if ((oldToken = token).next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + if (token.kind == kind) { + jj_gen++; + if (++jj_gc > 100) { + jj_gc = 0; + for (int i = 0; i < jj_2_rtns.length; i++) { + JJCalls c = jj_2_rtns[i]; + while (c != null) { + if (c.gen < jj_gen) c.first = null; + c = c.next; + } + } + } + return token; + } + token = oldToken; + jj_kind = kind; + throw generateParseException(); + } + + final private boolean jj_scan_token(int kind) { + if (jj_scanpos == jj_lastpos) { + jj_la--; + if (jj_scanpos.next == null) { + jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); + } else { + jj_lastpos = jj_scanpos = jj_scanpos.next; + } + } else { + jj_scanpos = jj_scanpos.next; + } + if (jj_rescan) { + int i = 0; Token tok = token; + while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } + if (tok != null) jj_add_error_token(kind, i); + } + return (jj_scanpos.kind != kind); + } + + final public Token getNextToken() { + if (token.next != null) token = token.next; + else token = token.next = token_source.getNextToken(); + jj_ntk = -1; + jj_gen++; + return token; + } + + final public Token getToken(int index) { + Token t = lookingAhead ? jj_scanpos : token; + for (int i = 0; i < index; i++) { + if (t.next != null) t = t.next; + else t = t.next = token_source.getNextToken(); + } + return t; + } + + final private int jj_ntk() { + if ((jj_nt=token.next) == null) + return (jj_ntk = (token.next=token_source.getNextToken()).kind); + else + return (jj_ntk = jj_nt.kind); + } + + private java.util.Vector jj_expentries = new java.util.Vector(); + private int[] jj_expentry; + private int jj_kind = -1; + private int[] jj_lasttokens = new int[100]; + private int jj_endpos; + + private void jj_add_error_token(int kind, int pos) { + if (pos >= 100) return; + if (pos == jj_endpos + 1) { + jj_lasttokens[jj_endpos++] = kind; + } else if (jj_endpos != 0) { + jj_expentry = new int[jj_endpos]; + for (int i = 0; i < jj_endpos; i++) { + jj_expentry[i] = jj_lasttokens[i]; + } + boolean exists = false; + for (java.util.Enumeration enum_ = jj_expentries.elements(); enum_.hasMoreElements();) { + int[] oldentry = (int[])(enum_.nextElement()); + if (oldentry.length == jj_expentry.length) { + exists = true; + for (int i = 0; i < jj_expentry.length; i++) { + if (oldentry[i] != jj_expentry[i]) { + exists = false; + break; + } + } + if (exists) break; + } + } + if (!exists) jj_expentries.addElement(jj_expentry); + if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind; + } + } + + final public ParseException generateParseException() { + jj_expentries.removeAllElements(); + boolean[] la1tokens = new boolean[54]; + for (int i = 0; i < 54; i++) { + la1tokens[i] = false; + } + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 34; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1< jj_gen) { + jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; + switch (i) { + case 0: jj_3_1(); break; + case 1: jj_3_2(); break; + } + } + p = p.next; + } while (p != null); + } + jj_rescan = false; + } + + final private void jj_save(int index, int xla) { + JJCalls p = jj_2_rtns[index]; + while (p.gen > jj_gen) { + if (p.next == null) { p = p.next = new JJCalls(); break; } + p = p.next; + } + p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; + } + + static final class JJCalls { + int gen; + Token first; + int arg; + JJCalls next; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserConstants.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserConstants.java new file mode 100644 index 000000000..b6b38ff41 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserConstants.java @@ -0,0 +1,118 @@ +/* Generated By:JavaCC: Do not edit this line. ELParserConstants.java */ +package org.apache.taglibs.standard.lang.jstl.parser; + +@SuppressWarnings("all") // Ignore warnings in generated code +public interface ELParserConstants { + + int EOF = 0; + int NON_EXPRESSION_TEXT = 1; + int START_EXPRESSION = 2; + int INTEGER_LITERAL = 7; + int FLOATING_POINT_LITERAL = 8; + int EXPONENT = 9; + int STRING_LITERAL = 10; + int BADLY_ESCAPED_STRING_LITERAL = 11; + int TRUE = 12; + int FALSE = 13; + int NULL = 14; + int END_EXPRESSION = 15; + int DOT = 16; + int GT1 = 17; + int GT2 = 18; + int LT1 = 19; + int LT2 = 20; + int EQ1 = 21; + int EQ2 = 22; + int LE1 = 23; + int LE2 = 24; + int GE1 = 25; + int GE2 = 26; + int NE1 = 27; + int NE2 = 28; + int LPAREN = 29; + int RPAREN = 30; + int COMMA = 31; + int COLON = 32; + int LBRACKET = 33; + int RBRACKET = 34; + int PLUS = 35; + int MINUS = 36; + int MULTIPLY = 37; + int DIVIDE1 = 38; + int DIVIDE2 = 39; + int MODULUS1 = 40; + int MODULUS2 = 41; + int NOT1 = 42; + int NOT2 = 43; + int AND1 = 44; + int AND2 = 45; + int OR1 = 46; + int OR2 = 47; + int EMPTY = 48; + int IDENTIFIER = 49; + int IMPL_OBJ_START = 50; + int LETTER = 51; + int DIGIT = 52; + int ILLEGAL_CHARACTER = 53; + + int DEFAULT = 0; + int IN_EXPRESSION = 1; + + String[] tokenImage = { + "", + "", + "\"${\"", + "\" \"", + "\"\\t\"", + "\"\\n\"", + "\"\\r\"", + "", + "", + "", + "", + "", + "\"true\"", + "\"false\"", + "\"null\"", + "\"}\"", + "\".\"", + "\">\"", + "\"gt\"", + "\"<\"", + "\"lt\"", + "\"==\"", + "\"eq\"", + "\"<=\"", + "\"le\"", + "\">=\"", + "\"ge\"", + "\"!=\"", + "\"ne\"", + "\"(\"", + "\")\"", + "\",\"", + "\":\"", + "\"[\"", + "\"]\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"div\"", + "\"%\"", + "\"mod\"", + "\"not\"", + "\"!\"", + "\"and\"", + "\"&&\"", + "\"or\"", + "\"||\"", + "\"empty\"", + "", + "\"#\"", + "", + "", + "", + }; + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserTokenManager.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserTokenManager.java new file mode 100644 index 000000000..1f2f0a9db --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ELParserTokenManager.java @@ -0,0 +1,1042 @@ +/* Generated By:JavaCC: Do not edit this line. ELParserTokenManager.java */ +package org.apache.taglibs.standard.lang.jstl.parser; + +@SuppressWarnings("all") // Ignore warnings in generated code +public class ELParserTokenManager implements ELParserConstants +{ + public java.io.PrintStream debugStream = System.out; + public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private final int jjStopStringLiteralDfa_0(int pos, long active0) +{ + switch (pos) + { + case 0: + if ((active0 & 0x4L) != 0L) + { + jjmatchedKind = 1; + return 2; + } + return -1; + default : + return -1; + } +} +private final int jjStartNfa_0(int pos, long active0) +{ + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); +} +private final int jjStopAtPos(int pos, int kind) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; +} +private final int jjStartNfaWithStates_0(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_0(state, pos + 1); +} +private final int jjMoveStringLiteralDfa0_0() +{ + switch(curChar) + { + case 36: + return jjMoveStringLiteralDfa1_0(0x4L); + default : + return jjMoveNfa_0(1, 0); + } +} +private final int jjMoveStringLiteralDfa1_0(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0); + return 1; + } + switch(curChar) + { + case 123: + if ((active0 & 0x4L) != 0L) + return jjStopAtPos(1, 2); + break; + default : + break; + } + return jjStartNfa_0(0, active0); +} +private final void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +private final void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +private final void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} +private final void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} +private final void jjCheckNAddStates(int start) +{ + jjCheckNAdd(jjnextStates[start]); + jjCheckNAdd(jjnextStates[start + 1]); +} +static final long[] jjbitVec0 = { + 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec2 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +private final int jjMoveNfa_0(int startState, int curPos) +{ + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 3; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 1: + if ((0xffffffefffffffffL & l) != 0L) + { + if (kind > 1) + kind = 1; + jjCheckNAdd(0); + } + else if (curChar == 36) + { + if (kind > 1) + kind = 1; + jjCheckNAdd(2); + } + break; + case 0: + if ((0xffffffefffffffffL & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(0); + break; + case 2: + if ((0xffffffefffffffffL & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(2); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 1: + case 0: + if (kind > 1) + kind = 1; + jjCheckNAdd(0); + break; + case 2: + if ((0xf7ffffffffffffffL & l) == 0L) + break; + if (kind > 1) + kind = 1; + jjstateSet[jjnewStateCnt++] = 2; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 1: + case 0: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 1) + kind = 1; + jjCheckNAdd(0); + break; + case 2: + if (!jjCanMove_0(hiByte, i1, i2, l1, l2)) + break; + if (kind > 1) + kind = 1; + jjstateSet[jjnewStateCnt++] = 2; + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +private final int jjStopStringLiteralDfa_1(int pos, long active0) +{ + switch (pos) + { + case 0: + if ((active0 & 0x1568015547000L) != 0L) + { + jjmatchedKind = 49; + return 6; + } + if ((active0 & 0x10000L) != 0L) + return 1; + return -1; + case 1: + if ((active0 & 0x400015540000L) != 0L) + return 6; + if ((active0 & 0x1168000007000L) != 0L) + { + jjmatchedKind = 49; + jjmatchedPos = 1; + return 6; + } + return -1; + case 2: + if ((active0 & 0x168000000000L) != 0L) + return 6; + if ((active0 & 0x1000000007000L) != 0L) + { + jjmatchedKind = 49; + jjmatchedPos = 2; + return 6; + } + return -1; + case 3: + if ((active0 & 0x5000L) != 0L) + return 6; + if ((active0 & 0x1000000002000L) != 0L) + { + jjmatchedKind = 49; + jjmatchedPos = 3; + return 6; + } + return -1; + default : + return -1; + } +} +private final int jjStartNfa_1(int pos, long active0) +{ + return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1); +} +private final int jjStartNfaWithStates_1(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_1(state, pos + 1); +} +private final int jjMoveStringLiteralDfa0_1() +{ + switch(curChar) + { + case 33: + jjmatchedKind = 43; + return jjMoveStringLiteralDfa1_1(0x8000000L); + case 37: + return jjStopAtPos(0, 40); + case 38: + return jjMoveStringLiteralDfa1_1(0x200000000000L); + case 40: + return jjStopAtPos(0, 29); + case 41: + return jjStopAtPos(0, 30); + case 42: + return jjStopAtPos(0, 37); + case 43: + return jjStopAtPos(0, 35); + case 44: + return jjStopAtPos(0, 31); + case 45: + return jjStopAtPos(0, 36); + case 46: + return jjStartNfaWithStates_1(0, 16, 1); + case 47: + return jjStopAtPos(0, 38); + case 58: + return jjStopAtPos(0, 32); + case 60: + jjmatchedKind = 19; + return jjMoveStringLiteralDfa1_1(0x800000L); + case 61: + return jjMoveStringLiteralDfa1_1(0x200000L); + case 62: + jjmatchedKind = 17; + return jjMoveStringLiteralDfa1_1(0x2000000L); + case 91: + return jjStopAtPos(0, 33); + case 93: + return jjStopAtPos(0, 34); + case 97: + return jjMoveStringLiteralDfa1_1(0x100000000000L); + case 100: + return jjMoveStringLiteralDfa1_1(0x8000000000L); + case 101: + return jjMoveStringLiteralDfa1_1(0x1000000400000L); + case 102: + return jjMoveStringLiteralDfa1_1(0x2000L); + case 103: + return jjMoveStringLiteralDfa1_1(0x4040000L); + case 108: + return jjMoveStringLiteralDfa1_1(0x1100000L); + case 109: + return jjMoveStringLiteralDfa1_1(0x20000000000L); + case 110: + return jjMoveStringLiteralDfa1_1(0x40010004000L); + case 111: + return jjMoveStringLiteralDfa1_1(0x400000000000L); + case 116: + return jjMoveStringLiteralDfa1_1(0x1000L); + case 124: + return jjMoveStringLiteralDfa1_1(0x800000000000L); + case 125: + return jjStopAtPos(0, 15); + default : + return jjMoveNfa_1(0, 0); + } +} +private final int jjMoveStringLiteralDfa1_1(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_1(0, active0); + return 1; + } + switch(curChar) + { + case 38: + if ((active0 & 0x200000000000L) != 0L) + return jjStopAtPos(1, 45); + break; + case 61: + if ((active0 & 0x200000L) != 0L) + return jjStopAtPos(1, 21); + else if ((active0 & 0x800000L) != 0L) + return jjStopAtPos(1, 23); + else if ((active0 & 0x2000000L) != 0L) + return jjStopAtPos(1, 25); + else if ((active0 & 0x8000000L) != 0L) + return jjStopAtPos(1, 27); + break; + case 97: + return jjMoveStringLiteralDfa2_1(active0, 0x2000L); + case 101: + if ((active0 & 0x1000000L) != 0L) + return jjStartNfaWithStates_1(1, 24, 6); + else if ((active0 & 0x4000000L) != 0L) + return jjStartNfaWithStates_1(1, 26, 6); + else if ((active0 & 0x10000000L) != 0L) + return jjStartNfaWithStates_1(1, 28, 6); + break; + case 105: + return jjMoveStringLiteralDfa2_1(active0, 0x8000000000L); + case 109: + return jjMoveStringLiteralDfa2_1(active0, 0x1000000000000L); + case 110: + return jjMoveStringLiteralDfa2_1(active0, 0x100000000000L); + case 111: + return jjMoveStringLiteralDfa2_1(active0, 0x60000000000L); + case 113: + if ((active0 & 0x400000L) != 0L) + return jjStartNfaWithStates_1(1, 22, 6); + break; + case 114: + if ((active0 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_1(1, 46, 6); + return jjMoveStringLiteralDfa2_1(active0, 0x1000L); + case 116: + if ((active0 & 0x40000L) != 0L) + return jjStartNfaWithStates_1(1, 18, 6); + else if ((active0 & 0x100000L) != 0L) + return jjStartNfaWithStates_1(1, 20, 6); + break; + case 117: + return jjMoveStringLiteralDfa2_1(active0, 0x4000L); + case 124: + if ((active0 & 0x800000000000L) != 0L) + return jjStopAtPos(1, 47); + break; + default : + break; + } + return jjStartNfa_1(0, active0); +} +private final int jjMoveStringLiteralDfa2_1(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_1(0, old0); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_1(1, active0); + return 2; + } + switch(curChar) + { + case 100: + if ((active0 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_1(2, 41, 6); + else if ((active0 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_1(2, 44, 6); + break; + case 108: + return jjMoveStringLiteralDfa3_1(active0, 0x6000L); + case 112: + return jjMoveStringLiteralDfa3_1(active0, 0x1000000000000L); + case 116: + if ((active0 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_1(2, 42, 6); + break; + case 117: + return jjMoveStringLiteralDfa3_1(active0, 0x1000L); + case 118: + if ((active0 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_1(2, 39, 6); + break; + default : + break; + } + return jjStartNfa_1(1, active0); +} +private final int jjMoveStringLiteralDfa3_1(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_1(1, old0); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_1(2, active0); + return 3; + } + switch(curChar) + { + case 101: + if ((active0 & 0x1000L) != 0L) + return jjStartNfaWithStates_1(3, 12, 6); + break; + case 108: + if ((active0 & 0x4000L) != 0L) + return jjStartNfaWithStates_1(3, 14, 6); + break; + case 115: + return jjMoveStringLiteralDfa4_1(active0, 0x2000L); + case 116: + return jjMoveStringLiteralDfa4_1(active0, 0x1000000000000L); + default : + break; + } + return jjStartNfa_1(2, active0); +} +private final int jjMoveStringLiteralDfa4_1(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return jjStartNfa_1(2, old0); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_1(3, active0); + return 4; + } + switch(curChar) + { + case 101: + if ((active0 & 0x2000L) != 0L) + return jjStartNfaWithStates_1(4, 13, 6); + break; + case 121: + if ((active0 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_1(4, 48, 6); + break; + default : + break; + } + return jjStartNfa_1(3, active0); +} +static final long[] jjbitVec3 = { + 0x1ff00000fffffffeL, 0xffffffffffffc000L, 0xffffffffL, 0x600000000000000L +}; +static final long[] jjbitVec4 = { + 0x0L, 0x0L, 0x0L, 0xff7fffffff7fffffL +}; +static final long[] jjbitVec5 = { + 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static final long[] jjbitVec6 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffL, 0x0L +}; +static final long[] jjbitVec7 = { + 0xffffffffffffffffL, 0xffffffffffffffffL, 0x0L, 0x0L +}; +static final long[] jjbitVec8 = { + 0x3fffffffffffL, 0x0L, 0x0L, 0x0L +}; +private final int jjMoveNfa_1(int startState, int curPos) +{ + int[] nextStates; + int startsAt = 0; + jjnewStateCnt = 35; + int i = 1; + jjstateSet[0] = startState; + int j, kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 0: + if ((0x3ff000000000000L & l) != 0L) + { + if (kind > 7) + kind = 7; + jjCheckNAddStates(0, 4); + } + else if ((0x1800000000L & l) != 0L) + { + if (kind > 49) + kind = 49; + jjCheckNAdd(6); + } + else if (curChar == 39) + jjCheckNAddStates(5, 9); + else if (curChar == 34) + jjCheckNAddStates(10, 14); + else if (curChar == 46) + jjCheckNAdd(1); + break; + case 1: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 8) + kind = 8; + jjCheckNAddTwoStates(1, 2); + break; + case 3: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(4); + break; + case 4: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 8) + kind = 8; + jjCheckNAdd(4); + break; + case 5: + if ((0x1800000000L & l) == 0L) + break; + if (kind > 49) + kind = 49; + jjCheckNAdd(6); + break; + case 6: + if ((0x3ff001000000000L & l) == 0L) + break; + if (kind > 49) + kind = 49; + jjCheckNAdd(6); + break; + case 7: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAddStates(0, 4); + break; + case 8: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 7) + kind = 7; + jjCheckNAdd(8); + break; + case 9: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(9, 10); + break; + case 10: + if (curChar != 46) + break; + if (kind > 8) + kind = 8; + jjCheckNAddTwoStates(11, 12); + break; + case 11: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 8) + kind = 8; + jjCheckNAddTwoStates(11, 12); + break; + case 13: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(14); + break; + case 14: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 8) + kind = 8; + jjCheckNAdd(14); + break; + case 15: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(15, 16); + break; + case 17: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(18); + break; + case 18: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 8) + kind = 8; + jjCheckNAdd(18); + break; + case 19: + if (curChar == 34) + jjCheckNAddStates(10, 14); + break; + case 20: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddStates(15, 17); + break; + case 22: + if (curChar == 34) + jjCheckNAddStates(15, 17); + break; + case 23: + if (curChar == 34 && kind > 10) + kind = 10; + break; + case 24: + if ((0xfffffffbffffffffL & l) != 0L) + jjCheckNAddTwoStates(24, 25); + break; + case 26: + if ((0xfffffffbffffffffL & l) != 0L && kind > 11) + kind = 11; + break; + case 27: + if (curChar == 39) + jjCheckNAddStates(5, 9); + break; + case 28: + if ((0xffffff7fffffffffL & l) != 0L) + jjCheckNAddStates(18, 20); + break; + case 30: + if (curChar == 39) + jjCheckNAddStates(18, 20); + break; + case 31: + if (curChar == 39 && kind > 10) + kind = 10; + break; + case 32: + if ((0xffffff7fffffffffL & l) != 0L) + jjCheckNAddTwoStates(32, 33); + break; + case 34: + if ((0xffffff7fffffffffL & l) != 0L && kind > 11) + kind = 11; + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 0: + case 6: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 49) + kind = 49; + jjCheckNAdd(6); + break; + case 2: + if ((0x2000000020L & l) != 0L) + jjAddStates(21, 22); + break; + case 12: + if ((0x2000000020L & l) != 0L) + jjAddStates(23, 24); + break; + case 16: + if ((0x2000000020L & l) != 0L) + jjAddStates(25, 26); + break; + case 20: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(15, 17); + break; + case 21: + if (curChar == 92) + jjstateSet[jjnewStateCnt++] = 22; + break; + case 22: + if (curChar == 92) + jjCheckNAddStates(15, 17); + break; + case 24: + if ((0xffffffffefffffffL & l) != 0L) + jjAddStates(27, 28); + break; + case 25: + if (curChar == 92) + jjstateSet[jjnewStateCnt++] = 26; + break; + case 26: + case 34: + if ((0xffffffffefffffffL & l) != 0L && kind > 11) + kind = 11; + break; + case 28: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(18, 20); + break; + case 29: + if (curChar == 92) + jjstateSet[jjnewStateCnt++] = 30; + break; + case 30: + if (curChar == 92) + jjCheckNAddStates(18, 20); + break; + case 32: + if ((0xffffffffefffffffL & l) != 0L) + jjAddStates(29, 30); + break; + case 33: + if (curChar == 92) + jjstateSet[jjnewStateCnt++] = 34; + break; + default : break; + } + } while(i != startsAt); + } + else + { + int hiByte = (int)(curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + MatchLoop: do + { + switch(jjstateSet[--i]) + { + case 0: + case 6: + if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) + break; + if (kind > 49) + kind = 49; + jjCheckNAdd(6); + break; + case 20: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(15, 17); + break; + case 24: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(27, 28); + break; + case 26: + case 34: + if (jjCanMove_0(hiByte, i1, i2, l1, l2) && kind > 11) + kind = 11; + break; + case 28: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(18, 20); + break; + case 32: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) + jjAddStates(29, 30); + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 35 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +static final int[] jjnextStates = { + 8, 9, 10, 15, 16, 28, 29, 31, 32, 33, 20, 21, 23, 24, 25, 20, + 21, 23, 28, 29, 31, 3, 4, 13, 14, 17, 18, 24, 25, 32, 33, +}; +private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec2[i2] & l2) != 0L); + default : + if ((jjbitVec0[i1] & l1) != 0L) + return true; + return false; + } +} +private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2) +{ + switch(hiByte) + { + case 0: + return ((jjbitVec4[i2] & l2) != 0L); + case 48: + return ((jjbitVec5[i2] & l2) != 0L); + case 49: + return ((jjbitVec6[i2] & l2) != 0L); + case 51: + return ((jjbitVec7[i2] & l2) != 0L); + case 61: + return ((jjbitVec8[i2] & l2) != 0L); + default : + if ((jjbitVec3[i1] & l1) != 0L) + return true; + return false; + } +} +public static final String[] jjstrLiteralImages = { +"", null, "\44\173", null, null, null, null, null, null, null, null, null, +"\164\162\165\145", "\146\141\154\163\145", "\156\165\154\154", "\175", "\56", "\76", "\147\164", +"\74", "\154\164", "\75\75", "\145\161", "\74\75", "\154\145", "\76\75", "\147\145", +"\41\75", "\156\145", "\50", "\51", "\54", "\72", "\133", "\135", "\53", "\55", "\52", +"\57", "\144\151\166", "\45", "\155\157\144", "\156\157\164", "\41", "\141\156\144", +"\46\46", "\157\162", "\174\174", "\145\155\160\164\171", null, null, null, null, null, }; +public static final String[] lexStateNames = { + "DEFAULT", + "IN_EXPRESSION", +}; +public static final int[] jjnewLexState = { + -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, +}; +static final long[] jjtoToken = { + 0x23fffffffffd87L, +}; +static final long[] jjtoSkip = { + 0x78L, +}; +private SimpleCharStream input_stream; +private final int[] jjrounds = new int[35]; +private final int[] jjstateSet = new int[70]; +protected char curChar; +public ELParserTokenManager(SimpleCharStream stream) +{ + if (SimpleCharStream.staticFlag) + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + input_stream = stream; +} +public ELParserTokenManager(SimpleCharStream stream, int lexState) +{ + this(stream); + SwitchTo(lexState); +} +public void ReInit(SimpleCharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +private final void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 35; i-- > 0;) + jjrounds[i] = 0x80000000; +} +public void ReInit(SimpleCharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} +public void SwitchTo(int lexState) +{ + if (lexState >= 2 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} + +private final Token jjFillToken() +{ + Token t = Token.newToken(jjmatchedKind); + t.kind = jjmatchedKind; + String im = jjstrLiteralImages[jjmatchedKind]; + t.image = (im == null) ? input_stream.GetImage() : im; + t.beginLine = input_stream.getBeginLine(); + t.beginColumn = input_stream.getBeginColumn(); + t.endLine = input_stream.getEndLine(); + t.endColumn = input_stream.getEndColumn(); + return t; +} + +int curLexState = 0; +int defaultLexState = 0; +int jjnewStateCnt; +int jjround; +int jjmatchedPos; +int jjmatchedKind; + +public final Token getNextToken() +{ + int kind; + Token specialToken = null; + Token matchedToken; + int curPos = 0; + + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } + + switch(curLexState) + { + case 0: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + try { input_stream.backup(0); + while (curChar <= 32 && (0x100002600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { continue EOFLoop; } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + if (jjmatchedPos == 0 && jjmatchedKind > 53) + { + jjmatchedKind = 53; + } + break; + } + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } + else + { + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } +} + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ParseException.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ParseException.java new file mode 100644 index 000000000..16ebc59bb --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/ParseException.java @@ -0,0 +1,193 @@ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 2.1 */ +package org.apache.taglibs.standard.lang.jstl.parser; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +@SuppressWarnings("all") // Ignore warnings in generated code +public class ParseException extends Exception { + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. The boolean + * flag "specialConstructor" is also set to true to indicate that + * this constructor was used to create this object. + * This constructor calls its super class with the empty string + * to force the "toString" method of parent class "Throwable" to + * print the error message in the form: + * ParseException: + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) + { + super(""); + specialConstructor = true; + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + specialConstructor = false; + } + + public ParseException(String message) { + super(message); + specialConstructor = false; + } + + /** + * This variable determines which constructor was used to create + * this object and thereby affects the semantics of the + * "getMessage" method (see below). + */ + protected boolean specialConstructor; + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * This method has the standard behavior when this object has been + * created using the standard constructors. Otherwise, it uses + * "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser), then this method is called during the printing + * of the final stack trace, and hence the correct error message + * gets displayed. + */ + public String getMessage() { + if (!specialConstructor) { + return super.getMessage(); + } + String expected = ""; + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected += tokenImage[expectedTokenSequences[i][j]] + " "; + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected += "..."; + } + expected += eol + " "; + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += add_escapes(tok.image); + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected; + return retval; + } + + /** + * The end of line string for this machine. + */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + */ + protected String add_escapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/SimpleCharStream.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/SimpleCharStream.java new file mode 100644 index 000000000..79bfeaf7b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/SimpleCharStream.java @@ -0,0 +1,402 @@ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 2.1 */ +package org.apache.taglibs.standard.lang.jstl.parser; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +@SuppressWarnings("all") // Ignore warnings in generated code +public final class SimpleCharStream +{ + public static final boolean staticFlag = false; + int bufsize; + int available; + int tokenBegin; + public int bufpos = -1; + private int bufline[]; + private int bufcolumn[]; + + private int column = 0; + private int line = 1; + + private boolean prevCharIsCR = false; + private boolean prevCharIsLF = false; + + private java.io.Reader inputStream; + + private char[] buffer; + private int maxNextCharInd = 0; + private int inBuf = 0; + + private final void ExpandBuff(boolean wrapAround) + { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try + { + if (wrapAround) + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } + else + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } + catch (Throwable t) + { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + private final void FillBuff() throws java.io.IOException + { + if (maxNextCharInd == available) + { + if (available == bufsize) + { + if (tokenBegin > 2048) + { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } + else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } + else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, + available - maxNextCharInd)) == -1) + { + inputStream.close(); + throw new java.io.IOException(); + } + else + maxNextCharInd += i; + return; + } + catch(java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + + public final char BeginToken() throws java.io.IOException + { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + private final void UpdateLineColumn(char c) + { + column++; + + if (prevCharIsLF) + { + prevCharIsLF = false; + line += (column = 1); + } + else if (prevCharIsCR) + { + prevCharIsCR = false; + if (c == '\n') + { + prevCharIsLF = true; + } + else + line += (column = 1); + } + + switch (c) + { + case '\r' : + prevCharIsCR = true; + break; + case '\n' : + prevCharIsLF = true; + break; + case '\t' : + column--; + column += (8 - (column & 07)); + break; + default : + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + + public final char readChar() throws java.io.IOException + { + if (inBuf > 0) + { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return (c); + } + + /** + * @deprecated + * @see #getEndColumn + */ + + public final int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @deprecated + * @see #getEndLine + */ + + public final int getLine() { + return bufline[bufpos]; + } + + public final int getEndColumn() { + return bufcolumn[bufpos]; + } + + public final int getEndLine() { + return bufline[bufpos]; + } + + public final int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + public final int getBeginLine() { + return bufline[tokenBegin]; + } + + public final void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.Reader dstream) + { + this(dstream, 1, 1, 4096); + } + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) + { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + + public void ReInit(java.io.Reader dstream) + { + ReInit(dstream, 1, 1, 4096); + } + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + public SimpleCharStream(java.io.InputStream dstream) + { + this(dstream, 1, 1, 4096); + } + + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); + } + + public void ReInit(java.io.InputStream dstream) + { + ReInit(dstream, 1, 1, 4096); + } + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + public final String GetImage() + { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + public final char[] GetSuffix(int len) + { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else + { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + public void Done() + { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token.
+ */ + public void adjustBeginLineColumn(int newLine, int newCol) + { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) + { + len = bufpos - tokenBegin + inBuf + 1; + } + else + { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k = 0; + int nextColDiff = 0, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) + { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) + { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) + { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/Token.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/Token.java new file mode 100644 index 000000000..a6561ad30 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/Token.java @@ -0,0 +1,82 @@ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 2.1 */ +package org.apache.taglibs.standard.lang.jstl.parser; + +/** + * Describes the input token stream. + */ + +@SuppressWarnings("all") // Ignore warnings in generated code +public class Token { + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** + * beginLine and beginColumn describe the position of the first character + * of this token; endLine and endColumn describe the position of the + * last character of this token. + */ + public int beginLine, beginColumn, endLine, endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** + * Returns the image. + */ + public final String toString() + { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simlpy add something like : + * + * case MyParserConstants.ID : return new IDToken(); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use it in your lexical actions. + */ + public static final Token newToken(int ofKind) + { + switch(ofKind) + { + default : return new Token(); + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/TokenMgrError.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/TokenMgrError.java new file mode 100644 index 000000000..b96927e3b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/jstl/parser/TokenMgrError.java @@ -0,0 +1,134 @@ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 2.1 */ +package org.apache.taglibs.standard.lang.jstl.parser; + +@SuppressWarnings("all") // Ignore warnings in generated code +public class TokenMgrError extends Error +{ + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occured. + */ + static final int LEXICAL_ERROR = 0; + + /** + * An attempt wass made to create a second instance of a static token manager. + */ + static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their espaced (or unicode escaped) + * equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuilder retval = new StringBuilder(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + * Parameters : + * EOFSeen : indicates if EOF caused the lexicl error + * curLexState : lexical state in which this error occured + * errorLine : line number when the error occured + * errorColumn : column number when the error occured + * errorAfter : prefix that was seen before this error occured + * curchar : the offending character + * Note: You can customize the lexical error message by modifying this method. + */ + private static final String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return("Lexical error at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + public TokenMgrError() { + } + + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluator.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluator.java new file mode 100644 index 000000000..a12c0c96d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluator.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.lang.support; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; + +/** + *

The interface for an expression-language validator and evaluator. + * Classes that implement an expression language expose their functionality + * via this interface.

+ *

The validate() and evaluate() methods must be thread-safe. That is, + * multiple threads may call these methods on the same ExpressionEvaluator + * object simultaneously. Implementations should synchronize access if + * they depend on transient state. Implementations should not, however, + * assume that only one object of each ExpressionEvaluator type will be + * instantiated; global caching should therefore be static. No release() + * mechanism or robust lifecycle is specified, for language-interpreter + * pluggability is experimental in EA2.

+ *

WARNING: This class supports experimentation for the EA2 + * release of JSTL; it is not expected to be part of the final RI or + * specification.

+ * + * @author Shawn Bayern (based exactly on rev1 draft) + */ +public interface ExpressionEvaluator { + + /** + * Translation time validation of an expression. + * This method will return a null String if the expression is valid; otherwise an error message. + */ + public String validate(String attributeName, + String expression); + + /** + * Evaluates the expression at request time. + */ + public Object evaluate(String attributeName, + String expression, + Class expectedType, + Tag tag, + PageContext pageContext) + throws JspException; +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluatorManager.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluatorManager.java new file mode 100644 index 000000000..e9738bf95 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/lang/support/ExpressionEvaluatorManager.java @@ -0,0 +1,133 @@ +/* + * 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.taglibs.standard.lang.support; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.lang.jstl.Coercions; +import org.apache.taglibs.standard.lang.jstl.ELException; +import org.apache.taglibs.standard.lang.jstl.Evaluator; +import org.apache.taglibs.standard.lang.jstl.Logger; + +/** + *

A conduit to the JSTL EL. Based on...

+ *

An implementation of the ExpressionEvaluatorManager called for by + * the JSTL rev1 draft. This class is responsible for delegating a + * request for expression evaluating to the particular, "active" + * ExpressionEvaluator for the given point in the PageContext object + * passed in.

+ * + * @author Shawn Bayern + */ +public class ExpressionEvaluatorManager { + + //********************************************************************* + // Constants + + public static final String EVALUATOR_CLASS = "org.apache.taglibs.standard.lang.jstl.Evaluator"; + + //********************************************************************* + // Internal, static state + + private static final ExpressionEvaluator EVALUATOR = new Evaluator(); + private static final ConcurrentMap nameMap = + new ConcurrentHashMap(); + static { + nameMap.put(EVALUATOR_CLASS, EVALUATOR); + } + + private static final Logger logger = new Logger(System.out); + + /** + * Invokes the evaluate() method on the "active" ExpressionEvaluator for the given pageContext. + */ + public static Object evaluate(String attributeName, + String expression, + Class expectedType, + Tag tag, + PageContext pageContext) + throws JspException { + + // delegate the call + return (EVALUATOR.evaluate(attributeName, expression, expectedType, tag, pageContext)); + } + + /** + * Invokes the evaluate() method on the "active" ExpressionEvaluator for the given pageContext. + */ + public static Object evaluate(String attributeName, + String expression, + Class expectedType, + PageContext pageContext) + throws JspException { + + return evaluate(attributeName, expression, expectedType, null, pageContext); + } + + /** + * Gets an ExpressionEvaluator from the cache, or seeds the cache + * if we haven't seen a particular ExpressionEvaluator before. + */ + @Deprecated + public static ExpressionEvaluator getEvaluatorByName(String name) throws JspException { + try { + ExpressionEvaluator evaluator = nameMap.get(name); + if (evaluator == null) { + nameMap.putIfAbsent(name, (ExpressionEvaluator) Class.forName(name).newInstance()); + evaluator = nameMap.get(name); + } + return evaluator; + } catch (ClassCastException ex) { + // just to display a better error message + throw new JspException("invalid ExpressionEvaluator: " + name, ex); + } catch (ClassNotFoundException ex) { + throw new JspException("couldn't find ExpressionEvaluator: " + name, ex); + } catch (IllegalAccessException ex) { + throw new JspException("couldn't access ExpressionEvaluator: " + name, ex); + } catch (InstantiationException ex) { + throw new JspException("couldn't instantiate ExpressionEvaluator: " + name, ex); + } + } + + /** + * Performs a type conversion according to the EL's rules. + */ + public static Object coerce(Object value, Class classe) throws JspException { + try { + // just delegate the call + return Coercions.coerce(value, classe, logger); + } catch (ELException ex) { + throw new JspException(ex); + } + } + + /** + * Validates an expression. + * @param attributeName the name of the attribute containing the expression + * @param expression the expression to validate + * @return null an error message or null of the expression is valid + */ + public static String validate(String attributeName, String expression) { + return EVALUATOR.validate(attributeName, expression); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ExpressionUtil.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ExpressionUtil.java new file mode 100644 index 000000000..54882ae5d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ExpressionUtil.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.Tag; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; + +/** + *

Contains some static utilities to facilitate common forms of + * expression evaluation.

+ * + * @author Shawn Bayern + */ + +public class ExpressionUtil { + + /** + * Evaluates an expression if present, but does not allow the expression + * to evaluate to 'null', throwing a NullAttributeException if it + * does. The function can return null, however, if the + * expression itself is null. + */ + public static Object evalNotNull(String tagName, + String attributeName, + String expression, + Class expectedType, + Tag tag, + PageContext pageContext) + throws JspException { + if (expression != null) { + Object r = ExpressionEvaluatorManager.evaluate( + attributeName, expression, expectedType, tag, pageContext); + if (r == null) { + throw new NullAttributeException(tagName, attributeName); + } + return r; + } else { + return null; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForEachTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForEachTag.java new file mode 100644 index 000000000..5241ba8ad --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForEachTag.java @@ -0,0 +1,173 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import java.util.ArrayList; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.IterationTag; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.ForEachSupport; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; + +/** + *

A handler for <forEach> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ + +public class ForEachTag + extends ForEachSupport + implements LoopTag, IterationTag { + + //********************************************************************* + // 'Private' state (implementation details) + + private String begin_; // stores EL-based property + private String end_; // stores EL-based property + private String step_; // stores EL-based property + private String items_; // stores EL-based property + + + //********************************************************************* + // Constructor + + public ForEachTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + /* Begins iterating by processing the first item. */ + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setBegin(String begin_) { + this.begin_ = begin_; + this.beginSpecified = true; + } + + // for EL-based attribute + + public void setEnd(String end_) { + this.end_ = end_; + this.endSpecified = true; + } + + // for EL-based attribute + + public void setStep(String step_) { + this.step_ = step_; + this.stepSpecified = true; + } + + public void setItems(String items_) { + this.items_ = items_; + } + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // defaults for interface with page author + begin_ = null; // (no expression) + end_ = null; // (no expression) + step_ = null; // (no expression) + items_ = null; // (no expression) + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (begin_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "begin", begin_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forEach", "begin"); + } + begin = ((Integer) r).intValue(); + validateBegin(); + } + + if (end_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "end", end_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forEach", "end"); + } + end = ((Integer) r).intValue(); + validateEnd(); + } + + if (step_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "step", step_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forEach", "step"); + } + step = ((Integer) r).intValue(); + validateStep(); + } + + if (items_ != null) { + rawItems = ExpressionEvaluatorManager.evaluate( + "items", items_, Object.class, this, pageContext); + // use an empty list to indicate "no iteration", if relevant + if (rawItems == null) { + rawItems = new ArrayList(); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForTokensTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForTokensTag.java new file mode 100644 index 000000000..54cb43085 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ForTokensTag.java @@ -0,0 +1,190 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.IterationTag; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.ForTokensSupport; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; + +/** + *

A handler for <forTokens> that accepts attributes as Strings + * and evaluates them as expressions at runtime. + * + * @author Shawn Bayern + */ +public class ForTokensTag + extends ForTokensSupport + implements LoopTag, IterationTag { + + //********************************************************************* + // 'Private' state (implementation details) + + private String begin_; // raw EL-based property + private String end_; // raw EL-based property + private String step_; // raw EL-based property + private String items_; // raw EL-based property + private String delims_; // raw EL-based property + + + //********************************************************************* + // Constructor + + public ForTokensTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + /* Begins iterating by processing the first item. */ + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setBegin(String begin_) { + this.begin_ = begin_; + this.beginSpecified = true; + } + + // for EL-based attribute + + public void setEnd(String end_) { + this.end_ = end_; + this.endSpecified = true; + } + + // for EL-based attribute + + public void setStep(String step_) { + this.step_ = step_; + this.stepSpecified = true; + } + + // for EL-based attribute + + public void setItems(String items_) { + this.items_ = items_; + } + + // for EL-based attribute + + public void setDelims(String delims_) { + this.delims_ = delims_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // defaults for interface with page author + begin_ = null; // (no expression) + end_ = null; // (no expression) + step_ = null; // (no expression) + items_ = null; // (no expression) + delims_ = null; // (no expression) + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (begin_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "begin", begin_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forTokens", "begin"); + } + begin = ((Integer) r).intValue(); + validateBegin(); + } + + if (end_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "end", end_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forTokens", "end"); + } + end = ((Integer) r).intValue(); + validateEnd(); + } + + if (step_ != null) { + Object r = ExpressionEvaluatorManager.evaluate( + "step", step_, Integer.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("forTokens", "step"); + } + step = ((Integer) r).intValue(); + validateStep(); + } + + if (items_ != null) { + items = (String) ExpressionEvaluatorManager.evaluate( + "items", items_, String.class, this, pageContext); + // use the empty string to indicate "no iteration" + if (items == null) { + items = ""; + } + } + + if (delims_ != null) { + delims = (String) ExpressionEvaluatorManager.evaluate( + "delims", delims_, String.class, this, pageContext); + // use the empty string to cause monolithic tokenization + if (delims == null) { + delims = ""; + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/IfTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/IfTag.java new file mode 100644 index 000000000..32e523192 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/IfTag.java @@ -0,0 +1,98 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; + +/** + *

Tag handler for <if> in JSTL's expression-evaluating library. + * Because of the support provided by the ConditionalTagSupport class, + * thistag is trivial enough not to require a separate base supporting + * class common to both libraries.

+ * + * @author Shawn Bayern + */ + +public class IfTag extends ConditionalTagSupport { + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public IfTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Supplied conditional logic + + protected boolean condition() throws JspTagException { + try { + Object r = ExpressionEvaluatorManager.evaluate( + "test", test, Boolean.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("if", "test"); + } else { + return (((Boolean) r).booleanValue()); + } + } catch (JspException ex) { + throw new JspTagException(ex.toString(), ex); + } + } + + + //********************************************************************* + // Private state + + private String test; // the value of the 'test' attribute + + + //********************************************************************* + // Accessors + + // receives the tag's 'test' attribute + + public void setTest(String test) { + this.test = test; + } + + + //********************************************************************* + // Private utility methods + + // resets internal state + + private void init() { + test = null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ImportTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ImportTag.java new file mode 100644 index 000000000..63b3a3d95 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ImportTag.java @@ -0,0 +1,129 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ImportSupport; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; + +/** + *

A handler for <import> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ + +public class ImportTag extends ImportSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String context_; // stores EL-based property + private String charEncoding_; // stores EL-based property + private String url_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ImportTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ImportTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setUrl(String url_) { + this.url_ = url_; + } + + public void setContext(String context_) { + this.context_ = context_; + } + + public void setCharEncoding(String charEncoding_) { + this.charEncoding_ = charEncoding_; + } + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + url_ = context_ = charEncoding_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + url = (String) ExpressionUtil.evalNotNull( + "import", "url", url_, String.class, this, pageContext); + if (url == null || url.equals("")) { + throw new NullAttributeException("import", "url"); + } + + context = (String) ExpressionUtil.evalNotNull( + "import", "context", context_, String.class, this, pageContext); + charEncoding = (String) ExpressionUtil.evalNotNull( + "import", "charEncoding", charEncoding_, String.class, this, + pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/OutTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/OutTag.java new file mode 100644 index 000000000..e09a92407 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/OutTag.java @@ -0,0 +1,95 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.OutSupport; + +/** + *

A handler for <out>, which redirects the browser to a + * new URL. + * + * @author Shawn Bayern + */ + +public class OutTag extends OutSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String valueExpression; // stores EL-based property + private String defaultExpression; // stores EL-based property + private String escapeXmlExpression; // stores EL-based property + + + //********************************************************************* + // Constructor + + public OutTag() { + } + + @Override + public void release() { + valueExpression = null; + defaultExpression = null; + escapeXmlExpression = null; + super.release(); + } + + public void setValue(String value) { + this.valueExpression = value; + } + + public void setDefault(String def) { + this.defaultExpression = def; + } + + public void setEscapeXml(String escapeXml) { + this.escapeXmlExpression = escapeXml; + } + + @Override + protected Object evalValue() throws JspException { + if (valueExpression == null) { + return null; + } + return ExpressionEvaluatorManager.evaluate("value", valueExpression, Object.class, this, pageContext); + } + + @Override + protected String evalDefault() throws JspException { + if (defaultExpression == null) { + return null; + } + return (String) ExpressionEvaluatorManager.evaluate("default", defaultExpression, String.class, this, pageContext); + } + + @Override + protected boolean evalEscapeXml() throws JspException { + if (escapeXmlExpression == null) { + return true; + } + Boolean result = (Boolean) ExpressionEvaluatorManager.evaluate("escapeXml", escapeXmlExpression, Boolean.class, this, pageContext); + if (result == null) { + return true; + } + return result; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ParamTag.java new file mode 100644 index 000000000..19adbfef3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/ParamTag.java @@ -0,0 +1,117 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.ParamSupport; + +/** + *

A handler for <param> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String name_; // stores EL-based property + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ParamTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ParamTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setName(String name_) { + this.name_ = name_; + } + + public void setValue(String value_) { + this.value_ = value_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + name_ = value_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + name = (String) ExpressionUtil.evalNotNull( + "import", "name", name_, String.class, this, pageContext); + value = (String) ExpressionUtil.evalNotNull( + "import", "value", value_, String.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/RedirectTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/RedirectTag.java new file mode 100644 index 000000000..f95945a72 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/RedirectTag.java @@ -0,0 +1,114 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.RedirectSupport; + +/** + *

A handler for <redirect>, which redirects the browser to a + * new URL. + * + * @author Shawn Bayern + */ + +public class RedirectTag extends RedirectSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String url_; // stores EL-based property + private String context_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new URLEncodeTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public RedirectTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + public void setUrl(String url_) { + this.url_ = url_; + } + + public void setContext(String context_) { + this.context_ = context_; + } + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + url_ = context_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + url = (String) ExpressionUtil.evalNotNull( + "redirect", "url", url_, String.class, this, pageContext); + context = (String) ExpressionUtil.evalNotNull( + "redirect", "context", context_, String.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/SetTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/SetTag.java new file mode 100644 index 000000000..989d807ab --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/SetTag.java @@ -0,0 +1,82 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.SetSupport; + +/** + * JSTL 1.0 compatible version of <set> that accepts expressions for attribute values. + * + * @author Shawn Bayern + */ + +public class SetTag extends SetSupport { + + private boolean valueSpecified; + private String valueExpression; + private String targetExpression; + private String propertyExpression; + + public SetTag() { + } + + public void setValue(String value) { + this.valueExpression = value; + this.valueSpecified = true; + } + + public void setTarget(String target) { + this.targetExpression = target; + } + + public void setProperty(String property) { + this.propertyExpression = property; + } + + @Override + public void release() { + valueExpression = null; + targetExpression = null; + propertyExpression = null; + valueSpecified = false; + super.release(); + } + + @Override + protected boolean isValueSpecified() { + return valueSpecified; + } + + @Override + protected Object evalValue() throws JspException { + return ExpressionEvaluatorManager.evaluate("value", valueExpression, Object.class, this, pageContext); + } + + @Override + protected Object evalTarget() throws JspException { + return ExpressionEvaluatorManager.evaluate("target", targetExpression, Object.class, this, pageContext); + } + + @Override + protected String evalProperty() throws JspException { + return (String) ExpressionEvaluatorManager.evaluate("property", propertyExpression, String.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/UrlTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/UrlTag.java new file mode 100644 index 000000000..de0489179 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/UrlTag.java @@ -0,0 +1,115 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.UrlSupport; + +/** + *

A handler for <urlEncode> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ + +public class UrlTag extends UrlSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String context_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new URLEncodeTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public UrlTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + public void setValue(String value_) { + this.value_ = value_; + } + + public void setContext(String context_) { + this.context_ = context_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + value = (String) ExpressionUtil.evalNotNull( + "url", "value", value_, String.class, this, pageContext); + context = (String) ExpressionUtil.evalNotNull( + "url", "context", context_, String.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/WhenTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/WhenTag.java new file mode 100644 index 000000000..b7846456a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/core/WhenTag.java @@ -0,0 +1,96 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; +import org.apache.taglibs.standard.tag.common.core.WhenTagSupport; + +/** + *

Tag handler for <when> in JSTL's expression-evaluating + * library.

+ * + * @author Shawn Bayern + */ + +public class WhenTag extends WhenTagSupport { + + //********************************************************************* + // Constructor and lifecycle management + + // initialize inherited and local state + + public WhenTag() { + super(); + init(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Supplied conditional logic + + protected boolean condition() throws JspTagException { + try { + Object r = ExpressionEvaluatorManager.evaluate( + "test", test, Boolean.class, this, pageContext); + if (r == null) { + throw new NullAttributeException("when", "test"); + } else { + return (((Boolean) r).booleanValue()); + } + } catch (JspException ex) { + throw new JspTagException(ex.toString(), ex); + } + } + + + //********************************************************************* + // Private state + + private String test; // the value of the 'test' attribute + + + //********************************************************************* + // Accessors + + // receives the tag's 'test' attribute + + public void setTest(String test) { + this.test = test; + } + + + //********************************************************************* + // Private utility methods + + // resets internal state + + private void init() { + test = null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/BundleTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/BundleTag.java new file mode 100644 index 000000000..53325d37e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/BundleTag.java @@ -0,0 +1,118 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.BundleSupport; + +/** + *

A handler for <bundle> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + * @author Jan Luehe + */ + +public class BundleTag extends BundleSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String basename_; // stores EL-based property + private String prefix_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new BundleTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public BundleTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setBasename(String basename_) { + this.basename_ = basename_; + } + + // for EL-based attribute + + public void setPrefix(String prefix_) { + this.prefix_ = prefix_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + basename_ = prefix_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + + // 'basename' attribute (mandatory) + basename = (String) ExpressionEvaluatorManager.evaluate( + "basename", basename_, String.class, this, pageContext); + + // 'prefix' attribute (optional) + if (prefix_ != null) { + prefix = (String) ExpressionEvaluatorManager.evaluate( + "prefix", prefix_, String.class, this, pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatDateTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatDateTag.java new file mode 100644 index 000000000..3365e93c5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatDateTag.java @@ -0,0 +1,178 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import java.util.Date; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.FormatDateSupport; + +/** + *

A handler for <formatDate> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class FormatDateTag extends FormatDateSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String type_; // stores EL-based property + private String dateStyle_; // stores EL-based property + private String timeStyle_; // stores EL-based property + private String pattern_; // stores EL-based property + private String timeZone_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new FormatDateTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public FormatDateTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + } + + // for EL-based attribute + + public void setType(String type_) { + this.type_ = type_; + } + + // for EL-based attribute + + public void setDateStyle(String dateStyle_) { + this.dateStyle_ = dateStyle_; + } + + // for EL-based attribute + + public void setTimeStyle(String timeStyle_) { + this.timeStyle_ = timeStyle_; + } + + // for EL-based attribute + + public void setPattern(String pattern_) { + this.pattern_ = pattern_; + } + + // for EL-based attribute + + public void setTimeZone(String timeZone_) { + this.timeZone_ = timeZone_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = type_ = dateStyle_ = timeStyle_ = pattern_ = timeZone_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + // 'value' attribute (mandatory) + value = (Date) ExpressionEvaluatorManager.evaluate( + "value", value_, Date.class, this, pageContext); + + // 'type' attribute + if (type_ != null) { + type = (String) ExpressionEvaluatorManager.evaluate( + "type", type_, String.class, this, pageContext); + } + + // 'dateStyle' attribute + if (dateStyle_ != null) { + dateStyle = (String) ExpressionEvaluatorManager.evaluate( + "dateStyle", dateStyle_, String.class, this, pageContext); + } + + // 'timeStyle' attribute + if (timeStyle_ != null) { + timeStyle = (String) ExpressionEvaluatorManager.evaluate( + "timeStyle", timeStyle_, String.class, this, pageContext); + } + + // 'pattern' attribute + if (pattern_ != null) { + pattern = (String) ExpressionEvaluatorManager.evaluate( + "pattern", pattern_, String.class, this, pageContext); + } + + // 'timeZone' attribute + if (timeZone_ != null) { + timeZone = ExpressionEvaluatorManager.evaluate( + "timeZone", timeZone_, Object.class, this, pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatNumberTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatNumberTag.java new file mode 100644 index 000000000..231a3bb80 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/FormatNumberTag.java @@ -0,0 +1,265 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.FormatNumberSupport; + +/** + *

A handler for <formatNumber> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class FormatNumberTag extends FormatNumberSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String type_; // stores EL-based property + private String pattern_; // stores EL-based property + private String currencyCode_; // stores EL-based property + private String currencySymbol_; // stores EL-based property + private String groupingUsed_; // stores EL-based property + private String maxIntegerDigits_; // stores EL-based property + private String minIntegerDigits_; // stores EL-based property + private String maxFractionDigits_; // stores EL-based property + private String minFractionDigits_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new FormatNumberTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public FormatNumberTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + this.valueSpecified = true; + } + + // for EL-based attribute + + public void setType(String type_) { + this.type_ = type_; + } + + // for EL-based attribute + + public void setPattern(String pattern_) { + this.pattern_ = pattern_; + } + + // for EL-based attribute + + public void setCurrencyCode(String currencyCode_) { + this.currencyCode_ = currencyCode_; + } + + // for EL-based attribute + + public void setCurrencySymbol(String currencySymbol_) { + this.currencySymbol_ = currencySymbol_; + } + + // for EL-based attribute + + public void setGroupingUsed(String groupingUsed_) { + this.groupingUsed_ = groupingUsed_; + this.groupingUsedSpecified = true; + } + + // for EL-based attribute + + public void setMaxIntegerDigits(String maxIntegerDigits_) { + this.maxIntegerDigits_ = maxIntegerDigits_; + this.maxIntegerDigitsSpecified = true; + } + + // for EL-based attribute + + public void setMinIntegerDigits(String minIntegerDigits_) { + this.minIntegerDigits_ = minIntegerDigits_; + this.minIntegerDigitsSpecified = true; + } + + // for EL-based attribute + + public void setMaxFractionDigits(String maxFractionDigits_) { + this.maxFractionDigits_ = maxFractionDigits_; + this.maxFractionDigitsSpecified = true; + } + + // for EL-based attribute + + public void setMinFractionDigits(String minFractionDigits_) { + this.minFractionDigits_ = minFractionDigits_; + this.minFractionDigitsSpecified = true; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = type_ = pattern_ = null; + currencyCode_ = currencySymbol_ = null; + groupingUsed_ = null; + maxIntegerDigits_ = minIntegerDigits_ = null; + maxFractionDigits_ = minFractionDigits_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + Object obj = null; + + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + // 'value' attribute + if (value_ != null) { + value = ExpressionEvaluatorManager.evaluate( + "value", value_, Object.class, this, pageContext); + } + + // 'type' attribute + if (type_ != null) { + type = (String) ExpressionEvaluatorManager.evaluate( + "type", type_, String.class, this, pageContext); + } + + // 'pattern' attribute + if (pattern_ != null) { + pattern = (String) ExpressionEvaluatorManager.evaluate( + "pattern", pattern_, String.class, this, pageContext); + } + + // 'currencyCode' attribute + if (currencyCode_ != null) { + currencyCode = (String) ExpressionEvaluatorManager.evaluate( + "currencyCode", currencyCode_, String.class, this, + pageContext); + } + + // 'currencySymbol' attribute + if (currencySymbol_ != null) { + currencySymbol = (String) ExpressionEvaluatorManager.evaluate( + "currencySymbol", currencySymbol_, String.class, this, + pageContext); + } + + // 'groupingUsed' attribute + if (groupingUsed_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "groupingUsed", groupingUsed_, Boolean.class, this, + pageContext); + if (obj != null) { + isGroupingUsed = ((Boolean) obj).booleanValue(); + } + } + + // 'maxIntegerDigits' attribute + if (maxIntegerDigits_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "maxIntegerDigits", maxIntegerDigits_, Integer.class, this, + pageContext); + if (obj != null) { + maxIntegerDigits = ((Integer) obj).intValue(); + } + } + + // 'minIntegerDigits' attribute + if (minIntegerDigits_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "minIntegerDigits", minIntegerDigits_, Integer.class, this, + pageContext); + if (obj != null) { + minIntegerDigits = ((Integer) obj).intValue(); + } + } + + // 'maxFractionDigits' attribute + if (maxFractionDigits_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "maxFractionDigits", maxFractionDigits_, Integer.class, this, + pageContext); + if (obj != null) { + maxFractionDigits = ((Integer) obj).intValue(); + } + } + + // 'minFractionDigits' attribute + if (minFractionDigits_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "minFractionDigits", minFractionDigits_, Integer.class, this, + pageContext); + if (obj != null) { + minFractionDigits = ((Integer) obj).intValue(); + } + } + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/MessageTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/MessageTag.java new file mode 100644 index 000000000..6267138d1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/MessageTag.java @@ -0,0 +1,129 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.jstl.fmt.LocalizationContext; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.MessageSupport; + +/** + *

A handler for <message> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class MessageTag extends MessageSupport { + + //********************************************************************* + // Private state (implementation details) + + private String key_; // stores EL-based property + private String bundle_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new MessageTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public MessageTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setKey(String key_) { + this.key_ = key_; + this.keySpecified = true; + } + + // for EL-based attribute + + public void setBundle(String bundle_) { + this.bundle_ = bundle_; + this.bundleSpecified = true; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + key_ = bundle_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (keySpecified) { + keyAttrValue = (String) ExpressionEvaluatorManager.evaluate( + "key", key_, String.class, this, pageContext); + } + + if (bundleSpecified) { + bundleAttrValue = (LocalizationContext) + ExpressionEvaluatorManager.evaluate( + "bundle", bundle_, LocalizationContext.class, this, + pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParamTag.java new file mode 100644 index 000000000..0f061baef --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParamTag.java @@ -0,0 +1,113 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.ParamSupport; + +/** + *

A handler for <param> that accepts message arguments as + * Strings and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ParamTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ParamTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + this.valueSpecified = true; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (value_ != null) { + value = ExpressionEvaluatorManager.evaluate( + "value", value_, Object.class, this, pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseDateTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseDateTag.java new file mode 100644 index 000000000..75b6c9fa6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseDateTag.java @@ -0,0 +1,200 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseDateSupport; + +/** + *

A handler for <parseDate> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class ParseDateTag extends ParseDateSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String type_; // stores EL-based property + private String dateStyle_; // stores EL-based property + private String timeStyle_; // stores EL-based property + private String pattern_; // stores EL-based property + private String timeZone_; // stores EL-based property + private String parseLocale_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ParseDateTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ParseDateTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + this.valueSpecified = true; + } + + // for EL-based attribute + + public void setType(String type_) { + this.type_ = type_; + } + + // for EL-based attribute + + public void setDateStyle(String dateStyle_) { + this.dateStyle_ = dateStyle_; + } + + // for EL-based attribute + + public void setTimeStyle(String timeStyle_) { + this.timeStyle_ = timeStyle_; + } + + // for EL-based attribute + + public void setPattern(String pattern_) { + this.pattern_ = pattern_; + } + + // for EL-based attribute + + public void setTimeZone(String timeZone_) { + this.timeZone_ = timeZone_; + } + + // for EL-based attribute + + public void setParseLocale(String parseLocale_) { + this.parseLocale_ = parseLocale_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = type_ = dateStyle_ = timeStyle_ = pattern_ = timeZone_ = null; + parseLocale_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + // 'value' attribute + if (value_ != null) { + value = (String) ExpressionEvaluatorManager.evaluate( + "value", value_, String.class, this, pageContext); + } + + // 'type' attribute + if (type_ != null) { + type = (String) ExpressionEvaluatorManager.evaluate( + "type", type_, String.class, this, pageContext); + } + + // 'dateStyle' attribute + if (dateStyle_ != null) { + dateStyle = (String) ExpressionEvaluatorManager.evaluate( + "dateStyle", dateStyle_, String.class, this, pageContext); + } + + // 'timeStyle' attribute + if (timeStyle_ != null) { + timeStyle = (String) ExpressionEvaluatorManager.evaluate( + "timeStyle", timeStyle_, String.class, this, pageContext); + } + + // 'pattern' attribute + if (pattern_ != null) { + pattern = (String) ExpressionEvaluatorManager.evaluate( + "pattern", pattern_, String.class, this, pageContext); + } + + // 'timeZone' attribute + if (timeZone_ != null) { + timeZone = ExpressionEvaluatorManager.evaluate( + "timeZone", timeZone_, Object.class, this, pageContext); + } + + // 'parseLocale' attribute + if (parseLocale_ != null) { + Object obj = ExpressionEvaluatorManager.evaluate( + "parseLocale", parseLocale_, Object.class, this, pageContext); + Locale locale = LocaleUtil.parseLocaleAttributeValue(obj); + if (locale != null) { + this.parseLocale = locale; + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseNumberTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseNumberTag.java new file mode 100644 index 000000000..03ef54214 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/ParseNumberTag.java @@ -0,0 +1,180 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.LocaleUtil; +import org.apache.taglibs.standard.tag.common.fmt.ParseNumberSupport; + +/** + *

A handler for <parseNumber> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class ParseNumberTag extends ParseNumberSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String type_; // stores EL-based property + private String pattern_; // stores EL-based property + private String parseLocale_; // stores EL-based property + private String integerOnly_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ParseNumberTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ParseNumberTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + this.valueSpecified = true; + } + + // for EL-based attribute + + public void setType(String type_) { + this.type_ = type_; + } + + // for EL-based attribute + + public void setPattern(String pattern_) { + this.pattern_ = pattern_; + } + + // for EL-based attribute + + public void setParseLocale(String parseLocale_) { + this.parseLocale_ = parseLocale_; + } + + // for EL-based attribute + + public void setIntegerOnly(String integerOnly_) { + this.integerOnly_ = integerOnly_; + this.integerOnlySpecified = true; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = type_ = pattern_ = parseLocale_ = integerOnly_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + Object obj = null; + + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + // 'value' attribute + if (value_ != null) { + value = (String) ExpressionEvaluatorManager.evaluate( + "value", value_, String.class, this, pageContext); + } + + // 'type' attribute + if (type_ != null) { + type = (String) ExpressionEvaluatorManager.evaluate( + "type", type_, String.class, this, pageContext); + } + + // 'pattern' attribute + if (pattern_ != null) { + pattern = (String) ExpressionEvaluatorManager.evaluate( + "pattern", pattern_, String.class, this, pageContext); + } + + // 'parseLocale' attribute + if (parseLocale_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "parseLocale", parseLocale_, Object.class, this, pageContext); + Locale locale = LocaleUtil.parseLocaleAttributeValue(obj); + if (locale != null) { + this.parseLocale = locale; + } + } + + // 'integerOnly' attribute + if (integerOnly_ != null) { + obj = ExpressionEvaluatorManager.evaluate( + "integerOnly", integerOnly_, Boolean.class, this, pageContext); + if (obj != null) { + isIntegerOnly = ((Boolean) obj).booleanValue(); + } + } + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/RequestEncodingTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/RequestEncodingTag.java new file mode 100644 index 000000000..fb3eb730b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/RequestEncodingTag.java @@ -0,0 +1,112 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.RequestEncodingSupport; + +/** + *

A handler for <requestEncoding> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class RequestEncodingTag extends RequestEncodingSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new RequestEncodingTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public RequestEncodingTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (value_ != null) { + value = (String) ExpressionEvaluatorManager.evaluate( + "value", value_, String.class, this, pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetBundleTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetBundleTag.java new file mode 100644 index 000000000..51728167b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetBundleTag.java @@ -0,0 +1,105 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.SetBundleSupport; + +/** + *

A handler for <setBundle> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + * @author Jan Luehe + */ + +public class SetBundleTag extends SetBundleSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String basename_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new SetBundleTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public SetBundleTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setBasename(String basename_) { + this.basename_ = basename_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + basename_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + + // 'basename' attribute (mandatory) + basename = (String) ExpressionEvaluatorManager.evaluate( + "basename", basename_, String.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetLocaleTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetLocaleTag.java new file mode 100644 index 000000000..6d98d37f9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetLocaleTag.java @@ -0,0 +1,117 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.SetLocaleSupport; + +/** + *

A handler for <setLocale> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Jan Luehe + */ + +public class SetLocaleTag extends SetLocaleSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + private String variant_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new LocaleTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public SetLocaleTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + } + + // for EL-based attribute + + public void setVariant(String variant_) { + this.variant_ = variant_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = variant_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + + // 'value' attribute (mandatory) + value = ExpressionEvaluatorManager.evaluate( + "value", value_, Object.class, this, pageContext); + + // 'variant' attribute (optional) + if (variant_ != null) { + variant = (String) ExpressionEvaluatorManager.evaluate( + "variant", variant_, String.class, this, pageContext); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetTimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetTimeZoneTag.java new file mode 100644 index 000000000..5a0e53c74 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/SetTimeZoneTag.java @@ -0,0 +1,105 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.SetTimeZoneSupport; + +/** + *

A handler for <setTimeZone> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + * @author Jan Luehe + */ + +public class SetTimeZoneTag extends SetTimeZoneSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new TimeZoneTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public SetTimeZoneTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + + // 'value' attribute (mandatory) + value = ExpressionEvaluatorManager.evaluate( + "value", value_, Object.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/TimeZoneTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/TimeZoneTag.java new file mode 100644 index 000000000..f77bae9a4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/fmt/TimeZoneTag.java @@ -0,0 +1,105 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.fmt.TimeZoneSupport; + +/** + *

A handler for <timeZone> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + * @author Jan Luehe + */ + +public class TimeZoneTag extends TimeZoneSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new TimeZoneTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public TimeZoneTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setValue(String value_) { + this.value_ = value_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + value_ = null; + } + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + + // 'value' attribute (mandatory) + value = ExpressionEvaluatorManager.evaluate( + "value", value_, Object.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/DateParamTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/DateParamTag.java new file mode 100644 index 000000000..6d0647174 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/DateParamTag.java @@ -0,0 +1,66 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import java.util.Date; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.DateParamTagSupport; + +/** + * Subclass for the JSTL library with EL support. + * + * @author Justyna Horwat + */ +public class DateParamTag extends DateParamTagSupport { + + private String valueEL; + private String typeEL; + + public void setValue(String valueEL) { + this.valueEL = valueEL; + } + + public void setType(String typeEL) { + this.typeEL = typeEL; + } + + public int doStartTag() throws JspException { + evaluateExpressions(); + return super.doStartTag(); + } + + //********************************************************************* + // Private utility methods + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + if (valueEL != null) { + value = (Date) ExpressionEvaluatorManager.evaluate( + "value", valueEL, Date.class, this, pageContext); + } + + if (typeEL != null) { + type = (String) ExpressionEvaluatorManager.evaluate( + "type", typeEL, String.class, this, pageContext); + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/ParamTag.java new file mode 100644 index 000000000..5c4aedd75 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/ParamTag.java @@ -0,0 +1,45 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.ParamTagSupport; + +/** + * Subclass for the JSTL library with EL support. + * + * @author Hans Bergsten + */ +public class ParamTag extends ParamTagSupport { + + private String valueEL; + + public void setValue(String valueEL) { + this.valueEL = valueEL; + } + + public int doStartTag() throws JspException { + if (valueEL != null) { + value = (Object) + ExpressionEvaluatorManager.evaluate("value", valueEL, + Object.class, this, pageContext); + } + return super.doStartTag(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/QueryTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/QueryTag.java new file mode 100644 index 000000000..4f5e11eb0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/QueryTag.java @@ -0,0 +1,123 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.QueryTagSupport; + +/** + * Subclass for the JSTL library with EL support. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public class QueryTag extends QueryTagSupport { + + private String dataSourceEL; + private String sqlEL; + private String startRowEL; + private String maxRowsEL; + + //********************************************************************* + // Constructor + + /** + * Constructs a new QueryTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public QueryTag() { + super(); + } + + //********************************************************************* + // Accessor methods + + public void setDataSource(String dataSourceEL) { + this.dataSourceEL = dataSourceEL; + this.dataSourceSpecified = true; + } + + /** + * The index of the first row returned can be + * specified using startRow. + */ + public void setStartRow(String startRowEL) { + this.startRowEL = startRowEL; + } + + /** + * Query result can be limited by specifying + * the maximum number of rows returned. + */ + public void setMaxRows(String maxRowsEL) { + this.maxRowsEL = maxRowsEL; + this.maxRowsSpecified = true; + } + + /** + * Setter method for the SQL statement to use for the + * query. The statement may contain parameter markers + * (question marks, ?). If so, the parameter values must + * be set using nested value elements. + */ + public void setSql(String sqlEL) { + this.sqlEL = sqlEL; + } + + public int doStartTag() throws JspException { + evaluateExpressions(); + return super.doStartTag(); + } + + //********************************************************************* + // Private utility methods + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + Integer tempInt = null; + + if (dataSourceEL != null) { + rawDataSource = (Object) ExpressionEvaluatorManager.evaluate( + "dataSource", dataSourceEL, Object.class, this, pageContext); + } + + if (sqlEL != null) { + sql = (String) ExpressionEvaluatorManager.evaluate("sql", sqlEL, + String.class, this, pageContext); + } + + if (startRowEL != null) { + tempInt = (Integer) ExpressionEvaluatorManager.evaluate( + "startRow", startRowEL, Integer.class, this, pageContext); + if (tempInt != null) { + startRow = tempInt.intValue(); + } + } + + if (maxRowsEL != null) { + tempInt = (Integer) ExpressionEvaluatorManager.evaluate( + "maxRows", maxRowsEL, Integer.class, this, pageContext); + if (tempInt != null) { + maxRows = tempInt.intValue(); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/SetDataSourceTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/SetDataSourceTag.java new file mode 100644 index 000000000..c807f8be7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/SetDataSourceTag.java @@ -0,0 +1,103 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.SetDataSourceTagSupport; + +/** + *

Tag handler for <SetDataSource> in JSTL, used to create + * a simple DataSource for prototyping.

+ */ +public class SetDataSourceTag extends SetDataSourceTagSupport { + + private String dataSourceEL; + private String driverClassNameEL; + private String jdbcURLEL; + private String userNameEL; + private String passwordEL; + + //********************************************************************* + // Accessor methods + + public void setDataSource(String dataSourceEL) { + this.dataSourceEL = dataSourceEL; + this.dataSourceSpecified = true; + } + + public void setDriver(String driverClassNameEL) { + this.driverClassNameEL = driverClassNameEL; + } + + public void setUrl(String jdbcURLEL) { + this.jdbcURLEL = jdbcURLEL; + } + + public void setUser(String userNameEL) { + this.userNameEL = userNameEL; + } + + public void setPassword(String passwordEL) { + this.passwordEL = passwordEL; + } + + //********************************************************************* + // Tag logic + + public int doStartTag() throws JspException { + evaluateExpressions(); + + return super.doStartTag(); + } + + + //********************************************************************* + // Private utility methods + + // Evaluates expressions as necessary + + private void evaluateExpressions() throws JspException { + if (dataSourceEL != null) { + dataSource = ExpressionEvaluatorManager.evaluate + ("dataSource", dataSourceEL, Object.class, this, pageContext); + } + + if (driverClassNameEL != null) { + driverClassName = (String) ExpressionEvaluatorManager.evaluate + ("driver", driverClassNameEL, String.class, this, pageContext); + } + + if (jdbcURLEL != null) { + jdbcURL = (String) ExpressionEvaluatorManager.evaluate + ("url", jdbcURLEL, String.class, this, pageContext); + } + + if (userNameEL != null) { + userName = (String) ExpressionEvaluatorManager.evaluate + ("user", userNameEL, String.class, this, pageContext); + } + + if (passwordEL != null) { + password = (String) ExpressionEvaluatorManager.evaluate + ("password", passwordEL, String.class, this, pageContext); + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/TransactionTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/TransactionTag.java new file mode 100644 index 000000000..e1b8ef00a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/TransactionTag.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.TransactionTagSupport; + +/** + * Subclass for the JSTL library with EL support. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ +public class TransactionTag extends TransactionTagSupport { + + private String dataSourceEL; + private String isolationEL; + + public void setDataSource(String dataSourceEL) { + this.dataSourceEL = dataSourceEL; + this.dataSourceSpecified = true; + } + + public void setIsolation(String isolationEL) { + this.isolationEL = isolationEL; + } + + public int doStartTag() throws JspException { + if (dataSourceEL != null) { + rawDataSource = (Object) + ExpressionEvaluatorManager.evaluate("dataSource", + dataSourceEL, Object.class, this, pageContext); + } + + if (isolationEL != null) { + isolationEL = (String) + ExpressionEvaluatorManager.evaluate("isolation", + isolationEL, String.class, this, pageContext); + super.setIsolation(isolationEL); + } + + return super.doStartTag(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/UpdateTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/UpdateTag.java new file mode 100644 index 000000000..d2ad2e486 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/sql/UpdateTag.java @@ -0,0 +1,61 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; +import org.apache.taglibs.standard.tag.common.sql.UpdateTagSupport; + +/** + * Subclass for the JSTL library with EL support. + * + * @author Hans Bergsten + */ +public class UpdateTag extends UpdateTagSupport { + + private String dataSourceEL; + private String sqlEL; + + public void setDataSource(String dataSourceEL) { + this.dataSourceEL = dataSourceEL; + this.dataSourceSpecified = true; + } + + /** + * Setter method for the SQL statement to use for the + * query. The statement may contain parameter markers + * (question marks, ?). If so, the parameter values must + * be set using nested value elements. + */ + public void setSql(String sqlEL) { + this.sqlEL = sqlEL; + } + + public int doStartTag() throws JspException { + if (dataSourceEL != null) { + rawDataSource = (Object) + ExpressionEvaluatorManager.evaluate("dataSource", + dataSourceEL, Object.class, this, pageContext); + } + if (sqlEL != null) { + sql = (String) ExpressionEvaluatorManager.evaluate("sql", sqlEL, + String.class, this, pageContext); + } + return super.doStartTag(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ExprTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ExprTag.java new file mode 100644 index 000000000..67ac9e71d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ExprTag.java @@ -0,0 +1,122 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.xml.ExprSupport; +import org.apache.taglibs.standard.tag.el.core.ExpressionUtil; + +/** + *

A handler for <out> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ +public class ExprTag extends ExprSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String escapeXml_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new handler. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ExprTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setEscapeXml(String escapeXml_) { + this.escapeXml_ = escapeXml_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + escapeXml_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + if (escapeXml_ != null) { + Boolean b = (Boolean) ExpressionUtil.evalNotNull( + "out", + "escapeXml", + escapeXml_, + Boolean.class, + this, + pageContext); + if (b == null) { + escapeXml = false; + } else { + escapeXml = b.booleanValue(); + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParamTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParamTag.java new file mode 100644 index 000000000..9d3539338 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParamTag.java @@ -0,0 +1,113 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.xml.ParamSupport; +import org.apache.taglibs.standard.tag.el.core.ExpressionUtil; + +/** + *

A handler for <param> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ + +public class ParamTag extends ParamSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String name_; // stores EL-based property + private String value_; // stores EL-based property + + + //********************************************************************* + // Constructor + + public ParamTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setName(String name_) { + this.name_ = name_; + } + + public void setValue(String value_) { + this.value_ = value_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + name_ = value_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + name = (String) ExpressionUtil.evalNotNull( + "param", "name", name_, String.class, this, pageContext); + value = ExpressionUtil.evalNotNull( + "param", "value", value_, Object.class, this, pageContext); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParseTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParseTag.java new file mode 100644 index 000000000..5f9a998bc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/ParseTag.java @@ -0,0 +1,132 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import jakarta.servlet.jsp.JspException; + +import org.apache.taglibs.standard.tag.common.core.NullAttributeException; +import org.apache.taglibs.standard.tag.common.xml.ParseSupport; +import org.apache.taglibs.standard.tag.el.core.ExpressionUtil; +import org.xml.sax.XMLFilter; + +/** + *

A handler for <parse> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ +public class ParseTag extends ParseSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String xml_; // stores EL-based property + private String systemId_; // stores EL-based property + private String filter_; // stores EL-based property + + + //********************************************************************* + // Constructor + + /** + * Constructs a new ParseTag. As with TagSupport, subclasses + * should not provide other constructors and are expected to call + * the superclass constructor + */ + public ParseTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setFilter(String filter_) { + this.filter_ = filter_; + } + + public void setXml(String xml_) { + this.xml_ = xml_; + } + + public void setSystemId(String systemId_) { + this.systemId_ = systemId_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + filter_ = xml_ = systemId_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + xml = ExpressionUtil.evalNotNull( + "parse", "xml", xml_, Object.class, this, pageContext); + systemId = (String) ExpressionUtil.evalNotNull( + "parse", "systemId", systemId_, String.class, this, pageContext); + + try { + filter = (XMLFilter) ExpressionUtil.evalNotNull( + "parse", "filter", filter_, XMLFilter.class, this, pageContext); + } catch (NullAttributeException ex) { + // explicitly let 'filter' be null + filter = null; + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java new file mode 100644 index 000000000..03d29e5db --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tag/el/xml/TransformTag.java @@ -0,0 +1,154 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import jakarta.servlet.jsp.JspException; +import javax.xml.transform.Result; + +import org.apache.taglibs.standard.tag.common.xml.TransformSupport; +import org.apache.taglibs.standard.tag.el.core.ExpressionUtil; + +/** + *

A handler for <transform> that accepts attributes as Strings + * and evaluates them as expressions at runtime.

+ * + * @author Shawn Bayern + */ +public class TransformTag extends TransformSupport { + + //********************************************************************* + // 'Private' state (implementation details) + + private String xml_; // stores EL-based property + private String xmlSystemId_; // stores EL-based property + private String xslt_; // stores EL-based property + private String xsltSystemId_; // stores EL-based property + private String result_; // stores EL-based property + + + //********************************************************************* + // Constructor + + public TransformTag() { + super(); + init(); + } + + + //********************************************************************* + // Tag logic + + // evaluates expression and chains to parent + + public int doStartTag() throws JspException { + + // evaluate any expressions we were passed, once per invocation + evaluateExpressions(); + + // chain to the parent implementation + return super.doStartTag(); + } + + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + + //********************************************************************* + // Accessor methods + + // for EL-based attribute + + public void setXml(String xml_) { + this.xml_ = xml_; + this.xmlSpecified = true; + } + + // for EL-based attribute + + public void setXmlSystemId(String xmlSystemId_) { + this.xmlSystemId_ = xmlSystemId_; + } + + // for EL-based attribute + + public void setXslt(String xslt_) { + this.xslt_ = xslt_; + } + + // for EL-based attribute + + public void setXsltSystemId(String xsltSystemId_) { + this.xsltSystemId_ = xsltSystemId_; + } + + /* Removed for RI 0.5 + // for EL-based attribute + public void setTransformer(String transformer_) { + this.transformer_ = transformer_; + } + */ + + // for EL-based attribute + + public void setResult(String result_) { + this.result_ = result_; + } + + + //********************************************************************* + // Private (utility) methods + + // (re)initializes state (during release() or construction) + + private void init() { + // null implies "no expression" + xml_ = xmlSystemId = xslt_ = xsltSystemId_ = result_ = null; + } + + /* Evaluates expressions as necessary */ + + private void evaluateExpressions() throws JspException { + /* + * Note: we don't check for type mismatches here; we assume + * the expression evaluator will return the expected type + * (by virtue of knowledge we give it about what that type is). + * A ClassCastException here is truly unexpected, so we let it + * propagate up. + */ + + xml = ExpressionUtil.evalNotNull( + "transform", "xml", xml_, Object.class, this, pageContext); + xmlSystemId = (String) ExpressionUtil.evalNotNull( + "transform", "xmlSystemId", xmlSystemId_, String.class, + this, pageContext); + xslt = ExpressionUtil.evalNotNull( + "transform", "xslt", xslt_, Object.class, this, + pageContext); + xsltSystemId = (String) ExpressionUtil.evalNotNull( + "transform", "xsltSystemId", xsltSystemId_, String.class, + this, pageContext); + result = (Result) ExpressionUtil.evalNotNull( + "transform", "result", result_, Result.class, this, pageContext); + + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELCoreTLV.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELCoreTLV.java new file mode 100644 index 000000000..d7be81bc9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELCoreTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.el; + +import org.apache.taglibs.standard.tlv.JstlCoreTLV; + +/** + */ +public class JstlELCoreTLV extends JstlCoreTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return ValidationUtil.validateExpression(elem, att, expr); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELFmtTLV.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELFmtTLV.java new file mode 100644 index 000000000..80deda920 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELFmtTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.el; + +import org.apache.taglibs.standard.tlv.JstlFmtTLV; + +/** + */ +public class JstlELFmtTLV extends JstlFmtTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return ValidationUtil.validateExpression(elem, att, expr); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELSqlTLV.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELSqlTLV.java new file mode 100644 index 000000000..4e68cb043 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELSqlTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.el; + +import org.apache.taglibs.standard.tlv.JstlSqlTLV; + +/** + */ +public class JstlELSqlTLV extends JstlSqlTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return ValidationUtil.validateExpression(elem, att, expr); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELXmlTLV.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELXmlTLV.java new file mode 100644 index 000000000..b34d2d6e0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/JstlELXmlTLV.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.tlv.el; + +import org.apache.taglibs.standard.tlv.JstlXmlTLV; + +/** + */ +public class JstlELXmlTLV extends JstlXmlTLV { + @Override + protected String validateExpression(String elem, String att, String expr) { + return ValidationUtil.validateExpression(elem, att, expr); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/ValidationUtil.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/ValidationUtil.java new file mode 100644 index 000000000..ee46d6a6f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/java/org/apache/taglibs/standard/tlv/el/ValidationUtil.java @@ -0,0 +1,32 @@ +/* + * 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.taglibs.standard.tlv.el; + +import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; + +/** + */ +public class ValidationUtil { + static String validateExpression(String elem, String att, String expr) { + + String response = ExpressionEvaluatorManager.validate(att, expr); + if (response != null) { + response = "tag = '" + elem + "' / attribute = '" + att + "': " + response; + } + return response; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/c-1_0.tld b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/c-1_0.tld new file mode 100644 index 000000000..9b4716297 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/c-1_0.tld @@ -0,0 +1,432 @@ + + + + + 1.0 + 1.2 + c + http://java.sun.com/jstl/core + JSTL core + JSTL 1.0 core library + + + + org.apache.taglibs.standard.tlv.el.JstlELCoreTLV + + + expressionAttributes + + out:value + out:default + out:escapeXml + if:test + import:url + import:context + import:charEncoding + forEach:items + forEach:begin + forEach:end + forEach:step + forTokens:items + forTokens:begin + forTokens:end + forTokens:step + param:encode + param:name + param:value + redirect:context + redirect:url + set:property + set:target + set:value + url:context + url:value + when:test + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + catch + org.apache.taglibs.standard.tag.common.core.CatchTag + JSP + + Catches any Throwable that occurs in its body and optionally + exposes it. + + + var + false + false + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + out + org.apache.taglibs.standard.tag.el.core.OutTag + JSP + + Like <%= ... >, but for expressions. + + + value + true + false + + + default + false + false + + + escapeXml + false + false + + + + + if + org.apache.taglibs.standard.tag.el.core.IfTag + JSP + + 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 + + + test + true + false + + + var + false + false + + + scope + false + false + + + + + import + org.apache.taglibs.standard.tag.el.core.ImportTag + org.apache.taglibs.standard.tei.ImportTEI + JSP + + Retrieves an absolute or relative URL and exposes its contents + to either the page, a String in 'var', or a Reader in 'varReader'. + + + url + true + false + + + var + false + false + + + scope + false + false + + + varReader + false + false + + + context + false + false + + + charEncoding + false + false + + + + + forEach + org.apache.taglibs.standard.tag.el.core.ForEachTag + org.apache.taglibs.standard.tei.ForEachTEI + JSP + + The basic iteration tag, accepting many different + collection types and supporting subsetting and other + functionality + + + items + false + false + + + begin + false + false + + + end + false + false + + + step + false + false + + + var + false + false + + + varStatus + false + false + + + + + forTokens + org.apache.taglibs.standard.tag.el.core.ForTokensTag + JSP + + Iterates over tokens, separated by the supplied delimeters + + + items + true + false + + + delims + true + false + + + begin + false + false + + + end + false + false + + + step + false + false + + + var + false + false + + + varStatus + false + false + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.el.core.ParamTag + JSP + + Adds a parameter to a containing 'import' tag's URL. + + + name + true + false + + + value + false + false + + + + + redirect + org.apache.taglibs.standard.tag.el.core.RedirectTag + JSP + + Redirects to a new URL. + + + var + false + false + + + scope + false + false + + + url + true + false + + + context + false + false + + + + + remove + org.apache.taglibs.standard.tag.common.core.RemoveTag + empty + + Removes a scoped variable (from a particular scope, if specified). + + + var + true + false + + + scope + false + false + + + + + set + org.apache.taglibs.standard.tag.el.core.SetTag + JSP + + Sets the result of an expression evaluation in a 'scope' + + + var + false + false + + + value + false + false + + + target + false + false + + + property + false + false + + + scope + false + false + + + + + url + org.apache.taglibs.standard.tag.el.core.UrlTag + JSP + + Prints or exposes a URL with optional query parameters + (via the c:param tag). + + + var + false + false + + + scope + false + false + + + value + true + false + + + context + false + false + + + + + when + org.apache.taglibs.standard.tag.el.core.WhenTag + JSP + + Subtag of <choose> that includes its body if its + condition evalutes to 'true' + + + test + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/fmt-1_0.tld b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/fmt-1_0.tld new file mode 100644 index 000000000..59386c508 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/fmt-1_0.tld @@ -0,0 +1,458 @@ + + + + + 1.0 + 1.2 + fmt + http://java.sun.com/jstl/fmt + JSTL fmt + JSTL 1.0 i18n-capable formatting library + + + + org.apache.taglibs.standard.tlv.el.JstlELFmtTLV + + + expressionAttributes + + requestEncoding:value + setLocale:value + setLocale:variant + timeZone:value + setTimeZone:value + bundle:basename + bundle:prefix + setBundle:basename + message:key + message:bundle + param:value + formatNumber:value + formatNumber:pattern + formatNumber:currencyCode + formatNumber:currencySymbol + formatNumber:groupingUsed + formatNumber:maxIntegerDigits + formatNumber:minIntegerDigits + formatNumber:maxFractionDigits + formatNumber:minFractionDigits + parseNumber:value + parseNumber:pattern + parseNumber:parseLocale + parseNumber:integerOnly + formatDate:value + formatDate:pattern + formatDate:timeZone + parseDate:value + parseDate:pattern + parseDate:timeZone + parseDate:parseLocale + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + requestEncoding + org.apache.taglibs.standard.tag.el.fmt.RequestEncodingTag + empty + + Sets the request character encoding + + + value + false + false + + + + + setLocale + org.apache.taglibs.standard.tag.el.fmt.SetLocaleTag + empty + + Stores the given locale in the locale configuration variable + + + value + true + false + + + variant + false + false + + + scope + false + false + + + + + timeZone + org.apache.taglibs.standard.tag.el.fmt.TimeZoneTag + JSP + + Specifies the time zone for any time formatting or parsing actions + nested in its body + + + value + true + false + + + + + setTimeZone + org.apache.taglibs.standard.tag.el.fmt.SetTimeZoneTag + empty + + Stores the given time zone in the time zone configuration variable + + + value + true + false + + + var + false + false + + + scope + false + false + + + + + bundle + org.apache.taglibs.standard.tag.el.fmt.BundleTag + JSP + + Loads a resource bundle to be used by its tag body + + + basename + true + false + + + prefix + false + false + + + + + setBundle + org.apache.taglibs.standard.tag.el.fmt.SetBundleTag + empty + + Loads a resource bundle and stores it in the named scoped variable or + the bundle configuration variable + + + basename + true + false + + + var + false + false + + + scope + false + false + + + + + message + org.apache.taglibs.standard.tag.el.fmt.MessageTag + JSP + + Maps key to localized message and performs parametric replacement + + + key + false + false + + + bundle + false + false + + + var + false + false + + + scope + false + false + + + + + param + org.apache.taglibs.standard.tag.el.fmt.ParamTag + JSP + + Supplies an argument for parametric replacement to a containing + <message> tag + + + value + false + false + + + + + formatNumber + org.apache.taglibs.standard.tag.el.fmt.FormatNumberTag + JSP + + Formats a numeric value as a number, currency, or percentage + + + value + false + false + + + type + false + false + + + pattern + false + false + + + currencyCode + false + false + + + currencySymbol + false + false + + + groupingUsed + false + false + + + maxIntegerDigits + false + false + + + minIntegerDigits + false + false + + + maxFractionDigits + false + false + + + minFractionDigits + false + false + + + var + false + false + + + scope + false + false + + + + + parseNumber + org.apache.taglibs.standard.tag.el.fmt.ParseNumberTag + JSP + + Parses the string representation of a number, currency, or percentage + + + value + false + false + + + type + false + false + + + pattern + false + false + + + parseLocale + false + false + + + integerOnly + false + false + + + var + false + false + + + scope + false + false + + + + + formatDate + org.apache.taglibs.standard.tag.el.fmt.FormatDateTag + empty + + Formats a date and/or time using the supplied styles and pattern + + + value + true + false + + + type + false + false + + + dateStyle + false + false + + + timeStyle + false + false + + + pattern + false + false + + + timeZone + false + false + + + var + false + false + + + scope + false + false + + + + + parseDate + org.apache.taglibs.standard.tag.el.fmt.ParseDateTag + JSP + + Parses the string representation of a date and/or time + + + value + false + false + + + type + false + false + + + dateStyle + false + false + + + timeStyle + false + false + + + pattern + false + false + + + timeZone + false + false + + + parseLocale + false + false + + + var + false + false + + + scope + false + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/sql-1_0.tld b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/sql-1_0.tld new file mode 100644 index 000000000..8a35767ea --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/sql-1_0.tld @@ -0,0 +1,229 @@ + + + + + 1.0 + 1.2 + sql + http://java.sun.com/jstl/sql + JSTL sql + JSTL 1.0 sql library + + + + org.apache.taglibs.standard.tlv.el.JstlELSqlTLV + + + expressionAttributes + + transaction:dataSource + transaction:isolation + query:sql + query:dataSource + query:startRow + query:maxRows + update:sql + update:dataSource + param:value + dateParam:value + dateParam:type + setDataSource:dataSource + setDataSource:driver + setDataSource:url + setDataSource:user + setDataSource:password + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + transaction + org.apache.taglibs.standard.tag.el.sql.TransactionTag + JSP + + Provides nested database action elements with a shared Connection, + set up to execute all statements as one transaction. + + + dataSource + false + false + + + isolation + false + false + + + + + query + org.apache.taglibs.standard.tag.el.sql.QueryTag + JSP + + Executes the SQL query defined in its body or through the + sql attribute. + + + var + true + false + + + scope + false + false + + + sql + false + false + + + dataSource + false + false + + + startRow + false + false + + + maxRows + false + false + + + + + update + org.apache.taglibs.standard.tag.el.sql.UpdateTag + JSP + + Executes the SQL update defined in its body or through the + sql attribute. + + + var + false + false + + + scope + false + false + + + sql + false + false + + + dataSource + false + false + + + + + param + org.apache.taglibs.standard.tag.el.sql.ParamTag + JSP + + Sets a parameter in an SQL statement to the specified value. + + + value + false + false + + + + + dateParam + org.apache.taglibs.standard.tag.el.sql.DateParamTag + empty + + Sets a parameter in an SQL statement to the specified java.util.Date val + ue. + + + value + true + true + + + type + false + true + + + + + setDataSource + org.apache.taglibs.standard.tag.el.sql.SetDataSourceTag + empty + + Creates a simple DataSource suitable only for prototyping. + + + var + false + false + + + scope + false + false + + + dataSource + false + false + + + driver + false + false + + + url + false + false + + + user + false + false + + + password + false + false + + + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/x-1_0.tld b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/x-1_0.tld new file mode 100644 index 000000000..17996ee71 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/META-INF/x-1_0.tld @@ -0,0 +1,289 @@ + + + + + 1.0 + 1.2 + x + http://java.sun.com/jstl/xml + JSTL XML + JSTL 1.0 XML library + + + + org.apache.taglibs.standard.tlv.el.JstlELXmlTLV + + + expressionAttributes + + out:escapeXml + parse:xml + parse:systemId + parse:filter + transform:xml + transform:xmlSystemId + transform:xslt + transform:xsltSystemId + transform:result + + + Whitespace-separated list of colon-separated token pairs + describing tag:attribute combinations that accept expressions. + The validator uses this information to determine which + attributes need their syntax validated. + + + + + + choose + org.apache.taglibs.standard.tag.common.core.ChooseTag + JSP + + Simple conditional tag that establishes a context for + mutually exclusive conditional operations, marked by + <when> and <otherwise> + + + + + out + org.apache.taglibs.standard.tag.el.xml.ExprTag + empty + + Like <%= ... >, but for XPath expressions. + + + select + true + false + + + escapeXml + false + false + + + + + if + org.apache.taglibs.standard.tag.common.xml.IfTag + JSP + + XML conditional tag, which evalutes its body if the + supplied XPath expression evalutes to 'true' as a boolean + + + select + true + false + + + var + false + false + + + scope + false + false + + + + + forEach + org.apache.taglibs.standard.tag.common.xml.ForEachTag + JSP + + XML iteration tag. + + + var + false + false + + + select + true + false + + + + + otherwise + org.apache.taglibs.standard.tag.common.core.OtherwiseTag + JSP + + Subtag of <choose> that follows <when> tags + and runs only if all of the prior conditions evaluated to + 'false' + + + + + param + org.apache.taglibs.standard.tag.el.xml.ParamTag + JSP + + Adds a parameter to a containing 'transform' tag's Transformer + + + name + true + false + + + value + false + false + + + + + parse + org.apache.taglibs.standard.tag.el.xml.ParseTag + org.apache.taglibs.standard.tei.XmlParseTEI + JSP + + Parses XML content from 'source' attribute or 'body' + + + var + false + false + + + varDom + false + false + + + scope + false + false + + + scopeDom + false + false + + + xml + false + false + + + systemId + false + false + + + filter + false + false + + + + + set + org.apache.taglibs.standard.tag.common.xml.SetTag + empty + + Saves the result of an XPath expression evaluation in a 'scope' + + + var + true + false + + + select + false + false + + + scope + false + false + + + + + transform + org.apache.taglibs.standard.tag.el.xml.TransformTag + org.apache.taglibs.standard.tei.XmlTransformTEI + JSP + + Conducts a transformation given a source XML document + and an XSLT stylesheet + + + var + false + false + + + scope + false + false + + + result + false + false + + + xml + false + false + + + xmlSystemId + false + false + + + xslt + false + false + + + xsltSystemId + false + false + + + + + when + org.apache.taglibs.standard.tag.common.xml.WhenTag + JSP + + Subtag of <choose> that includes its body if its + expression evalutes to 'true' + + + select + true + false + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources.properties b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources.properties new file mode 100644 index 000000000..59d9d26a8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources.properties @@ -0,0 +1,156 @@ +# 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. + +EXCEPTION_GETTING_BEANINFO=\ + An Exception occurred getting the BeanInfo for class {0} + +NULL_EXPRESSION_STRING=\ + A null expression string may not be passed to the \ + expression evaluator + +PARSE_EXCEPTION=\ + Encountered "{1}", expected one of [{0}] + +CANT_GET_PROPERTY_OF_NULL=\ + Attempt to get property "{0}" from a null value + +NO_SUCH_PROPERTY=\ + Class {0} does not have a property "{1}" + +NO_GETTER_METHOD=\ + Property "{0}" of class {1} does not have a public getter method + +ERROR_GETTING_PROPERTY=\ + An error occurred while getting property "{0}" from an instance \ + of class {1} + +CANT_GET_INDEXED_VALUE_OF_NULL=\ + Attempt to apply the "{0}" operator to a null value + +CANT_GET_NULL_INDEX=\ + Attempt to apply a null index to the "{0}" operator + +NULL_INDEX=\ + The index supplied to the "{0}" operator may not be null + +BAD_INDEX_VALUE=\ + The "{0}" operator was supplied with an index value of type \ + "{1}" to be applied to a List or array, but \ + that value cannot be converted to an integer. + +EXCEPTION_ACCESSING_LIST=\ + An exception occurred while trying to access index {0} of a \ + List + +EXCEPTION_ACCESSING_ARRAY=\ + An exception occurred while trying to access index {0} of an \ + Array + +CANT_FIND_INDEX=\ + Unable to find a value for "{0}" in object of class "{1}" using \ + operator "{2}" + +TOSTRING_EXCEPTION=\ + An object of type "{0}" threw an exception in its toString() \ + method while trying to be coerced to a String + +BOOLEAN_TO_NUMBER=\ + Attempt to coerce a boolean value "{0}" to type \ + "{1}" + +STRING_TO_NUMBER_EXCEPTION=\ + An exception occured trying to convert String "{0}" to type "{1}" + +COERCE_TO_NUMBER=\ + Attempt to coerce a value of type "{0}" to type "{1}" + +BOOLEAN_TO_CHARACTER=\ + Attempt to coerce a boolean value "{0}" to type Character + +EMPTY_STRING_TO_CHARACTER=\ + Attempt to coerce an empty String to type Character + +COERCE_TO_CHARACTER=\ + Attempt to coerce a value of type "{0}" to Character + +NULL_TO_BOOLEAN=\ + Attempt to coerce a null value to a Boolean + +STRING_TO_BOOLEAN=\ + An exception occurred trying to convert String "{0}" to type Boolean + +COERCE_TO_BOOLEAN=\ + Attempt to coerce a value of type "{0}" to Boolean + +COERCE_TO_OBJECT=\ + Attempt to coerce a value of type "{0}" to type "{1}" + +NO_PROPERTY_EDITOR=\ + Attempt to convert String "{0}" to type "{1}", but there is \ + no PropertyEditor for that type + +PROPERTY_EDITOR_ERROR=\ + Unable to parse value "{0}" into expected type "{1}" + +ARITH_OP_NULL=\ + Attempt to apply operator "{0}" to null value + +ARITH_OP_BAD_TYPE=\ + Attempt to apply operator "{0}" to arguments of type "{1}" \ + and "{2}" + +ARITH_ERROR=\ + An error occurred applying operator "{0}" to operands "{1}" \ + and "{2}" + +ERROR_IN_EQUALS= + An error occurred calling equals() on an object of type "{0}" \ + when comparing with an object of type "{1}" for operator "{2}" + +UNARY_OP_BAD_TYPE=\ + Attempt to apply operator "{0}" to arguments of type "{1}" + +NAMED_VALUE_NOT_FOUND=\ + Unable to find a value for name "{0}" + +CANT_GET_INDEXED_PROPERTY=\ + An error occurred obtaining the indexed property value of an \ + object of type "{0}" with index "{1}" + +COMPARABLE_ERROR=\ + An exception occurred while trying to compare a value of \ + Comparable type "{0}" with a value of type "{1}" for operator \ + "{2}" + +BAD_IMPLICIT_OBJECT=\ + No such implicit object "{0}" - the only implicit objects are: \ + {1} + +ATTRIBUTE_EVALUATION_EXCEPTION=\ + An error occurred while evaluating custom action attribute "{0}" \ + with value "{1}": {2} ({3}) + +ATTRIBUTE_PARSE_EXCEPTION=\ + An error occurred while parsing custom action attribute "{0}" \ + with value "{1}": {2} + +UNKNOWN_FUNCTION=\ + No function is mapped to the name "{1}" + +INAPPROPRIATE_FUNCTION_ARG_COUNT=\ + The function "{1}" requires {2} arguments but was passed {3} + +FUNCTION_INVOCATION_ERROR=\ + An error occurred while evaluating function "{0}" diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources_ja.properties b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources_ja.properties new file mode 100644 index 000000000..9ac1f2179 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/main/resources/org/apache/taglibs/standard/lang/jstl/Resources_ja.properties @@ -0,0 +1,137 @@ +# 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. + +EXCEPTION_GETTING_BEANINFO=\ + \u30af\u30e9\u30b9 {0} \u306e BeanInfo \u3092\u53d6\u5f97\u3059\u308b\u904e\u7a0b\u3067\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +NULL_EXPRESSION_STRING=\ + null \u306e\u5f0f\u6587\u5b57\u5217\u306f\u3001\u5f0f\u306e\u8a55\u4fa1\u3068\u3057\u3066\u901a\u3089\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093 + +PARSE_EXCEPTION=\ + [{0}] \u306e\uff11\u3064\u3092\u671f\u5f85\u3057\u307e\u3057\u305f\u304c\u3001"{1}" \u306b\u906d\u9047\u3057\u307e\u3057\u305f + +CANT_GET_PROPERTY_OF_NULL=\ + null \u5024\u3088\u308a\u30d7\u30ed\u30d1\u30c6\u30a3 "{0}" \u3092\u53d6\u5f97\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +NO_SUCH_PROPERTY=\ + \u30af\u30e9\u30b9 {0} \u306b\u306f\u3001\u30d7\u30ed\u30d1\u30c6\u30a3 "{1}" \u304c\u5b58\u5728\u3057\u307e\u305b\u3093 + +NO_GETTER_METHOD=\ + \u30af\u30e9\u30b9 {1} \u306b\u3042\u308b\u30d7\u30ed\u30d1\u30c6\u30a3 "{0}" \u7528\u306e public \u3067\u5ba3\u8a00\u3055\u308c\u305f getter \u30e1\u30bd\u30c3\u30c9\u304c\u3042\u308a\u307e\u305b\u3093 + +ERROR_GETTING_PROPERTY=\ + \u30af\u30e9\u30b9 {1} \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304b\u3089\u30d7\u30ed\u30d1\u30c6\u30a3 "{0}" \u3092\u53d6\u5f97\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +CANT_GET_INDEXED_VALUE_OF_NULL=\ + null \u5024\u306b\u5bfe\u3057\u3066 "{0}" \u30aa\u30da\u30ec\u30fc\u30bf\u3092\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +CANT_GET_NULL_INDEX=\ + "{0}" \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u3066 null \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +NULL_INDEX=\ + "{0}" \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u5bfe\u3057\u3066\u4f9b\u7d66\u3055\u308c\u305f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f null \u3067\u3042\u3063\u3066\u306f\u3044\u3051\u307e\u305b\u3093 + +BAD_INDEX_VALUE=\ + "{0}" \u30aa\u30da\u30ec\u30fc\u30bf\u306b\u3088\u3063\u3066 List \u3082\u3057\u304f\u306f\u914d\u5217\u306b\u9069\u7528\u3055\u308c\u305f "{1}" \u578b\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5024\u3092\u4f9b\u7d66\u3057\u307e\u3057\u305f\u304c\u3001\u305d\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u5024\u3092\u6574\u6570\u5024\u3078\u5909\u63db\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 + +EXCEPTION_ACCESSING_LIST=\ + List \u306e\u4e2d\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 {0} \u3078\u30a2\u30af\u30bb\u30b9\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +EXCEPTION_ACCESSING_ARRAY=\ + Array \u306e\u4e2d\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9 {0} \u3078\u30a2\u30af\u30bb\u30b9\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +CANT_FIND_INDEX=\ + \u30aa\u30da\u30ec\u30fc\u30bf "{2}" \u3092\u5229\u7528\u3057\u307e\u3057\u305f\u304c\u3001\u30af\u30e9\u30b9 "{1}" \u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u304a\u3044\u3066 "{0}" \u306b\u5bfe\u5fdc\u3059\u308b\u5024\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 + +TOSTRING_EXCEPTION=\ + "{0}" \u578b\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3092 String \u306b\u5909\u63db\u3059\u308b\u904e\u7a0b\u306b\u304a\u3044\u3066\u3001\u3053\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e toString() \u30e1\u30bd\u30c3\u30c9\u304c\u4f8b\u5916\u3092\u30b9\u30ed\u30fc\u3057\u307e\u3057\u305f + +BOOLEAN_TO_NUMBER=\ + boolean \u5024 "{0}" \u3092 "{1}" \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +STRING_TO_NUMBER_EXCEPTION=\ + String "{0}" \u3092 "{1}" \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u305f\u969b\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +COERCE_TO_NUMBER=\ + "{0}" \u578b\u306e\u5024\u3092 "{1}" \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +BOOLEAN_TO_CHARACTER=\ + boolean \u5024 "{0}" \u3092 Character \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +EMPTY_STRING_TO_CHARACTER=\ + \u7a7a\u306e String \u3092 Character \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +COERCE_TO_CHARACTER=\ + "{0}" \u578b\u306e\u5024\u3092 Character \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +NULL_TO_BOOLEAN=\ + null \u5024\u3092 Boolean \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +STRING_TO_BOOLEAN=\ + String "{0}" \u3092 Boolean \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u305f\u969b\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +COERCE_TO_BOOLEAN=\ + "{0}" \u578b\u306e\u5024\u3092 Boolean \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +COERCE_TO_OBJECT=\ + "{0}" \u578b\u306e\u5024\u3092 "{1}" \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +NO_PROPERTY_EDITOR=\ + String "{0}" \u3092 "{1}" \u578b\u306b\u5909\u63db\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001\u305d\u306e\u578b\u306b\u5bfe\u5fdc\u3059\u308b PropertyEditor \u304c\u5b58\u5728\u3057\u307e\u305b\u3093 + +PROPERTY_EDITOR_ERROR=\ + \u5024 "{0}" \u3092\u69cb\u6587\u89e3\u6790\u3057\u307e\u3057\u305f\u304c\u3001\u671f\u5f85\u3055\u308c\u308b "{1}" \u578b\u306b\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093 + +ARITH_OP_NULL=\ + null \u5024\u306b\u5bfe\u3057\u3066\u30aa\u30da\u30ec\u30fc\u30bf "{0}" \u3092\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +ARITH_OP_BAD_TYPE=\ + "{1}" \u578b\u304a\u3088\u3073 "{2}" \u578b\u306e\u5909\u6570\u306b\u5bfe\u3057\u3066\u30aa\u30da\u30ec\u30fc\u30bf "{0}" \u3092\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +ARITH_ERROR=\ + \u30aa\u30da\u30e9\u30f3\u30c9 "{1}" \u304a\u3088\u3073 "{2}" \u306b\u5bfe\u3057\u3066\u30aa\u30da\u30ec\u30fc\u30bf {0} \u3092\u9069\u7528\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +ERROR_IN_EQUALS=\ + \u30aa\u30da\u30ec\u30fc\u30bf "{2}" \u306b\u5bfe\u3057\u3066 "{1}" \u578b\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u3068\u6bd4\u8f03\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u304c\u3001"{0}" \u578b\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e equals() \u30e1\u30bd\u30c3\u30c9\u3092\u547c\u3073\u51fa\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +UNARY_OP_BAD_TYPE=\ + "{1}" \u578b\u306e\u5909\u6570\u306b\u5bfe\u3057\u3066\u30aa\u30da\u30ec\u30fc\u30bf "{0}" \u3092\u9069\u7528\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059 + +NAMED_VALUE_NOT_FOUND=\ + \u540d\u79f0 "{0}" \u306b\u5bfe\u5fdc\u3059\u308b\u5024\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093 + +CANT_GET_INDEXED_PROPERTY=\ + \u30a4\u30f3\u30c7\u30c3\u30af\u30b9 "{1}" \u3092\u4ed8\u4e0e\u3057\u305f "{0}" \u578b\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30fb\u30d7\u30ed\u30d1\u30c6\u30a3\u5024\u3092\u5f97\u3088\u3046\u3068\u3057\u305f\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +COMPARABLE_ERROR=\ + \u30aa\u30da\u30ec\u30fc\u30bf "{2}" \u306b\u5bfe\u3057\u3066 Comparable \u578b\u3067\u3042\u308b "{0}" \u306e\u5024\u3068 "{1}" \u578b\u306e\u5024\u3068\u3092\u6bd4\u8f03\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f + +BAD_IMPLICIT_OBJECT=\ + \u305d\u306e\u3088\u3046\u306a\u6697\u9ed9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8 "{0}" \u306f\u5b58\u5728\u3057\u307e\u305b\u3093 - \u552f\u4e00\u306e\u6697\u9ed9\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059: {1} + +ATTRIBUTE_EVALUATION_EXCEPTION=\ + \u5024 "{1}" \u306e\u30bb\u30c3\u30c8\u3055\u308c\u305f\u30ab\u30b9\u30bf\u30e0\u30fb\u30a2\u30af\u30b7\u30e7\u30f3\u5c5e\u6027 "{0}" \u3092\u8a55\u4fa1\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {2} ({3}) + +ATTRIBUTE_PARSE_EXCEPTION=\ + \u5024 "{1}" \u306e\u30bb\u30c3\u30c8\u3055\u308c\u305f\u30ab\u30b9\u30bf\u30e0\u30fb\u30a2\u30af\u30b7\u30e7\u30f3\u5c5e\u6027 "{0}" \u3092\u69cb\u6587\u89e3\u6790\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {2} + +UNKNOWN_FUNCTION=\ + "{1}" \u3068\u3044\u3046\u95a2\u6570\u540d\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 + +INAPPROPRIATE_FUNCTION_ARG_COUNT=\ + \u95a2\u6570 "{1}" \u3067\u306f\u3001{2}\u500b\u306e\u5f15\u6570\u3092\u5fc5\u8981\u3068\u3057\u307e\u3059\u304c\u3001{3} \u3092\u901a\u3057\u307e\u3057\u305f\u3002 + +FUNCTION_INVOCATION_ERROR=\ + \u95a2\u6570 "{0}" \u3092\u8a55\u4fa1\u3057\u3066\u3044\u308b\u904e\u7a0b\u3067\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean1.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean1.java new file mode 100644 index 000000000..c587a87ce --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean1.java @@ -0,0 +1,370 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.util.List; +import java.util.Map; + +/** + *

This is a test bean with a set of properties + * + * @author Nathan Abramson - Art Technology Group + */ + +public class Bean1 { + //------------------------------------- + // Properties + //------------------------------------- + // property boolean1 + + boolean mBoolean1; + + public boolean getBoolean1() { + return mBoolean1; + } + + public void setBoolean1(boolean pBoolean1) { + mBoolean1 = pBoolean1; + } + + //------------------------------------- + // property byte1 + + byte mByte1; + + public byte getByte1() { + return mByte1; + } + + public void setByte1(byte pByte1) { + mByte1 = pByte1; + } + + //------------------------------------- + // property char1 + + char mChar1; + + public char getChar1() { + return mChar1; + } + + public void setChar1(char pChar1) { + mChar1 = pChar1; + } + + //------------------------------------- + // property short1 + + short mShort1; + + public short getShort1() { + return mShort1; + } + + public void setShort1(short pShort1) { + mShort1 = pShort1; + } + + //------------------------------------- + // property int1 + + int mInt1; + + public int getInt1() { + return mInt1; + } + + public void setInt1(int pInt1) { + mInt1 = pInt1; + } + + //------------------------------------- + // property long1 + + long mLong1; + + public long getLong1() { + return mLong1; + } + + public void setLong1(long pLong1) { + mLong1 = pLong1; + } + + //------------------------------------- + // property float1 + + float mFloat1; + + public float getFloat1() { + return mFloat1; + } + + public void setFloat1(float pFloat1) { + mFloat1 = pFloat1; + } + + //------------------------------------- + // property double1 + + double mDouble1; + + public double getDouble1() { + return mDouble1; + } + + public void setDouble1(double pDouble1) { + mDouble1 = pDouble1; + } + + //------------------------------------- + // property boolean2 + + Boolean mBoolean2; + + public Boolean getBoolean2() { + return mBoolean2; + } + + public void setBoolean2(Boolean pBoolean2) { + mBoolean2 = pBoolean2; + } + + //------------------------------------- + // property byte2 + + Byte mByte2; + + public Byte getByte2() { + return mByte2; + } + + public void setByte2(Byte pByte2) { + mByte2 = pByte2; + } + + //------------------------------------- + // property char2 + + Character mChar2; + + public Character getChar2() { + return mChar2; + } + + public void setChar2(Character pChar2) { + mChar2 = pChar2; + } + + //------------------------------------- + // property short2 + + Short mShort2; + + public Short getShort2() { + return mShort2; + } + + public void setShort2(Short pShort2) { + mShort2 = pShort2; + } + + //------------------------------------- + // property int2 + + Integer mInt2; + + public Integer getInt2() { + return mInt2; + } + + public void setInt2(Integer pInt2) { + mInt2 = pInt2; + } + + //------------------------------------- + // property long2 + + Long mLong2; + + public Long getLong2() { + return mLong2; + } + + public void setLong2(Long pLong2) { + mLong2 = pLong2; + } + + //------------------------------------- + // property float2 + + Float mFloat2; + + public Float getFloat2() { + return mFloat2; + } + + public void setFloat2(Float pFloat2) { + mFloat2 = pFloat2; + } + + //------------------------------------- + // property double2 + + Double mDouble2; + + public Double getDouble2() { + return mDouble2; + } + + public void setDouble2(Double pDouble2) { + mDouble2 = pDouble2; + } + + //------------------------------------- + // property string1 + + String mString1; + + public String getString1() { + return mString1; + } + + public void setString1(String pString1) { + mString1 = pString1; + } + + //------------------------------------- + // property string2 + + String mString2; + + public String getString2() { + return mString2; + } + + public void setString2(String pString2) { + mString2 = pString2; + } + + //------------------------------------- + // property bean1 + + Bean1 mBean1; + + public Bean1 getBean1() { + return mBean1; + } + + public void setBean1(Bean1 pBean1) { + mBean1 = pBean1; + } + + //------------------------------------- + // property bean2 + + Bean1 mBean2; + + public Bean1 getBean2() { + return mBean2; + } + + public void setBean2(Bean1 pBean2) { + mBean2 = pBean2; + } + + //------------------------------------- + // property noGetter + + String mNoGetter; + + public void setNoGetter(String pNoGetter) { + mNoGetter = pNoGetter; + } + + //------------------------------------- + // property errorInGetter + + String mErrorInGetter; + + public String getErrorInGetter() { + throw new NullPointerException("Error!"); + } + + //------------------------------------- + // property stringArray1 + + String[] mStringArray1; + + public String[] getStringArray1() { + return mStringArray1; + } + + public void setStringArray1(String[] pStringArray1) { + mStringArray1 = pStringArray1; + } + + //------------------------------------- + // property list1 + + List mList1; + + public List getList1() { + return mList1; + } + + public void setList1(List pList1) { + mList1 = pList1; + } + + //------------------------------------- + // property map1 + + Map mMap1; + + public Map getMap1() { + return mMap1; + } + + public void setMap1(Map pMap1) { + mMap1 = pMap1; + } + + //------------------------------------- + // property indexed1 + + public String getIndexed1(int pIndex) { + return mStringArray1[pIndex]; + } + + //------------------------------------- + // Member variables + //------------------------------------- + + //------------------------------------- + + /** + * Constructor + */ + public Bean1() { + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2.java new file mode 100644 index 000000000..18de6fe49 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2.java @@ -0,0 +1,63 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +/** + *

This is a test bean that holds a single String + * + * @author Nathan Abramson - Art Technology Group + */ + +public class Bean2 { + //------------------------------------- + // Properties + //------------------------------------- + // property value + + String mValue; + + public String getValue() { + return mValue; + } + + public void setValue(String pValue) { + mValue = pValue; + } + + //------------------------------------- + // Member variables + //------------------------------------- + + //------------------------------------- + + /** + * Constructor + */ + public Bean2(String pValue) { + mValue = pValue; + } + + //------------------------------------- + + public String toString() { + return ("Bean2[" + mValue + "]"); + } + + //------------------------------------- + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2Editor.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2Editor.java new file mode 100644 index 000000000..faaf27903 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/Bean2Editor.java @@ -0,0 +1,42 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.beans.PropertyEditorSupport; + +/** + * PropertyEditor for parsing Bean2 + * + * @author Nathan Abramson - Art Technology Group + */ + +public class Bean2Editor + extends PropertyEditorSupport { + //------------------------------------- + + public void setAsText(String pText) + throws IllegalArgumentException { + if ("badvalue".equals(pText)) { + throw new IllegalArgumentException("Bad value " + pText); + } else { + setValue(new Bean2(pText)); + } + } + + //------------------------------------- +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/EvaluationTest.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/EvaluationTest.java new file mode 100644 index 000000000..4a4388671 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/EvaluationTest.java @@ -0,0 +1,736 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.PageContext; + +import junit.framework.TestCase; +import org.apache.taglibs.standard.lang.jstl.Evaluator; +import org.apache.taglibs.standard.lang.jstl.test.beans.Factory; + +/** + * Tests for EL Evaluation based on previous golden files. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class EvaluationTest extends TestCase { + + private PageContext context; + private Evaluator e; + + @Override + protected void setUp() throws Exception { + super.setUp(); + context = createTestContext(); + e = new Evaluator(); + } + + public void testBasicLiterals() throws JspException { + assertEquals(1, e.evaluate("test", "${1}", Integer.TYPE, null, context)); + assertEquals(-12, e.evaluate("test", "${-12}", Integer.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${true}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${false}", Boolean.TYPE, null, context)); + assertEquals("", e.evaluate("test", "${null}", String.class, null, context)); + assertEquals(4.2, e.evaluate("test", "${4.2}", Double.TYPE, null, context)); + assertEquals(-21.3f, e.evaluate("test", "${-21.3}", Float.TYPE, null, context)); + assertEquals(4.0f, e.evaluate("test", "${4.}", Float.TYPE, null, context)); + assertEquals(0.21f, e.evaluate("test", "${.21}", Float.TYPE, null, context)); + assertEquals(0.3, e.evaluate("test", "${3e-1}", Double.TYPE, null, context)); + assertEquals(0.2222222222, e.evaluate("test", "${.2222222222}", Double.TYPE, null, context)); + } + + public void testBasicRelationalsBetweenLiterals() throws JspException { + assertEquals(true, e.evaluate("test", "${1 < 2}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${1 > 2}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${1 >= 2}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${1 <= 2}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${1 == 2}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${1 != 2}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${3 >= 3}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${3 <= 3}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${3 == 3}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${3 < 3}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${3 > 3}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${3 != 3}", Boolean.TYPE, null, context)); + } + + public void testBasicRelationalsBetweenBooleans() throws JspException { + // next two tests pass on Java5 or later as Boolean now implements Comparable + assertEquals(true, e.evaluate("test", "${false < true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${false > true}", Object.class, null, context)); + + assertEquals(true, e.evaluate("test", "${true >= true}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${true <= true}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${true == true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${true != true}", Object.class, null, context)); + } + + public void testLookingUpObjectsInScopes() throws JspException { + assertEquals("page-scoped1", e.evaluate("test", "${pageScope.val1a}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${requestScope.val1a}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${sessionScope.val1a}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${applicationScope.val1a}", String.class, null, context)); + assertEquals("page-scoped1", e.evaluate("test", "${val1a}", String.class, null, context)); + + assertEquals("", e.evaluate("test", "${pageScope.val1b}", String.class, null, context)); + assertEquals("request-scoped1", e.evaluate("test", "${requestScope.val1b}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${sessionScope.val1b}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${applicationScope.val1b}", String.class, null, context)); + assertEquals("request-scoped1", e.evaluate("test", "${val1b}", String.class, null, context)); + + assertEquals("", e.evaluate("test", "${pageScope.val1c}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${requestScope.val1c}", String.class, null, context)); + assertEquals("session-scoped1", e.evaluate("test", "${sessionScope.val1c}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${applicationScope.val1c}", String.class, null, context)); + assertEquals("session-scoped1", e.evaluate("test", "${val1c}", String.class, null, context)); + + assertEquals("", e.evaluate("test", "${pageScope.val1d}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${requestScope.val1d}", String.class, null, context)); + assertEquals("", e.evaluate("test", "${sessionScope.val1d}", String.class, null, context)); + assertEquals("app-scoped1", e.evaluate("test", "${applicationScope.val1d}", String.class, null, context)); + assertEquals("app-scoped1", e.evaluate("test", "${val1d}", String.class, null, context)); + } + + public void testAccessingProperties() throws JspException { + assertEquals(4, e.evaluate("test", "${bean1a.int1}", Integer.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.boolean1}", Boolean.TYPE, null, context)); + assertEquals("hello", e.evaluate("test", "${bean1a.string1}", String.class, null, context)); + assertEquals(-224, e.evaluate("test", "${bean1a.bean1.int2}", Integer.TYPE, null, context)); + assertEquals("bean3's string", e.evaluate("test", "${bean1a.bean1.bean2.string2}", String.class, null, context)); + } + + public void testEntireConversionMatrix() throws JspException { + assertEquals((byte) 12, e.evaluate("test", "${bean1a.byte1}", Byte.TYPE, null, context)); + assertEquals('\14', e.evaluate("test", "${bean1a.byte1}", Character.TYPE, null, context)); + assertEquals((short) 12, e.evaluate("test", "${bean1a.byte1}", Short.TYPE, null, context)); + assertEquals(12, e.evaluate("test", "${bean1a.byte1}", Integer.TYPE, null, context)); + assertEquals(12l, e.evaluate("test", "${bean1a.byte1}", Long.TYPE, null, context)); + assertEquals(12.0f, e.evaluate("test", "${bean1a.byte1}", Float.TYPE, null, context)); + assertEquals(12.0, e.evaluate("test", "${bean1a.byte1}", Double.TYPE, null, context)); + + assertEquals((byte) 98, e.evaluate("test", "${bean1a.char1}", Byte.TYPE, null, context)); + assertEquals('b', e.evaluate("test", "${bean1a.char1}", Character.TYPE, null, context)); + assertEquals((short) 98, e.evaluate("test", "${bean1a.char1}", Short.TYPE, null, context)); + assertEquals(98, e.evaluate("test", "${bean1a.char1}", Integer.TYPE, null, context)); + assertEquals(98l, e.evaluate("test", "${bean1a.char1}", Long.TYPE, null, context)); + assertEquals(98.0f, e.evaluate("test", "${bean1a.char1}", Float.TYPE, null, context)); + assertEquals(98.0, e.evaluate("test", "${bean1a.char1}", Double.TYPE, null, context)); + + assertEquals((byte) -124, e.evaluate("test", "${bean1a.short1}", Byte.TYPE, null, context)); + assertEquals((char) -124, e.evaluate("test", "${bean1a.short1}", Character.TYPE, null, context)); + assertEquals((short) -124, e.evaluate("test", "${bean1a.short1}", Short.TYPE, null, context)); + assertEquals(-124, e.evaluate("test", "${bean1a.short1}", Integer.TYPE, null, context)); + assertEquals(-124l, e.evaluate("test", "${bean1a.short1}", Long.TYPE, null, context)); + assertEquals(-124.0f, e.evaluate("test", "${bean1a.short1}", Float.TYPE, null, context)); + assertEquals(-124.0, e.evaluate("test", "${bean1a.short1}", Double.TYPE, null, context)); + + assertEquals((byte) 4, e.evaluate("test", "${bean1a.int1}", Byte.TYPE, null, context)); + assertEquals((char) 4, e.evaluate("test", "${bean1a.int1}", Character.TYPE, null, context)); + assertEquals((short) 4, e.evaluate("test", "${bean1a.int1}", Short.TYPE, null, context)); + assertEquals(4, e.evaluate("test", "${bean1a.int1}", Integer.TYPE, null, context)); + assertEquals(4l, e.evaluate("test", "${bean1a.int1}", Long.TYPE, null, context)); + assertEquals(4.0f, e.evaluate("test", "${bean1a.int1}", Float.TYPE, null, context)); + assertEquals(4.0, e.evaluate("test", "${bean1a.int1}", Double.TYPE, null, context)); + + assertEquals((byte) -41, e.evaluate("test", "${bean1a.long1}", Byte.TYPE, null, context)); + assertEquals((char) 222423, e.evaluate("test", "${bean1a.long1}", Character.TYPE, null, context)); + assertEquals((short) 25815, e.evaluate("test", "${bean1a.long1}", Short.TYPE, null, context)); + assertEquals(222423, e.evaluate("test", "${bean1a.long1}", Integer.TYPE, null, context)); + assertEquals(222423l, e.evaluate("test", "${bean1a.long1}", Long.TYPE, null, context)); + assertEquals(222423.0f, e.evaluate("test", "${bean1a.long1}", Float.TYPE, null, context)); + assertEquals(222423.0, e.evaluate("test", "${bean1a.long1}", Double.TYPE, null, context)); + + assertEquals((byte) 12, e.evaluate("test", "${bean1a.float1}", Byte.TYPE, null, context)); + assertEquals((char) 12, e.evaluate("test", "${bean1a.float1}", Character.TYPE, null, context)); + assertEquals((short) 12, e.evaluate("test", "${bean1a.float1}", Short.TYPE, null, context)); + assertEquals(12, e.evaluate("test", "${bean1a.float1}", Integer.TYPE, null, context)); + assertEquals(12l, e.evaluate("test", "${bean1a.float1}", Long.TYPE, null, context)); + assertEquals(12.4f, e.evaluate("test", "${bean1a.float1}", Float.TYPE, null, context)); + assertEquals(12.399999618530273, e.evaluate("test", "${bean1a.float1}", Double.TYPE, null, context)); + + assertEquals((byte) 89, e.evaluate("test", "${bean1a.double1}", Byte.TYPE, null, context)); + assertEquals((char) 89, e.evaluate("test", "${bean1a.double1}", Character.TYPE, null, context)); + assertEquals((short) 89, e.evaluate("test", "${bean1a.double1}", Short.TYPE, null, context)); + assertEquals(89, e.evaluate("test", "${bean1a.double1}", Integer.TYPE, null, context)); + assertEquals(89l, e.evaluate("test", "${bean1a.double1}", Long.TYPE, null, context)); + assertEquals(89.224f, e.evaluate("test", "${bean1a.double1}", Float.TYPE, null, context)); + assertEquals(89.224, e.evaluate("test", "${bean1a.double1}", Double.TYPE, null, context)); + } + + public void testEntireRelationalComparisonPromotionMatrix() throws JspException { + assertEquals(false, e.evaluate("test", "${bean1a.byte1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.byte1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.byte1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.byte1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.byte1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.byte1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.byte1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.char1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.char1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.short1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.short1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(true, e.evaluate("test", "${bean1a.int1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.int1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.int1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.int1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.int1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.int1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.int1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.long1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(false, e.evaluate("test", "${bean1a.float1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.float1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.float1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.float1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.float1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.float1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.float1 < bean1a.double1}", Boolean.TYPE, null, context)); + + assertEquals(false, e.evaluate("test", "${bean1a.double1 < bean1a.byte1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.double1 < bean1a.char1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.double1 < bean1a.short1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.double1 < bean1a.int1}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.double1 < bean1a.long1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.double1 < bean1a.float1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.double1 < bean1a.double1}", Boolean.TYPE, null, context)); + } + + public void testOtherRelationalComparisonRules() throws JspException { + assertEquals(true, e.evaluate("test", "${null == null}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${noSuchAttribute == noSuchAttribute}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${noSuchAttribute == null}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${null == noSuchAttribute}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a == null}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${null == bean1a}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a == bean1a}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a > \"hello\"}", Boolean.TYPE, null, context)); + assertJspException("${bean1a < 14}"); + assertEquals(false, e.evaluate("test", "${bean1a == \"hello\"}", Boolean.TYPE, null, context)); + } + + public void testStringComparisons() throws JspException { + assertEquals(true, e.evaluate("test", "${bean1a.string1 == \"hello\"}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.string1 != \"hello\"}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${bean1a.string1 == \"goodbye\"}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.string1 != \"goodbye\"}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${bean1a.string1 > \"goodbye\"}", Boolean.TYPE, null, context)); + assertEquals(true, e.evaluate("test", "${\"hello\" == bean1a.string1}", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${\"goodbye\" > bean1a.string1}", Boolean.TYPE, null, context)); + } + + public void testErrorsInPropertyTraversal() throws JspException { + assertEquals(null, e.evaluate("test", "${noSuchAttribute.abc}", Object.class, null, context)); + assertEquals(null, e.evaluate("test", "${bean1a.bean2.byte1}", Object.class, null, context)); + assertJspException("${bean1a.noProperty}"); + assertJspException("${bean1a.noGetter}"); + assertJspException("${bean1a.errorInGetter}"); + assertEquals(null, e.evaluate("test", "${bean1a.bean2.string2}", Object.class, null, context)); + } + + public void testAccessingPublicPropertiesFromPrivateClasses() throws JspException { + assertEquals("got the value", e.evaluate("test", "${pbean1.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean2.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean3.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean4.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean5.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean6.value}", Object.class, null, context)); + assertEquals("got the value", e.evaluate("test", "${pbean7.value}", Object.class, null, context)); + } + + public void testLiteralConversions() throws JspException { + assertEquals(true, e.evaluate("test", "true", Boolean.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "false", Boolean.TYPE, null, context)); + assertEquals((byte) 12, e.evaluate("test", "12", Byte.TYPE, null, context)); + assertEquals('1', e.evaluate("test", "12", Character.TYPE, null, context)); + assertEquals((short) 12, e.evaluate("test", "12", Short.TYPE, null, context)); + assertEquals(12, e.evaluate("test", "12", Integer.TYPE, null, context)); + assertEquals(12l, e.evaluate("test", "12", Long.TYPE, null, context)); + assertEquals(12.0f, e.evaluate("test", "12", Float.TYPE, null, context)); + assertEquals(12.0, e.evaluate("test", "12", Double.TYPE, null, context)); + + // conversion using property editor + Object o = e.evaluate("test", "hello", Bean2.class, null, context); + assertTrue(o instanceof Bean2); + assertEquals("hello", ((Bean2) o).getValue()); + + try { + e.evaluate("test", "badvalue", Bean2.class, null, context); + fail(); + } catch (JspException e) { + // OK + } + + try { + e.evaluate("test", "hello", Bean1.class, null, context); + fail(); + } catch (JspException e) { + // OK + } + } + + public void testNullValuesBumpedUpToConstants() throws JspException { + assertEquals(false, e.evaluate("test", "${null}", Boolean.TYPE, null, context)); + assertEquals((byte) 0, e.evaluate("test", "${null}", Byte.TYPE, null, context)); + assertEquals((short) 0, e.evaluate("test", "${null}", Short.TYPE, null, context)); + assertEquals((char) 0, e.evaluate("test", "${null}", Character.TYPE, null, context)); + assertEquals(0, e.evaluate("test", "${null}", Integer.TYPE, null, context)); + assertEquals(0l, e.evaluate("test", "${null}", Long.TYPE, null, context)); + assertEquals(0.0f, e.evaluate("test", "${null}", Float.TYPE, null, context)); + assertEquals(0.0, e.evaluate("test", "${null}", Double.TYPE, null, context)); + assertEquals(false, e.evaluate("test", "${null}", Boolean.class, null, context)); + assertEquals((byte) 0, e.evaluate("test", "${null}", Byte.class, null, context)); + assertEquals((short) 0, e.evaluate("test", "${null}", Short.class, null, context)); + assertEquals((char) 0, e.evaluate("test", "${null}", Character.class, null, context)); + assertEquals(0, e.evaluate("test", "${null}", Integer.class, null, context)); + assertEquals(0l, e.evaluate("test", "${null}", Long.class, null, context)); + assertEquals(0.0f, e.evaluate("test", "${null}", Float.class, null, context)); + assertEquals(0.0, e.evaluate("test", "${null}", Double.class, null, context)); + } + + public void testReservedWordsAsIdentifiers() throws JspException { + assertJspException("${and}"); + assertJspException("${or}"); + assertJspException("${not}"); + assertJspException("${eq}"); + assertJspException("${ne}"); + assertJspException("${lt}"); + assertJspException("${gt}"); + assertJspException("${le}"); + assertJspException("${ge}"); + assertEquals(null, e.evaluate("test", "${instanceof}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${false}", Object.class, null, context)); + assertEquals(null, e.evaluate("test", "${null}", Object.class, null, context)); + } + + public void testReservedWordsAsPropertyNames() throws JspException { + assertJspException("${bean1a.and}"); + assertJspException("${bean1a.or}"); + assertJspException("${bean1a.not}"); + assertJspException("${bean1a.eq}"); + assertJspException("${bean1a.ne}"); + assertJspException("${bean1a.lt}"); + assertJspException("${bean1a.gt}"); + assertJspException("${bean1a.le}"); + assertJspException("${bean1a.ge}"); + assertJspException("${bean1a.instanceof}"); + assertJspException("${bean1a.page}"); + assertJspException("${bean1a.request}"); + assertJspException("${bean1a.session}"); + assertJspException("${bean1a.application}"); + assertJspException("${bean1a.true}"); + assertJspException("${bean1a.false}"); + assertJspException("${bean1a.null}"); + } + + public void testArithmetic() throws JspException { + assertEquals(8l, e.evaluate("test", "${3+5}", Object.class, null, context)); + assertEquals(-2l, e.evaluate("test", "${3-5}", Object.class, null, context)); + assertEquals(0.6, e.evaluate("test", "${3/5}", Object.class, null, context)); + assertEquals(15l, e.evaluate("test", "${3*5}", Object.class, null, context)); + assertEquals(15.0, e.evaluate("test", "${3*5.0}", Object.class, null, context)); + assertEquals(15.0, e.evaluate("test", "${3.0*5}", Object.class, null, context)); + assertEquals(15.0, e.evaluate("test", "${3.0*5.0}", Object.class, null, context)); + assertEquals(4l, e.evaluate("test", "${225 % 17}", Object.class, null, context)); + assertEquals(24l, e.evaluate("test", "${ 1 + 2 + 3 * 5 + 6}", Object.class, null, context)); + assertEquals(32l, e.evaluate("test", "${ 1 + (2 + 3) * 5 + 6}", Object.class, null, context)); + } + + public void testLogicalOperators() throws JspException { + assertEquals(true, e.evaluate("test", "${ true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ not true}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ not false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ not not true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ not not false}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ true and false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ true and true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ false and true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ false and false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ true or false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ true or true}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ false or true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ false or false}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ false or false or false or true and false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ false or false or false or true and false or true}", Object.class, null, context)); + } + + public void testIndexedAccessOperator() throws JspException { + // test as equivalent to property accessor + assertEquals(89.224, e.evaluate("test", "${ bean1a[\"double1\"] }", Object.class, null, context)); + assertEquals(Double.class, e.evaluate("test", "${ bean1a[\"double1\"].class }", Object.class, null, context)); + + // test as array accessor + assertEquals(null, e.evaluate("test", "${ bean1a.stringArray1[-1]}", Object.class, null, context)); + assertEquals("string1", e.evaluate("test", "${ bean1a.stringArray1[0]}", Object.class, null, context)); + assertEquals("string2", e.evaluate("test", "${ bean1a.stringArray1[1]}", Object.class, null, context)); + assertEquals("string3", e.evaluate("test", "${ bean1a.stringArray1[2]}", Object.class, null, context)); + assertEquals("string4", e.evaluate("test", "${ bean1a.stringArray1[3]}", Object.class, null, context)); + assertEquals(null, e.evaluate("test", "${ bean1a.stringArray1[4]}", Object.class, null, context)); + + // test as list accessor + assertEquals(14, e.evaluate("test", "${ bean1a.list1 [0]}", Object.class, null, context)); + assertEquals("another value", e.evaluate("test", "${ bean1a.list1 [1]}", Object.class, null, context)); + assertEquals("string3", e.evaluate("test", "${ bean1a.list1 [2][2]}", Object.class, null, context)); + + // test as indexed property accessor + assertJspException("${ bean1a.indexed1[-1]}"); + assertJspException("${ bean1a.indexed1[0]}"); + assertJspException("${ bean1a.indexed1[1]}"); + assertJspException("${ bean1a.indexed1[2]}"); + assertJspException("${ bean1a.indexed1[3]}"); + assertJspException("${ bean1a.indexed1[4]}"); + + // test as map accessor + assertEquals("value1", e.evaluate("test", "${ bean1a.map1.key1 }", Object.class, null, context)); + assertEquals("value1", e.evaluate("test", "${ bean1a.map1 [\"key1\"] }", Object.class, null, context)); + assertEquals("value3", e.evaluate("test", "${ bean1a.map1 [14] }", Object.class, null, context)); + assertEquals("value3", e.evaluate("test", "${ bean1a.map1 [2 * 7] }", Object.class, null, context)); + assertEquals(14, e.evaluate("test", "${ bean1a.map1.recurse.list1[0] }", Object.class, null, context)); + } + + public void testStringConcatenation() { + assertJspException("${ \"a\" + \"bcd\" }"); + assertJspException("${ \"a\" + (4*3) }"); + assertJspException("${ bean1a.map1 [\"key\" + (5-4)] }"); + } + + public void testStringComparisons2() throws JspException { + assertEquals(true, e.evaluate("test", "${ \"30\" < \"4\" }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 30 < \"4\" }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 30 > \"4\" }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ \"0004\" == \"4\" }", Object.class, null, context)); + } + + public void testRelationalComparisonWithAlternateSymbols() throws JspException { + assertEquals(false, e.evaluate("test", "${ 4 eq 3}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 ne 3}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 eq 4}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 4 ne 4}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 4 lt 3}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 gt 3}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 4 le 3}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 ge 3}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 le 4}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 4 ge 4}", Object.class, null, context)); + } + + public void testExpressionsOnLeftSideOfValueSuffix() throws JspException { + assertEquals(Long.class, e.evaluate("test", "${(3).class}", Object.class, null, context)); + assertEquals("value1", e.evaluate("test", "${(bean1a.map1)[\"key1\"]}", Object.class, null, context)); + } + + public void testStringBooleanLogicalOperators() throws JspException { + assertEquals(false, e.evaluate("test", "${'true' and false}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${'true' or true}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${false and 'true'}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${false or 'true'}", Object.class, null, context)); + } + + public void testEmptyOperator() throws JspException { + assertEquals(false, e.evaluate("test", "${ empty \"A\"}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty \"\" }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty false}", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty 0}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ not empty 0}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ not empty empty 0}", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty emptyTests.emptyArray }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty emptyTests.nonemptyArray }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty emptyTests.emptyList }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty emptyTests.nonemptyList }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty emptyTests.emptyMap }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty emptyTests.nonemptyMap }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ empty emptyTests.emptySet }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ empty emptyTests.nonemptySet }", Object.class, null, context)); + } + + public void testStringArithmetic() throws JspException { + assertEquals(2.0, e.evaluate("test", "${ \"6\" / \"3\" }", Object.class, null, context)); + assertEquals(7l, e.evaluate("test", "${ 3 + \"4\" }", Object.class, null, context)); + assertEquals(7l, e.evaluate("test", "${ \"4\" + 3 }", Object.class, null, context)); + assertEquals(7.5, e.evaluate("test", "${ 3 + \"4.5\" }", Object.class, null, context)); + assertEquals(7.5, e.evaluate("test", "${ \"4.5\" + 3 }", Object.class, null, context)); + assertEquals(9.0, e.evaluate("test", "${ 3.0 + 6.0}", Object.class, null, context)); + assertEquals(1.915590913E9, e.evaluate("test", "${ 31121.0 * 61553.0 }", Object.class, null, context)); + assertEquals(1915590913l, e.evaluate("test", "${ 31121 * 61553 }", Object.class, null, context)); + assertEquals(9220838762064379904l, e.evaluate("test", "${ 65536 * 65536 * 65536 * 32759 }", Object.class, null, context)); + assertEquals(4l, e.evaluate("test", "${ 9220838762064379904 - 9220838762064379900 }", Object.class, null, context)); + } + + public void testRelationalOperatorsInvolvingNull() throws JspException { + assertEquals(true, e.evaluate("test", "${ null == null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null != null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null > null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null < null }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ null >= null }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ null <= null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null == 3 }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ null != 3 }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null > 3 }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null < 3 }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null >= 3 }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null <= 3 }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 3 == null }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ 3 != null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 3 > null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 3 < null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 3 >= null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ 3 <= null }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ null == \"\" }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ null != \"\" }", Object.class, null, context)); + assertEquals(false, e.evaluate("test", "${ \"\" == null }", Object.class, null, context)); + assertEquals(true, e.evaluate("test", "${ \"\" != null }", Object.class, null, context)); + } + + public void testArithmeticOperatorsInvolvingStrings() throws JspException { + assertEquals(7L, e.evaluate("test", "${ 4 + 3 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4.0 + 3 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4 + 3.0 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4.0 + 3.0 }", Object.class, null, context)); + assertEquals(7l, e.evaluate("test", "${ \"4\" + 3 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4.0\" + 3 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4\" + 3.0 }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4.0\" + 3.0 }", Object.class, null, context)); + assertEquals(7l, e.evaluate("test", "${ 4 + \"3\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4.0 + \"3\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4 + \"3.0\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ 4.0 + \"3.0\" }", Object.class, null, context)); + assertEquals(7l, e.evaluate("test", "${ \"4\" + \"3\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4.0\" + \"3\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4\" + \"3.0\" }", Object.class, null, context)); + assertEquals(7.0, e.evaluate("test", "${ \"4.0\" + \"3.0\" }", Object.class, null, context)); + + assertEquals(1L, e.evaluate("test", "${ 4 - 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 - 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4 - 3.0 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 - 3.0 }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ \"4\" - 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" - 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4\" - 3.0 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" - 3.0 }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ 4 - \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 - \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4 - \"3.0\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 - \"3.0\" }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ \"4\" - \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" - \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4\" - \"3.0\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" - \"3.0\" }", Object.class, null, context)); + + assertEquals(12L, e.evaluate("test", "${ 4 * 3 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4.0 * 3 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4 * 3.0 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4.0 * 3.0 }", Object.class, null, context)); + assertEquals(12l, e.evaluate("test", "${ \"4\" * 3 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4.0\" * 3 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4\" * 3.0 }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4.0\" * 3.0 }", Object.class, null, context)); + assertEquals(12l, e.evaluate("test", "${ 4 * \"3\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4.0 * \"3\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4 * \"3.0\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ 4.0 * \"3.0\" }", Object.class, null, context)); + assertEquals(12l, e.evaluate("test", "${ \"4\" * \"3\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4.0\" * \"3\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4\" * \"3.0\" }", Object.class, null, context)); + assertEquals(12.0, e.evaluate("test", "${ \"4.0\" * \"3.0\" }", Object.class, null, context)); + + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4 / 3 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4.0 / 3 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4 / 3.0 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4.0 / 3.0 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4\" / 3 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4.0\" / 3 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4\" / 3.0 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4.0\" / 3.0 }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4 / \"3\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4.0 / \"3\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4 / \"3.0\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ 4.0 / \"3.0\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4\" / \"3\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4.0\" / \"3\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4\" / \"3.0\" }", Object.class, null, context)); + assertEquals(1.3333333333333333, e.evaluate("test", "${ \"4.0\" / \"3.0\" }", Object.class, null, context)); + + assertEquals(1L, e.evaluate("test", "${ 4 % 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 % 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4 % 3.0 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 % 3.0 }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ \"4\" % 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" % 3 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4\" % 3.0 }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" % 3.0 }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ 4 % \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 % \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4 % \"3.0\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ 4.0 % \"3.0\" }", Object.class, null, context)); + assertEquals(1l, e.evaluate("test", "${ \"4\" % \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" % \"3\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4\" % \"3.0\" }", Object.class, null, context)); + assertEquals(1.0, e.evaluate("test", "${ \"4.0\" % \"3.0\" }", Object.class, null, context)); + + assertEquals(4.0, e.evaluate("test", "${ \"8\" / \"2\" }", Object.class, null, context)); + assertEquals(403.0, e.evaluate("test", "${ \"4e2\" + \"3\" }", Object.class, null, context)); + assertEquals(304.0, e.evaluate("test", "${ \"4\" + \"3e2\" }", Object.class, null, context)); + assertEquals(700.0, e.evaluate("test", "${ \"4e2\" + \"3e2\" }", Object.class, null, context)); + } + + public void testUnaryMinusOperatorInvolvingStrings() throws JspException { + assertEquals(-3l, e.evaluate("test", "${ -3 }", Object.class, null, context)); + assertEquals(-3.0, e.evaluate("test", "${ -3.0 }", Object.class, null, context)); + assertEquals(-3L, e.evaluate("test", "${ -\"3\" }", Object.class, null, context)); + assertEquals(-3.0, e.evaluate("test", "${ -\"3.0\" }", Object.class, null, context)); + assertEquals(-300.0, e.evaluate("test", "${ -\"3e2\" }", Object.class, null, context)); + } + + private void assertJspException(String expr) { + try { + e.evaluate("test", expr, Object.class, null, context); + fail(); + } catch (JspException e1) { + // OK + } + } + + /** + * Creates and returns the test PageContext that will be used for + * the tests. + */ + static PageContext createTestContext() { + PageContext ret = new PageContextImpl(); + + // Create some basic values for lookups + ret.setAttribute("val1a", "page-scoped1", PageContext.PAGE_SCOPE); + ret.setAttribute("val1b", "request-scoped1", PageContext.REQUEST_SCOPE); + ret.setAttribute("val1c", "session-scoped1", PageContext.SESSION_SCOPE); + ret.setAttribute("val1d", "app-scoped1", PageContext.APPLICATION_SCOPE); + + // Create a bean + { + Bean1 b1 = new Bean1(); + b1.setBoolean1(true); + b1.setByte1((byte) 12); + b1.setShort1((short) -124); + b1.setChar1('b'); + b1.setInt1(4); + b1.setLong1(222423); + b1.setFloat1((float) 12.4); + b1.setDouble1(89.224); + b1.setString1("hello"); + b1.setStringArray1(new String[]{ + "string1", + "string2", + "string3", + "string4" + }); + { + List l = new ArrayList(); + l.add(new Integer(14)); + l.add("another value"); + l.add(b1.getStringArray1()); + b1.setList1(l); + } + { + Map m = new HashMap(); + m.put("key1", "value1"); + m.put(new Integer(14), "value2"); + m.put(new Long(14), "value3"); + m.put("recurse", b1); + b1.setMap1(m); + } + ret.setAttribute("bean1a", b1); + + Bean1 b2 = new Bean1(); + b2.setInt2(new Integer(-224)); + b2.setString2("bean2's string"); + b1.setBean1(b2); + + Bean1 b3 = new Bean1(); + b3.setDouble1(1422.332); + b3.setString2("bean3's string"); + b2.setBean2(b3); + } + + // Create the public/private beans + { + ret.setAttribute("pbean1", Factory.createBean1()); + ret.setAttribute("pbean2", Factory.createBean2()); + ret.setAttribute("pbean3", Factory.createBean3()); + ret.setAttribute("pbean4", Factory.createBean4()); + ret.setAttribute("pbean5", Factory.createBean5()); + ret.setAttribute("pbean6", Factory.createBean6()); + ret.setAttribute("pbean7", Factory.createBean7()); + } + + // Create the empty tests + { + Map m = new HashMap(); + m.put("emptyArray", new Object[0]); + m.put("nonemptyArray", new Object[]{"abc"}); + m.put("emptyList", new ArrayList()); + { + List l = new ArrayList(); + l.add("hello"); + m.put("nonemptyList", l); + } + m.put("emptyMap", new HashMap()); + { + Map m2 = new HashMap(); + m2.put("a", "a"); + m.put("nonemptyMap", m2); + } + m.put("emptySet", new HashSet()); + { + Set s = new HashSet(); + s.add("hello"); + m.put("nonemptySet", s); + } + ret.setAttribute("emptyTests", m); + } + + return ret; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java new file mode 100644 index 000000000..7726599aa --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/PageContextImpl.java @@ -0,0 +1,299 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import jakarta.el.ELContext; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.el.ExpressionEvaluator; +import jakarta.servlet.jsp.el.VariableResolver; + +/** + *

This is a "dummy" implementation of PageContext whose only + * purpose is to serve the attribute getter/setter API's. + * + * @author Nathan Abramson - Art Technology Group + */ + +public class PageContextImpl + extends PageContext { + //------------------------------------- + // Properties + //------------------------------------- + + //------------------------------------- + // Member variables + //------------------------------------- + + Map mPage = Collections.synchronizedMap(new HashMap()); + Map mRequest = Collections.synchronizedMap(new HashMap()); + Map mSession = Collections.synchronizedMap(new HashMap()); + Map mApp = Collections.synchronizedMap(new HashMap()); + + //------------------------------------- + + /** + * Constructor + */ + public PageContextImpl() { + } + + //------------------------------------- + // PageContext methods + //------------------------------------- + + public void initialize(Servlet servlet, + ServletRequest request, + ServletResponse response, + String errorPageURL, + boolean needSession, + int bufferSize, + boolean autoFlush) { + } + + //------------------------------------- + + public void release() { + } + + //------------------------------------- + + public void setAttribute(String name, + Object attribute) { + mPage.put(name, attribute); + } + + //------------------------------------- + + public void setAttribute(String name, + Object attribute, + int scope) { + switch (scope) { + case PAGE_SCOPE: + mPage.put(name, attribute); + break; + case REQUEST_SCOPE: + mRequest.put(name, attribute); + break; + case SESSION_SCOPE: + mSession.put(name, attribute); + break; + case APPLICATION_SCOPE: + mApp.put(name, attribute); + break; + default: + throw new IllegalArgumentException("Bad scope " + scope); + } + } + + //------------------------------------- + + public Object getAttribute(String name) { + return mPage.get(name); + } + + //------------------------------------- + + public Object getAttribute(String name, + int scope) { + switch (scope) { + case PAGE_SCOPE: + return mPage.get(name); + case REQUEST_SCOPE: + return mRequest.get(name); + case SESSION_SCOPE: + return mSession.get(name); + case APPLICATION_SCOPE: + return mApp.get(name); + default: + throw new IllegalArgumentException("Bad scope " + scope); + } + } + + //------------------------------------- + + public Object findAttribute(String name) { + if (mPage.containsKey(name)) { + return mPage.get(name); + } else if (mRequest.containsKey(name)) { + return mRequest.get(name); + } else if (mSession.containsKey(name)) { + return mSession.get(name); + } else if (mApp.containsKey(name)) { + return mApp.get(name); + } else { + return null; + } + } + + //------------------------------------- + + public void removeAttribute(String name) { + if (mPage.containsKey(name)) { + mPage.remove(name); + } else if (mRequest.containsKey(name)) { + mRequest.remove(name); + } else if (mSession.containsKey(name)) { + mSession.remove(name); + } else if (mApp.containsKey(name)) { + mApp.remove(name); + } + } + + //------------------------------------- + + public void removeAttribute(String name, + int scope) { + switch (scope) { + case PAGE_SCOPE: + mPage.remove(name); + break; + case REQUEST_SCOPE: + mRequest.remove(name); + break; + case SESSION_SCOPE: + mSession.remove(name); + break; + case APPLICATION_SCOPE: + mApp.remove(name); + break; + default: + throw new IllegalArgumentException("Bad scope " + scope); + } + } + + //------------------------------------- + + public int getAttributesScope(String name) { + if (mPage.containsKey(name)) { + return PAGE_SCOPE; + } else if (mRequest.containsKey(name)) { + return REQUEST_SCOPE; + } else if (mSession.containsKey(name)) { + return SESSION_SCOPE; + } else if (mApp.containsKey(name)) { + return APPLICATION_SCOPE; + } else { + return 0; + } + } + + //------------------------------------- + + public Enumeration getAttributeNamesInScope(int scope) { + return null; + } + + //------------------------------------- + + public JspWriter getOut() { + return null; + } + + //------------------------------------- + + public HttpSession getSession() { + return null; + } + + //------------------------------------- + + public Object getPage() { + return null; + } + + //------------------------------------- + + public ServletRequest getRequest() { + return null; + } + + //------------------------------------- + + public ServletResponse getResponse() { + return null; + } + + //------------------------------------- + + public Exception getException() { + return null; + } + + //------------------------------------- + + public ServletConfig getServletConfig() { + return null; + } + + //------------------------------------- + + public ServletContext getServletContext() { + return null; + } + + //------------------------------------- + + public void forward(String path) { + } + + //------------------------------------- + + public void include(String path) { + } + + //------------------------------------- + + public void handlePageException(Exception exc) { + } + + //------------------------------------- + + public void handlePageException(Throwable exc) { + } + + //------------------------------------- + + // Since JSP 2.0 + + public void include(java.lang.String relativeUrlPath, boolean flush) { + } + + public ExpressionEvaluator getExpressionEvaluator() { + return null; + } + + public VariableResolver getVariableResolver() { + return null; + } + + public ELContext getELContext() { + return null; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/ParserTest.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/ParserTest.java new file mode 100644 index 000000000..f80616f9c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/ParserTest.java @@ -0,0 +1,132 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.io.BufferedReader; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.io.PrintWriter; +import java.nio.charset.Charset; + +import jakarta.servlet.jsp.JspException; + +import junit.framework.TestCase; +import org.apache.taglibs.standard.lang.jstl.Evaluator; +import org.junit.Assert; +import org.junit.Test; + +/** + *

This runs a series of tests specifically for the parser. It + * parses various expressions and prints out the canonical + * representation of those parsed expressions. + *

The expressions are stored in an input text file, with one line + * per expression. Blank lines and lines that start with # are + * ignored. The results are written to an output file (blank lines + * and # lines are included in the output file). The output file may + * be compared against an existing output file to do regression + * testing. + * + * @author Nathan Abramson - Art Technology Group + */ +public class ParserTest extends TestCase { + private final Charset UTF8 = Charset.forName("UTF-8"); + + @Test + public void testParser() throws IOException { + try { + System.setProperty("jakarta.servlet.jsp.functions.allowed", "true"); + BufferedReader in = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("parserTests.txt"), UTF8)); + CharArrayWriter writer = new CharArrayWriter(); + PrintWriter out = new PrintWriter(writer); + + runTests(in, out); + out.close(); + in.close(); + + LineNumberReader expected = new LineNumberReader(new InputStreamReader(getClass().getResourceAsStream("parserTestsOutput.txt"), UTF8)); + LineNumberReader actual = new LineNumberReader(new CharArrayReader(writer.toCharArray())); + + Assert.assertFalse(isDifferentStreams(actual, expected)); + actual.close(); + expected.close(); + } finally { + System.clearProperty("jakarta.servlet.jsp.functions.allowed"); + } + } + + /** + * Runs the tests, reading expressions from pIn and writing the + * results to pOut. + */ + public static void runTests(BufferedReader pIn, PrintWriter pOut) + throws IOException { + while (true) { + String str = pIn.readLine(); + if (str == null) { + break; + } + if (str.startsWith("#") || + "".equals(str.trim())) { + pOut.println(str); + } else { + pOut.println("Attribute value: " + str); + try { + String result = Evaluator.parseAndRender(str); + pOut.println("Parses to: " + result); + } + catch (JspException exc) { + pOut.println("Causes an error: " + exc.getMessage()); + } + } + } + + } + + /** + * Performs a line-by-line comparison of the two files, returning + * true if the files are different, false if not. + */ + public static boolean isDifferentStreams(LineNumberReader actual, + LineNumberReader expected) + throws IOException { + while (true) { + String str1 = actual.readLine(); + String str2 = expected.readLine(); + if (str1 == null && + str2 == null) { + return false; + } else if (str1 == null || + str2 == null) { + return true; + } else { + if (!str1.equals(str2)) { + System.out.println("Files differ at line " + actual.getLineNumber()); + return true; + } + } + } + } + + @Test + public void testUnicodeCharacter() throws JspException { + Assert.assertEquals("\u1111", Evaluator.parseAndRender("\u1111")); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/StaticFunctionTest.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/StaticFunctionTest.java new file mode 100644 index 000000000..be862c645 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/StaticFunctionTest.java @@ -0,0 +1,96 @@ +/* + * 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.taglibs.standard.lang.jstl.test; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; +import org.apache.taglibs.standard.lang.jstl.Evaluator; + +/** + *

This class contains some test functions.

+ * + * @author Shawn Bayern + */ +public class StaticFunctionTest extends TestCase { + + public void testFunctions() throws Exception { + + System.setProperty("jakarta.servlet.jsp.functions.allowed", "true"); + Map m = getSampleMethodMap(); + Evaluator e = new Evaluator(); + Object o; + + o = e.evaluate("", "4", Integer.class, null, null, m, "foo"); + assertEquals("4", o.toString()); + o = e.evaluate("", "${4}", Integer.class, null, null, m, "foo"); + assertEquals("4", o.toString()); + o = e.evaluate("", "${2+2}", Integer.class, null, null, m, "foo"); + assertEquals("4", o.toString()); + o = e.evaluate("", "${foo:add(2, 3)}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + o = e.evaluate("", "${foo:multiply(2, 3)}", Integer.class, null, null, m, "foo"); + assertEquals("6", o.toString()); + o = e.evaluate("", "${add(2, 3)}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + o = e.evaluate("", "${multiply(2, 3)}", Integer.class, null, null, m, "foo"); + assertEquals("6", o.toString()); + o = e.evaluate("", "${add(2, 3) + 5}", Integer.class, null, null, m, "foo"); + assertEquals("10", o.toString()); + + + o = e.evaluate("", "${getInt(getInteger(getInt(5)))}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + + o = e.evaluate("", "${getInteger(getInt(getInteger(5)))}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + + o = e.evaluate("", "${getInt(getInt(getInt(5)))}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + + o = e.evaluate("", "${getInteger(getInteger(getInteger(5)))}", Integer.class, null, null, m, "foo"); + assertEquals("5", o.toString()); + } + + public static int add(int a, int b) { + return a + b; + } + + public static int multiply(int a, int b) { + return a * b; + } + + public static int getInt(Integer i) { + return i.intValue(); + } + + public static Integer getInteger(int i) { + return new Integer(i); + } + + public static Map getSampleMethodMap() throws Exception { + Map m = new HashMap(); + Class c = StaticFunctionTest.class; + m.put("foo:add", c.getMethod("add", new Class[]{Integer.TYPE, Integer.TYPE})); + m.put("foo:multiply", c.getMethod("multiply", new Class[]{Integer.TYPE, Integer.TYPE})); + m.put("foo:getInt", c.getMethod("getInt", new Class[]{Integer.class})); + m.put("foo:getInteger", c.getMethod("getInteger", new Class[]{Integer.TYPE})); + return m; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/Factory.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/Factory.java new file mode 100644 index 000000000..1a60f2c0c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/Factory.java @@ -0,0 +1,54 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A factory for generating the various beans + * + * @author Nathan Abramson - Art Technology Group + */ + +public class Factory { + public static PublicBean1 createBean1() { + return new PublicBean1(); + } + + public static PublicBean1 createBean2() { + return new PrivateBean1a(); + } + + public static PublicBean1 createBean3() { + return new PublicBean1b(); + } + + public static PublicInterface2 createBean4() { + return new PublicBean2a(); + } + + public static PublicInterface2 createBean5() { + return new PrivateBean2b(); + } + + public static PublicInterface2 createBean6() { + return new PrivateBean2c(); + } + + public static PublicInterface2 createBean7() { + return new PrivateBean2d(); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean1a.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean1a.java new file mode 100644 index 000000000..6b74c6bb5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean1a.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A private bean subclassing a public bean + * + * @author Nathan Abramson - Art Technology Group + */ + +class PrivateBean1a + extends PublicBean1 { +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2b.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2b.java new file mode 100644 index 000000000..a96b7b2d3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2b.java @@ -0,0 +1,31 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A private implementation of a public interface + * + * @author Nathan Abramson - Art Technology Group + */ + +class PrivateBean2b + implements PublicInterface2 { + public Object getValue() { + return "got the value"; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2c.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2c.java new file mode 100644 index 000000000..a66d782c1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2c.java @@ -0,0 +1,29 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A private subclass of a public class impelementing a public + * interface + * + * @author Nathan Abramson - Art Technology Group + */ + +class PrivateBean2c + extends PublicBean2a { +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2d.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2d.java new file mode 100644 index 000000000..46add2165 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PrivateBean2d.java @@ -0,0 +1,29 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A private subclass of a private class impelementing a public + * interface + * + * @author Nathan Abramson - Art Technology Group + */ + +class PrivateBean2d + extends PrivateBean2b { +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1.java new file mode 100644 index 000000000..472844a7f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1.java @@ -0,0 +1,30 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A publicly-accessible bean + * + * @author Nathan Abramson - Art Technology Group + */ + +public class PublicBean1 { + public Object getValue() { + return "got the value"; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1b.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1b.java new file mode 100644 index 000000000..0f01e2b5f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean1b.java @@ -0,0 +1,29 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A public bean subclassing a private bean subclassing a public + * bean + * + * @author Nathan Abramson - Art Technology Group + */ + +public class PublicBean1b + extends PrivateBean1a { +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean2a.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean2a.java new file mode 100644 index 000000000..c8a7eb9ce --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicBean2a.java @@ -0,0 +1,31 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A publicly-accessible implementation of a public interface + * + * @author Nathan Abramson - Art Technology Group + */ + +public class PublicBean2a + implements PublicInterface2 { + public Object getValue() { + return "got the value"; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicInterface2.java b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicInterface2.java new file mode 100644 index 000000000..c65e6c84f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/java/org/apache/taglibs/standard/lang/jstl/test/beans/PublicInterface2.java @@ -0,0 +1,28 @@ +/* + * 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.taglibs.standard.lang.jstl.test.beans; + +/** + *

A publicly-accessible interface + * + * @author Nathan Abramson - Art Technology Group + */ + +public interface PublicInterface2 { + public Object getValue(); +} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTests.txt b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTests.txt new file mode 100644 index 000000000..4fe6da390 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTests.txt @@ -0,0 +1,159 @@ +# 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. +# +# testing mixture of strings and expressions +abc +${ 3} +a${ +a${ 5 } +${ 3 }b +${ 1 }${ 2 } +abc ${ 1} ${ 2} def + +# testing values that end with or contain "$" +$ +\$ + $ +test$ +$test +test$test +test$$$ +test$$${ 34 } +test$$${ 34 }$$ +test$${ 34 } +$${ 34 } +$$ +test$$ +test$$test +${ 34 }$${ 34 } + +# literals +${1} +${-12} +${true} +${false} +${null} +${4.2} +${-21.3} +${4.} +${.21} +${3e-1} +${.2222222222} + +# string literals with " +${"abc"} +${""} +${"a"} +${" "} +${" some string ''' "} +${" with escaping \\"} +${" with escaping \""} +${" with escaping \"\\\""} +${" bad \ escaping"} +${" bad \' escaping"} + +# string literals with ' +${'abc'} +${''} +${'a'} +${' '} +${' some string """ '} +${' with escaping \\'} +${' with escaping \''} +${' with escaping \'\\\''} +${' bad \ escaping'} +${' bad \" escaping'} + +# identifiers +${abc} +${abc123} +${abc_123} +${bad*identifier} + +# property accessors +${a .b .c} +${ abc . 'def.ghi' . ghi . "jkl \"" } + +# array accessors +${ a[14] } +${ abc [def]} +${ def ["yesthisisallowed"]} + +# mixed property/array accessors +${ a.b.c[d. e. f]} +${ a[14].b[32].c[24][ 261] [24]} +${ a[b[c[d[e[f]]]].g] } + +# mixed operators +${ 1 + 3 - 2 * 1 == 4} +${ 1 + 3 - 2 * 1 == 4 / 1.2} +${ 1 + 3 - 2 * 1 == 4 / 1.2 and abc} +${ 1 + 3 - 2 * 1 == 4 / 1.2 and abc or def or ghi and true} + +# unary operators +${ --not abc.def } + +# array accessors of non-integer types +${ a ["hello"]."12" [17.5] } + +# making sure unicode escapes are not recognized +\u0040 +"\u0040" + +# relational operators +${ a > b } +${ a gt b } +${ a < b } +${ a lt b } +${ a >= b } +${ a ge b } +${ a <= b } +${ a le b } +${ a == b } +${ a eq b } +${ a != b } +${ a ne b } + +# logical operators +${ a and b} +${ a && b} +${ a or b} +${ a || b} +${ !a } +${ not a } + +# empty operator +${ empty "A"} +${ empty "" } +${ empty null } +${ empty false} +${ empty 0} +${ not empty 0} +${ not empty empty 0} +${ empty } + +# functions +${a()} +${ a() } +${a(b)} +${ a(b) } +${a(b,c)} +${a(b,c,d)} +${a:b(c)} +${a:b(c,d)} +${a:b(c,d,e)} +${a(b).c} +${a(b)[c]} +${a[b()]} diff --git a/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTestsOutput.txt b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTestsOutput.txt new file mode 100644 index 000000000..9a55d5d48 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/jstlel/src/test/resources/org/apache/taglibs/standard/lang/jstl/test/parserTestsOutput.txt @@ -0,0 +1,270 @@ +# 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. +# +# testing mixture of strings and expressions +Attribute value: abc +Parses to: abc +Attribute value: ${ 3} +Parses to: ${3} +Attribute value: a${ +Causes an error: An error occurred while parsing custom action attribute "test" with value "a${": Encountered "", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] +Attribute value: a${ 5 } +Parses to: a${5} +Attribute value: ${ 3 }b +Parses to: ${3}b +Attribute value: ${ 1 }${ 2 } +Parses to: ${1}${2} +Attribute value: abc ${ 1} ${ 2} def +Parses to: abc ${1} ${2} def + +# testing values that end with or contain "$" +Attribute value: $ +Parses to: $ +Attribute value: \$ +Parses to: \$ +Attribute value: $ +Parses to: $ +Attribute value: test$ +Parses to: test$ +Attribute value: $test +Parses to: $test +Attribute value: test$test +Parses to: test$test +Attribute value: test$$$ +Parses to: test$$$ +Attribute value: test$$${ 34 } +Parses to: test$$${34} +Attribute value: test$$${ 34 }$$ +Parses to: test$$${34}$$ +Attribute value: test$${ 34 } +Parses to: test$${34} +Attribute value: $${ 34 } +Parses to: $${34} +Attribute value: $$ +Parses to: $$ +Attribute value: test$$ +Parses to: test$$ +Attribute value: test$$test +Parses to: test$$test +Attribute value: ${ 34 }$${ 34 } +Parses to: ${34}$${34} + +# literals +Attribute value: ${1} +Parses to: ${1} +Attribute value: ${-12} +Parses to: ${(- 12)} +Attribute value: ${true} +Parses to: ${true} +Attribute value: ${false} +Parses to: ${false} +Attribute value: ${null} +Parses to: ${null} +Attribute value: ${4.2} +Parses to: ${4.2} +Attribute value: ${-21.3} +Parses to: ${(- 21.3)} +Attribute value: ${4.} +Parses to: ${4.0} +Attribute value: ${.21} +Parses to: ${0.21} +Attribute value: ${3e-1} +Parses to: ${0.3} +Attribute value: ${.2222222222} +Parses to: ${0.2222222222} + +# string literals with " +Attribute value: ${"abc"} +Parses to: ${"abc"} +Attribute value: ${""} +Parses to: ${""} +Attribute value: ${"a"} +Parses to: ${"a"} +Attribute value: ${" "} +Parses to: ${" "} +Attribute value: ${" some string ''' "} +Parses to: ${" some string ''' "} +Attribute value: ${" with escaping \\"} +Parses to: ${" with escaping \\"} +Attribute value: ${" with escaping \""} +Parses to: ${" with escaping \""} +Attribute value: ${" with escaping \"\\\""} +Parses to: ${" with escaping \"\\\""} +Attribute value: ${" bad \ escaping"} +Causes an error: An error occurred while parsing custom action attribute "test" with value "${" bad \ escaping"}": Encountered "" bad \ ", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] +Attribute value: ${" bad \' escaping"} +Causes an error: An error occurred while parsing custom action attribute "test" with value "${" bad \' escaping"}": Encountered "" bad \'", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] + +# string literals with ' +Attribute value: ${'abc'} +Parses to: ${"abc"} +Attribute value: ${''} +Parses to: ${""} +Attribute value: ${'a'} +Parses to: ${"a"} +Attribute value: ${' '} +Parses to: ${" "} +Attribute value: ${' some string """ '} +Parses to: ${" some string \"\"\" "} +Attribute value: ${' with escaping \\'} +Parses to: ${" with escaping \\"} +Attribute value: ${' with escaping \''} +Parses to: ${" with escaping '"} +Attribute value: ${' with escaping \'\\\''} +Parses to: ${" with escaping '\\'"} +Attribute value: ${' bad \ escaping'} +Causes an error: An error occurred while parsing custom action attribute "test" with value "${' bad \ escaping'}": Encountered "' bad \ ", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] +Attribute value: ${' bad \" escaping'} +Causes an error: An error occurred while parsing custom action attribute "test" with value "${' bad \" escaping'}": Encountered "' bad \"", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] + +# identifiers +Attribute value: ${abc} +Parses to: ${abc} +Attribute value: ${abc123} +Parses to: ${abc123} +Attribute value: ${abc_123} +Parses to: ${abc_123} +Attribute value: ${bad*identifier} +Parses to: ${(bad * identifier)} + +# property accessors +Attribute value: ${a .b .c} +Parses to: ${a.b.c} +Attribute value: ${ abc . 'def.ghi' . ghi . "jkl \"" } +Causes an error: An error occurred while parsing custom action attribute "test" with value "${ abc . 'def.ghi' . ghi . "jkl \"" }": Encountered "'def.ghi'", expected one of [] + +# array accessors +Attribute value: ${ a[14] } +Parses to: ${a[14]} +Attribute value: ${ abc [def]} +Parses to: ${abc[def]} +Attribute value: ${ def ["yesthisisallowed"]} +Parses to: ${def["yesthisisallowed"]} + +# mixed property/array accessors +Attribute value: ${ a.b.c[d. e. f]} +Parses to: ${a.b.c[d.e.f]} +Attribute value: ${ a[14].b[32].c[24][ 261] [24]} +Parses to: ${a[14].b[32].c[24][261][24]} +Attribute value: ${ a[b[c[d[e[f]]]].g] } +Parses to: ${a[b[c[d[e[f]]]].g]} + +# mixed operators +Attribute value: ${ 1 + 3 - 2 * 1 == 4} +Parses to: ${((1 + 3 - (2 * 1)) == 4)} +Attribute value: ${ 1 + 3 - 2 * 1 == 4 / 1.2} +Parses to: ${((1 + 3 - (2 * 1)) == (4 / 1.2))} +Attribute value: ${ 1 + 3 - 2 * 1 == 4 / 1.2 and abc} +Parses to: ${(((1 + 3 - (2 * 1)) == (4 / 1.2)) and abc)} +Attribute value: ${ 1 + 3 - 2 * 1 == 4 / 1.2 and abc or def or ghi and true} +Parses to: ${((((1 + 3 - (2 * 1)) == (4 / 1.2)) and abc) or def or (ghi and true))} + +# unary operators +Attribute value: ${ --not abc.def } +Parses to: ${(- - not abc.def)} + +# array accessors of non-integer types +Attribute value: ${ a ["hello"]."12" [17.5] } +Causes an error: An error occurred while parsing custom action attribute "test" with value "${ a ["hello"]."12" [17.5] }": Encountered ""12"", expected one of [] + +# making sure unicode escapes are not recognized +Attribute value: \u0040 +Parses to: \u0040 +Attribute value: "\u0040" +Parses to: "\u0040" + +# relational operators +Attribute value: ${ a > b } +Parses to: ${(a > b)} +Attribute value: ${ a gt b } +Parses to: ${(a > b)} +Attribute value: ${ a < b } +Parses to: ${(a < b)} +Attribute value: ${ a lt b } +Parses to: ${(a < b)} +Attribute value: ${ a >= b } +Parses to: ${(a >= b)} +Attribute value: ${ a ge b } +Parses to: ${(a >= b)} +Attribute value: ${ a <= b } +Parses to: ${(a <= b)} +Attribute value: ${ a le b } +Parses to: ${(a <= b)} +Attribute value: ${ a == b } +Parses to: ${(a == b)} +Attribute value: ${ a eq b } +Parses to: ${(a == b)} +Attribute value: ${ a != b } +Parses to: ${(a != b)} +Attribute value: ${ a ne b } +Parses to: ${(a != b)} + +# logical operators +Attribute value: ${ a and b} +Parses to: ${(a and b)} +Attribute value: ${ a && b} +Parses to: ${(a and b)} +Attribute value: ${ a or b} +Parses to: ${(a or b)} +Attribute value: ${ a || b} +Parses to: ${(a or b)} +Attribute value: ${ !a } +Parses to: ${(not a)} +Attribute value: ${ not a } +Parses to: ${(not a)} + +# empty operator +Attribute value: ${ empty "A"} +Parses to: ${(empty "A")} +Attribute value: ${ empty "" } +Parses to: ${(empty "")} +Attribute value: ${ empty null } +Parses to: ${(empty null)} +Attribute value: ${ empty false} +Parses to: ${(empty false)} +Attribute value: ${ empty 0} +Parses to: ${(empty 0)} +Attribute value: ${ not empty 0} +Parses to: ${(not empty 0)} +Attribute value: ${ not empty empty 0} +Parses to: ${(not empty empty 0)} +Attribute value: ${ empty } +Causes an error: An error occurred while parsing custom action attribute "test" with value "${ empty }": Encountered "}", expected one of [, , , "true", "false", "null", "(", "-", "not", "!", "empty", ] + +# functions +Attribute value: ${a()} +Parses to: ${a()} +Attribute value: ${ a() } +Parses to: ${a()} +Attribute value: ${a(b)} +Parses to: ${a(b)} +Attribute value: ${ a(b) } +Parses to: ${a(b)} +Attribute value: ${a(b,c)} +Parses to: ${a(b, c)} +Attribute value: ${a(b,c,d)} +Parses to: ${a(b, c, d)} +Attribute value: ${a:b(c)} +Parses to: ${a:b(c)} +Attribute value: ${a:b(c,d)} +Parses to: ${a:b(c, d)} +Attribute value: ${a:b(c,d,e)} +Parses to: ${a:b(c, d, e)} +Attribute value: ${a(b).c} +Parses to: ${a(b).c} +Attribute value: ${a(b)[c]} +Parses to: ${a(b)[c]} +Attribute value: ${a[b()]} +Parses to: ${a[b()]} diff --git a/Java-base/tomcat-taglibs-standard/src/pom.xml b/Java-base/tomcat-taglibs-standard/src/pom.xml new file mode 100644 index 000000000..2b40066dd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/pom.xml @@ -0,0 +1,261 @@ + + + + + 4.0.0 + + org.apache.taglibs + taglibs-parent + 4-SNAPSHOT + + + pom + + taglibs-standard + 2.0.0-SNAPSHOT + Apache Standard Taglib + + 2001 + + An implementation of the JSP Standard Tag Library (JSTL). + + + http://tomcat.apache.org/taglibs/standard-${project.version} + + + scm:git:https://github.com/apache/tomcat-taglibs-standard + scm:git:https://github.com/apache/tomcat-taglibs-standard + https://github.com/apache/tomcat-taglibs-standard + + + + jenkins + https://builds.apache.org/job/taglib-standard/ + + + + + Pierre Delisle + + + Shawn Bayern + + + Nathan Abramson + + + Hans Bergsten + + + Scott Hasse + + + Justyna Horwat + + + Mark Kolb + + + Jan Luehe + + + Glenn Nielsen + + + Dmitri Plotnikov + + + Felipe Leme + + + Henri Yandell + + + Bjorn Townsend + + + Jeremy Boynes + + + Konstantin Kolinko + + + + + + Robert Goff + + + Dan Armstrong + + + + + build-tools + spec + impl + compat + jstlel + standard-examples + + + + + + + org.apache.taglibs + taglibs-standard-spec + ${project.version} + + + org.apache.taglibs + taglibs-standard-impl + ${project.version} + + + jakarta.servlet + jakarta.servlet-api + 5.0.0-M1 + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + 3.0.0-M1 + + + jakarta.el + jakarta.el-api + 4.0.0.M1 + + + xalan + xalan + 2.7.1 + + + + + junit + junit + 4.8.1 + + + org.easymock + easymock + 3.0 + + + + + + + + + org.apache.rat + apache-rat-plugin + + + standard-test/src/test/resources/org/apache/taglibs/standard/tag/el/core/TestOutTag.txt + CHANGES.txt + DEPENDENCIES + README_bin.txt + README_src.txt + RELEASING.txt + Jenkinsfile + */*.iml + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.1.1 + + + + + + + + + + + + + + + + + + + org.apache.rat + apache-rat-plugin + + + verify + + check + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + ban-javax-namespace + + enforce + + + + + + javax.servlet + servletapi + javax.servlet.jsp + javax.el + + + + + + + + + + + + + apache.snapshots + https://repository.apache.org/content/repositories/snapshots/ + + false + + + true + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/spec/pom.xml b/Java-base/tomcat-taglibs-standard/src/spec/pom.xml new file mode 100644 index 000000000..9503381b2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/pom.xml @@ -0,0 +1,95 @@ + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-standard-spec + bundle + + Apache Standard Taglib Specification API + + + An implementation of the JSP Standard Tag Library (JSTL) Specification API. + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + provided + + + + junit + junit + test + + + org.easymock + easymock + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.groupId}.${project.artifactId};singleton=true + JSR-052 JavaServer Pages Standard Tag Library Specification + + Sun Microsystems, Inc. + 1.2 + javax.servlet.jsp.jstl*;version=1.2 + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../build-tools/src/main/resources/taglibs/checkstyle.xml + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/ConditionalTagSupport.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/ConditionalTagSupport.java new file mode 100644 index 000000000..f55386040 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/ConditionalTagSupport.java @@ -0,0 +1,162 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

Abstract class that facilitates implementation of conditional actions + * where the boolean result is exposed as a JSP scoped variable. The + * boolean result may then be used as the test condition in a <c:when> + * action.

+ *

This base class provides support for:

+ *
    + *
  • Conditional processing of the action's body based on the returned value + * of the abstract method condition().
  • + *
  • Storing the result of condition() as a Boolean object + * into a JSP scoped variable identified by attributes var and + * scope. + *
+ * + * @author Shawn Bayern + */ +public abstract class ConditionalTagSupport + extends TagSupport { + //********************************************************************* + // Abstract methods + + /** + *

Subclasses implement this method to compute the boolean result + * of the conditional action. This method is invoked once per tag invocation + * by doStartTag(). + * + * @return a boolean representing the condition that a particular subclass + * uses to drive its conditional logic. + */ + protected abstract boolean condition() throws JspTagException; + + + //********************************************************************* + // Constructor + + /** + * Base constructor to initialize local state. As with TagSupport, + * subclasses should not implement constructors with arguments, and + * no-argument constructors implemented by subclasses must call the + * superclass constructor. + */ + public ConditionalTagSupport() { + super(); + init(); + } + + + //********************************************************************* + // Lifecycle management and implementation of conditional behavior + + /** + * Includes its body if condition() evaluates to true. + */ + @Override + public int doStartTag() throws JspException { + + // execute our condition() method once per invocation + result = condition(); + + // expose variables if appropriate + exposeVariables(); + + // handle conditional behavior + if (result) { + return EVAL_BODY_INCLUDE; + } else { + return SKIP_BODY; + } + } + + /** + * Releases any resources this ConditionalTagSupport may have (or inherit). + */ + @Override + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // Private state + + private boolean result; // the saved result of condition() + private String var; // scoped attribute name + private int scope; // scoped attribute scope + + + //********************************************************************* + // Accessors + + /** + * Sets the 'var' attribute. + * + * @param var Name of the exported scoped variable storing the result of + * condition(). + */ + public void setVar(String var) { + this.var = var; + } + + /** + * Sets the 'scope' attribute. + * + * @param scope Scope of the 'var' attribute + */ + public void setScope(String scope) { + if (scope.equalsIgnoreCase("page")) { + this.scope = PageContext.PAGE_SCOPE; + } else if (scope.equalsIgnoreCase("request")) { + this.scope = PageContext.REQUEST_SCOPE; + } else if (scope.equalsIgnoreCase("session")) { + this.scope = PageContext.SESSION_SCOPE; + } else if (scope.equalsIgnoreCase("application")) { + this.scope = PageContext.APPLICATION_SCOPE; + } + // TODO: Add error handling? Needs direction from spec. + } + + + //********************************************************************* + // Utility methods + + // expose attributes if we have a non-null 'var' + + private void exposeVariables() { + if (var != null) { + pageContext.setAttribute(var, Boolean.valueOf(result), scope); + } + } + + // initializes internal state + + private void init() { + result = false; // not really necessary + var = null; + scope = PageContext.PAGE_SCOPE; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/Config.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/Config.java new file mode 100644 index 000000000..6980f75ff --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/Config.java @@ -0,0 +1,358 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.jsp.PageContext; + +/** + * Class supporting access to configuration settings. + */ +public class Config { + + /* + * I18N/Formatting actions related configuration data + */ + + /** + * Name of configuration setting for application- (as opposed to browser-) + * based preferred locale + */ + public static final String FMT_LOCALE + = "jakarta.servlet.jsp.jstl.fmt.locale"; + + /** + * Name of configuration setting for fallback locale + */ + public static final String FMT_FALLBACK_LOCALE + = "jakarta.servlet.jsp.jstl.fmt.fallbackLocale"; + + /** + * Name of configuration setting for i18n localization context + */ + public static final String FMT_LOCALIZATION_CONTEXT + = "jakarta.servlet.jsp.jstl.fmt.localizationContext"; + + /** + * Name of localization setting for time zone + */ + public static final String FMT_TIME_ZONE + = "jakarta.servlet.jsp.jstl.fmt.timeZone"; + + /* + * SQL actions related configuration data + */ + + /** + * Name of configuration setting for SQL data source + */ + public static final String SQL_DATA_SOURCE + = "jakarta.servlet.jsp.jstl.sql.dataSource"; + + /** + * Name of configuration setting for maximum number of rows to be included + * in SQL query result + */ + public static final String SQL_MAX_ROWS + = "jakarta.servlet.jsp.jstl.sql.maxRows"; + + /* + * Private constants + */ + private static final String PAGE_SCOPE_SUFFIX = ".page"; + private static final String REQUEST_SCOPE_SUFFIX = ".request"; + private static final String SESSION_SCOPE_SUFFIX = ".session"; + private static final String APPLICATION_SCOPE_SUFFIX = ".application"; + + /** + * Looks up a configuration variable in the given scope. + *

The lookup of configuration variables is performed as if each scope + * had its own name space, that is, the same configuration variable name + * in one scope does not replace one stored in a different scope. + * + * @param pc Page context in which the configuration variable is to be + * looked up + * @param name Configuration variable name + * @param scope Scope in which the configuration variable is to be looked + * up + * @return The java.lang.Object associated with the configuration + * variable, or null if it is not defined. + */ + public static Object get(PageContext pc, String name, int scope) { + switch (scope) { + case PageContext.PAGE_SCOPE: + return pc.getAttribute(name + PAGE_SCOPE_SUFFIX, scope); + case PageContext.REQUEST_SCOPE: + return pc.getAttribute(name + REQUEST_SCOPE_SUFFIX, scope); + case PageContext.SESSION_SCOPE: + return get(pc.getSession(), name); + case PageContext.APPLICATION_SCOPE: + return pc.getAttribute(name + APPLICATION_SCOPE_SUFFIX, scope); + default: + throw new IllegalArgumentException("unknown scope"); + } + } + + /** + * Looks up a configuration variable in the "request" scope. + *

The lookup of configuration variables is performed as if each scope + * had its own name space, that is, the same configuration variable name + * in one scope does not replace one stored in a different scope. + * + * @param request Request object in which the configuration variable is to + * be looked up + * @param name Configuration variable name + * @return The java.lang.Object associated with the configuration + * variable, or null if it is not defined. + */ + public static Object get(ServletRequest request, String name) { + return request.getAttribute(name + REQUEST_SCOPE_SUFFIX); + } + + /** + * Looks up a configuration variable in the "session" scope. + *

The lookup of configuration variables is performed as if each scope + * had its own name space, that is, the same configuration variable name + * in one scope does not replace one stored in a different scope.

+ * + * @param session Session object in which the configuration variable is to + * be looked up + * @param name Configuration variable name + * @return The java.lang.Object associated with the configuration + * variable, or null if it is not defined, if session is null, or if the session + * is invalidated. + */ + public static Object get(HttpSession session, String name) { + Object ret = null; + if (session != null) { + try { + ret = session.getAttribute(name + SESSION_SCOPE_SUFFIX); + } catch (IllegalStateException ex) { + } // when session is invalidated + } + return ret; + } + + /** + * Looks up a configuration variable in the "application" scope. + *

The lookup of configuration variables is performed as if each scope + * had its own name space, that is, the same configuration variable name + * in one scope does not replace one stored in a different scope. + * + * @param context Servlet context in which the configuration variable is + * to be looked up + * @param name Configuration variable name + * @return The java.lang.Object associated with the configuration + * variable, or null if it is not defined. + */ + public static Object get(ServletContext context, String name) { + return context.getAttribute(name + APPLICATION_SCOPE_SUFFIX); + } + + /** + * Sets the value of a configuration variable in the given scope. + *

Setting the value of a configuration variable is performed as if + * each scope had its own namespace, that is, the same configuration + * variable name in one scope does not replace one stored in a different + * scope. + * + * @param pc Page context in which the configuration variable is to be set + * @param name Configuration variable name + * @param value Configuration variable value + * @param scope Scope in which the configuration variable is to be set + */ + public static void set(PageContext pc, String name, Object value, + int scope) { + switch (scope) { + case PageContext.PAGE_SCOPE: + pc.setAttribute(name + PAGE_SCOPE_SUFFIX, value, scope); + break; + case PageContext.REQUEST_SCOPE: + pc.setAttribute(name + REQUEST_SCOPE_SUFFIX, value, scope); + break; + case PageContext.SESSION_SCOPE: + pc.setAttribute(name + SESSION_SCOPE_SUFFIX, value, scope); + break; + case PageContext.APPLICATION_SCOPE: + pc.setAttribute(name + APPLICATION_SCOPE_SUFFIX, value, scope); + break; + default: + throw new IllegalArgumentException("unknown scope"); + } + } + + /** + * Sets the value of a configuration variable in the "request" scope. + *

Setting the value of a configuration variable is performed as if + * each scope had its own namespace, that is, the same configuration + * variable name in one scope does not replace one stored in a different + * scope. + * + * @param request Request object in which the configuration variable is to + * be set + * @param name Configuration variable name + * @param value Configuration variable value + */ + public static void set(ServletRequest request, String name, Object value) { + request.setAttribute(name + REQUEST_SCOPE_SUFFIX, value); + } + + /** + * Sets the value of a configuration variable in the "session" scope. + *

Setting the value of a configuration variable is performed as if + * each scope had its own namespace, that is, the same configuration + * variable name in one scope does not replace one stored in a different + * scope. + * + * @param session Session object in which the configuration variable is to + * be set + * @param name Configuration variable name + * @param value Configuration variable value + */ + public static void set(HttpSession session, String name, Object value) { + session.setAttribute(name + SESSION_SCOPE_SUFFIX, value); + } + + /** + * Sets the value of a configuration variable in the "application" scope. + *

Setting the value of a configuration variable is performed as if + * each scope had its own namespace, that is, the same configuration + * variable name in one scope does not replace one stored in a different + * scope. + * + * @param context Servlet context in which the configuration variable is to + * be set + * @param name Configuration variable name + * @param value Configuration variable value + */ + public static void set(ServletContext context, String name, Object value) { + context.setAttribute(name + APPLICATION_SCOPE_SUFFIX, value); + } + + /** + * Removes a configuration variable from the given scope. + *

Removing a configuration variable is performed as if each scope had + * its own namespace, that is, the same configuration variable name in one + * scope does not impact one stored in a different scope. + * + * @param pc Page context from which the configuration variable is to be + * removed + * @param name Configuration variable name + * @param scope Scope from which the configuration variable is to be + * removed + */ + public static void remove(PageContext pc, String name, int scope) { + switch (scope) { + case PageContext.PAGE_SCOPE: + pc.removeAttribute(name + PAGE_SCOPE_SUFFIX, scope); + break; + case PageContext.REQUEST_SCOPE: + pc.removeAttribute(name + REQUEST_SCOPE_SUFFIX, scope); + break; + case PageContext.SESSION_SCOPE: + pc.removeAttribute(name + SESSION_SCOPE_SUFFIX, scope); + break; + case PageContext.APPLICATION_SCOPE: + pc.removeAttribute(name + APPLICATION_SCOPE_SUFFIX, scope); + break; + default: + throw new IllegalArgumentException("unknown scope"); + } + } + + /** + * Removes a configuration variable from the "request" scope. + *

Removing a configuration variable is performed as if each scope had + * its own namespace, that is, the same configuration variable name in one + * scope does not impact one stored in a different scope. + * + * @param request Request object from which the configuration variable is + * to be removed + * @param name Configuration variable name + */ + public static void remove(ServletRequest request, String name) { + request.removeAttribute(name + REQUEST_SCOPE_SUFFIX); + } + + /** + * Removes a configuration variable from the "session" scope. + *

Removing a configuration variable is performed as if each scope had + * its own namespace, that is, the same configuration variable name in one + * scope does not impact one stored in a different scope. + * + * @param session Session object from which the configuration variable is + * to be removed + * @param name Configuration variable name + */ + public static void remove(HttpSession session, String name) { + session.removeAttribute(name + SESSION_SCOPE_SUFFIX); + } + + /** + * Removes a configuration variable from the "application" scope. + *

Removing a configuration variable is performed as if each scope had + * its own namespace, that is, the same configuration variable name in one + * scope does not impact one stored in a different scope. + * + * @param context Servlet context from which the configuration variable is + * to be removed + * @param name Configuration variable name + */ + public static void remove(ServletContext context, String name) { + context.removeAttribute(name + APPLICATION_SCOPE_SUFFIX); + } + + /** + * Finds the value associated with a specific configuration setting + * identified by its context initialization parameter name. + *

For each of the JSP scopes (page, request, session, application), + * get the value of the configuration variable identified by name + * using method get(). Return as soon as a non-null value is + * found. If no value is found, get the value of the context initialization + * parameter identified by name. + * + * @param pc Page context in which the configuration setting is to be + * searched + * @param name Context initialization parameter name of the configuration + * setting + * @return The java.lang.Object associated with the configuration + * setting identified by name, or null if it is not defined. + */ + public static Object find(PageContext pc, String name) { + Object ret = get(pc, name, PageContext.PAGE_SCOPE); + if (ret == null) { + ret = get(pc, name, PageContext.REQUEST_SCOPE); + if (ret == null) { + if (pc.getSession() != null) { + // check session only if a session is present + ret = get(pc, name, PageContext.SESSION_SCOPE); + } + if (ret == null) { + ret = get(pc, name, PageContext.APPLICATION_SCOPE); + if (ret == null) { + ret = pc.getServletContext().getInitParameter(name); + } + } + } + } + + return ret; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IndexedValueExpression.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IndexedValueExpression.java new file mode 100644 index 000000000..a6b364a13 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IndexedValueExpression.java @@ -0,0 +1,109 @@ +/** + * 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 jakarta.servlet.jsp.jstl.core; + +import java.io.Serializable; + +import jakarta.el.ELContext; +import jakarta.el.ValueExpression; + +/** + * ValueExpression that refers to a specific member of an indexed variable. + * This allows individual members of an indexed collection to be used as lvalues. + */ +public final class IndexedValueExpression extends ValueExpression implements Serializable { + // serialVersionUID value defined by specification JavaDoc + private static final long serialVersionUID = 1L; + + /** + * The index variable. + */ + protected final Integer i; + + /** + * The indexed variable. + */ + protected final ValueExpression orig; + + /** + * Constructor specifying indexed variable and index. + * + * @param valueExpression that evaluates to the indexed variable + * @param i index specifying the member + */ + public IndexedValueExpression(ValueExpression valueExpression, int i) { + orig = valueExpression; + this.i = i; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + IndexedValueExpression that = (IndexedValueExpression) o; + return i.equals(that.i) && orig.equals(that.orig); + } + + @Override + public Class getExpectedType() { + return orig.getExpectedType(); + } + + @Override + public String getExpressionString() { + return orig.getExpressionString(); + } + + @Override + public Class getType(ELContext elContext) { + return elContext.getELResolver().getType(elContext, orig.getValue(elContext), i); + } + + @Override + public Object getValue(ELContext elContext) { + return elContext.getELResolver().getValue(elContext, orig.getValue(elContext), i); + } + + @Override + public int hashCode() { + return orig.hashCode() + i; + } + + @Override + public boolean isLiteralText() { + return false; + } + + @Override + public boolean isReadOnly(ELContext elContext) { + return elContext.getELResolver().isReadOnly(elContext, orig.getValue(elContext), i); + } + + @Override + public void setValue(ELContext elContext, Object arg1) { + elContext.getELResolver().setValue(elContext, orig.getValue(elContext), i, arg1); + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedExpression.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedExpression.java new file mode 100644 index 000000000..13570c434 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedExpression.java @@ -0,0 +1,162 @@ +/** + * 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 jakarta.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 jakarta.el.ELContext; +import jakarta.el.ValueExpression; + +/** + * Helper class for accessing members of a deferred expression result by index. + */ +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; + + /** + * Constructor specifying the expression to access. + * If the expression evaluates to a String, then it will be split using the specified delimiters. + * + * @param orig the original expression to be accessed + * @param delims delimiters to be used to split a String result + */ + public IteratedExpression(ValueExpression orig, String delims) { + this.orig = orig; + this.delims = delims; + } + + /** + * Iterates the original expression and returns the value at the index. + * + * @param context against which the expression should be evaluated + * @param i the index of the value to return + * @return the value at the index + */ + 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; + } + + /** + * Returns the original expression. + * + * @return the original expression + */ + 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; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedValueExpression.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedValueExpression.java new file mode 100644 index 000000000..6d4dc5a96 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/IteratedValueExpression.java @@ -0,0 +1,94 @@ +/** + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.el.ELContext; +import jakarta.el.ValueExpression; + +/** + * ValueExpression that refers to a specific member of an indexed variable backed by an IteratedExpression. + * This allows individual members of an indexed collection to be used as lvalues. + */ +public final class IteratedValueExpression extends ValueExpression { + // serialVersionUID value defined by specification JavaDoc + private static final long serialVersionUID = 1L; + + protected final int i; + // TODO: IteratedExpression is not serializable - should this be ignored? + protected final IteratedExpression iteratedExpression; + + public IteratedValueExpression(IteratedExpression _iteratedExpr, int i) { + iteratedExpression = _iteratedExpr; + this.i = i; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + + IteratedValueExpression that = (IteratedValueExpression) obj; + return i == that.i && iteratedExpression.equals(that.iteratedExpression); + } + + @Override + public Class getExpectedType() { + return iteratedExpression.getValueExpression().getExpectedType(); + } + + @Override + public String getExpressionString() { + return iteratedExpression.getValueExpression().getExpressionString(); + } + + @Override + public Class getType(ELContext elContext) { + return iteratedExpression.getValueExpression().getType(elContext); + } + + @Override + public Object getValue(ELContext elContext) { + return iteratedExpression.getItem(elContext, i); + } + + @Override + public int hashCode() { + return iteratedExpression.hashCode() + i; + } + + @Override + public boolean isLiteralText() { + return false; + } + + @Override + public boolean isReadOnly(ELContext elContext) { + return true; + } + + @Override + public void setValue(ELContext elContext, Object arg1) { + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTag.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTag.java new file mode 100644 index 000000000..6a4551321 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTag.java @@ -0,0 +1,54 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.servlet.jsp.tagext.Tag; + +/** + *

JSTL allows developers to write custom iteration tags by + * implementing the LoopTag interface. This is not to be confused + * with javax.servlet.jsp.tagext.IterationTag as defined in JSP 1.2. + * LoopTag establishes a mechanism for iteration tags to be recognized + * and for type-safe implicit collaboration with custom subtags. + *

In most cases, it will not be necessary to implement this interface + * manually, for a base support class (LoopTagSupport) is provided + * to facilitate implementation.

+ * + * @author Shawn Bayern + */ + +public interface LoopTag extends Tag { + + /** + * Retrieves the current item in the iteration. Behaves + * idempotently; calling getCurrent() repeatedly should return the same + * Object until the iteration is advanced. (Specifically, calling + * getCurrent() does not advance the iteration.) + * + * @return the current item as an object + */ + public Object getCurrent(); + + /** + * Retrieves a 'status' object to provide information about the + * current round of the iteration. + * + * @return The LoopTagStatus for the current LoopTag. + */ + public LoopTagStatus getLoopStatus(); +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagStatus.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagStatus.java new file mode 100644 index 000000000..d9a40f5f0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagStatus.java @@ -0,0 +1,121 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +/** + *

Exposes the current status of + * an iteration. JSTL provides a mechanism for LoopTags to + * return information about the current index of the iteration and + * convenience methods to determine whether or not the current round is + * either the first or last in the iteration. It also lets authors + * use the status object to obtain information about the iteration range, + * step, and current object.

+ *

Environments that require more status can extend this interface.

+ * + * @author Shawn Bayern + */ + +public interface LoopTagStatus { + + /** + * Retrieves the current item in the iteration. Behaves + * idempotently; calling getCurrent() repeatedly should return the same + * Object until the iteration is advanced. (Specifically, calling + * getCurrent() does not advance the iteration.) + * + * @return the current item as an object + */ + public Object getCurrent(); + + /** + * Retrieves the index of the current round of the iteration. If + * iteration is being performed over a subset of an underlying + * array, java.lang.Collection, or other type, the index returned + * is absolute with respect to the underlying collection. Indices + * are 0-based. + * + * @return the 0-based index of the current round of the iteration + */ + public int getIndex(); + + /** + *

Retrieves the "count" of the current round of the iteration. The + * count is a relative, 1-based sequence number identifying the + * current "round" of iteration (in context with all rounds the + * current iteration will perform).

+ *

As an example, an iteration with begin = 5, end = 15, and step = + * 5 produces the counts 1, 2, and 3 in that order.

+ * + * @return the 1-based count of the current round of the iteration + */ + public int getCount(); + + /** + * Returns information about whether the current round of the + * iteration is the first one. This current round may be the 'first' + * even when getIndex() != 0, for 'index' refers to the absolute + * index of the current 'item' in the context of its underlying + * collection. It is always that case that a true result from + * isFirst() implies getCount() == 1. + * + * @return true if the current round is the first in the + * iteration, false otherwise. + */ + public boolean isFirst(); + + /** + * Returns information about whether the current round of the + * iteration is the last one. As with isFirst(), subsetting is + * taken into account. isLast() doesn't necessarily refer to the + * status of the underlying Iterator; it refers to whether or not + * the current round will be the final round of iteration for the + * tag associated with this LoopTagStatus. + * + * @return true if the current round is the last in the + * iteration, false otherwise. + */ + public boolean isLast(); + + /** + * Returns the value of the 'begin' attribute for the associated tag, + * or null if no 'begin' attribute was specified. + * + * @return the 'begin' value for the associated tag, or null + * if no 'begin' attribute was specified + */ + public Integer getBegin(); + + /** + * Returns the value of the 'end' attribute for the associated tag, + * or null if no 'end' attribute was specified. + * + * @return the 'end' value for the associated tag, or null + * if no 'end' attribute was specified + */ + public Integer getEnd(); + + /** + * Returns the value of the 'step' attribute for the associated tag, + * or null if no 'step' attribute was specified. + * + * @return the 'step' value for the associated tag, or null + * if no 'step' attribute was specified + */ + public Integer getStep(); + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java new file mode 100644 index 000000000..85e86035e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java @@ -0,0 +1,655 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.el.ELContext; +import jakarta.el.ValueExpression; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.IterationTag; +import jakarta.servlet.jsp.tagext.TagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; + +/** + *

Base support class to facilitate implementation of iteration tags.

+ *

Since most iteration tags will behave identically with respect to + * actual iterative behavior, JSTL provides this + * base support class to facilitate implementation. Many iteration tags + * will extend this and merely implement the hasNext() and + * next() methods + * to provide contents for the handler to iterate over.

+ *

In particular, this base class provides support for:

+ *
    + *
  • Iteration control, based on protected prepare(), next(), + * and hasNext() methods + *
  • Subsetting (begin, end, step>functionality, + * including validation + * of subset parameters for sensibility) + *
  • item retrieval (getCurrent()) + *
  • status retrieval (LoopTagStatus) + *
  • exposing attributes (set by var and varStatus attributes) + *
+ *

In providing support for these tasks, LoopTagSupport contains + * certain control variables that act to modify the iteration. Accessors + * are provided for these control variables when the variables represent + * information needed or wanted at translation time (e.g., var, + * varStatus). For + * other variables, accessors cannot be provided here since subclasses + * may differ on their implementations of how those accessors are received. + * For instance, one subclass might accept a String and convert it into + * an object of a specific type by using an expression evaluator; others + * might accept objects directly. Still others might not want to expose + * such information to outside control.

+ * + * @author Shawn Bayern + */ + +public abstract class LoopTagSupport + extends TagSupport + implements LoopTag, IterationTag, TryCatchFinally { + //********************************************************************* + // 'Protected' state + + /* + * JavaBean-style properties and other state slaved to them. These + * properties can be set directly by accessors; they will not be + * modified by the LoopTagSupport implementation -- and should + * not be modified by subclasses outside accessors unless those + * subclasses are perfectly aware of what they're doing. + * (An example where such non-accessor modification might be sensible + * is in the doStartTag() method of an EL-aware subclass.) + */ + + /** + * Starting index ('begin' attribute) + */ + protected int begin; + + /** + * Ending index of the iteration ('end' attribute). + * A value of -1 internally indicates 'no end + * specified', although accessors for the core JSTL tags do not + * allow this value to be supplied directly by the user. + */ + protected int end; + + /** + * Iteration step ('step' attribute) + */ + protected int step; + + /** + * Boolean flag indicating whether 'begin' was specified. + */ + protected boolean beginSpecified; + + /** + * Boolean flag indicating whether 'end' was specified. + */ + protected boolean endSpecified; + + /** + * Boolean flag indicating whether 'step' was specified. + */ + protected boolean stepSpecified; + + /** + * Attribute-exposing control + */ + protected String itemId, statusId; + + protected ValueExpression deferredExpression; + + //********************************************************************* + // 'Private' state (implementation details) + + /* + * State exclusively internal to the default, reference implementation. + * (While this state is kept private to ensure consistency, 'status' + * and 'item' happen to have one-for-one, read-only, accesor methods + * as part of the LoopTag interface.) + * + * 'last' is kept separately for two reasons: (a) to avoid + * running a computation every time it's requested, and (b) to + * let LoopTagStatus.isLast() avoid throwing any exceptions, + * which would complicate subtag and scripting-variable use. + * + * Our 'internal index' begins at 0 and increases by 'step' each + * round; this is arbitrary, but it seemed a simple way of keeping + * track of the information we need. To avoid computing + * getLoopStatus().getCount() by dividing index / step, we keep + * a separate 'count' and increment it by 1 each round (as a minor + * performance improvement). + */ + private LoopTagStatus status; // our LoopTagStatus + private Object item; // the current item + private int index; // the current internal index + private int count; // the iteration count + private boolean last; // current round == last one? + + //********************************************************************* + // Constructor + + /** + * Constructs a new LoopTagSupport. As with TagSupport, subclasses + * should not implement constructors with arguments, and no-arguments + * constructors implemented by subclasses must call the superclass + * constructor. + */ + public LoopTagSupport() { + super(); + init(); + } + + + //********************************************************************* + // Abstract methods + + /** + *

Returns the next object over which the tag should iterate. This + * method must be provided by concrete subclasses of LoopTagSupport + * to inform the base logic about what objects it should iterate over.

+ *

It is expected that this method will generally be backed by an + * Iterator, but this will not always be the case. In particular, if + * retrieving the next object raises the possibility of an exception + * being thrown, this method allows that exception to propagate back + * to the JSP container as a JspTagException; a standalone Iterator + * would not be able to do this. (This explains why LoopTagSupport + * does not simply call for an Iterator from its subtags.)

+ * + * @return the java.lang.Object to use in the next round of iteration + * @throws java.util.NoSuchElementException + * if next() is called but no new elements are available + * @throws jakarta.servlet.jsp.JspTagException + * for other, unexpected exceptions + */ + protected abstract Object next() throws JspTagException; + + /** + *

Returns information concerning the availability of more items + * over which to iterate. This method must be provided by concrete + * subclasses of LoopTagSupport to assist the iterative logic + * provided by the supporting base class.

+ *

See next for more information about the + * purpose and expectations behind this tag.

+ * + * @return true if there is at least one more item to iterate + * over, false otherwise + * @throws jakarta.servlet.jsp.JspTagException + * + * @see #next + */ + protected abstract boolean hasNext() throws JspTagException; + + /** + *

Prepares for a single tag invocation. Specifically, allows + * subclasses to prepare for calls to hasNext() and next(). + * Subclasses can assume that prepare() will be called once for + * each invocation of doStartTag() in the superclass.

+ * + * @throws jakarta.servlet.jsp.JspTagException + * + */ + protected abstract void prepare() throws JspTagException; + + + //********************************************************************* + // Lifecycle management and implementation of iterative behavior + + /** + * Releases any resources this LoopTagSupport may have (or inherit). + */ + @Override + public void release() { + super.release(); + init(); + } + + /** + * Begins iterating by processing the first item. + */ + @Override + public int doStartTag() throws JspException { + if (end != -1 && begin > end) { + // JSTL 1.1. We simply do not execute the loop. + return SKIP_BODY; + } + + // we're beginning a new iteration, so reset our counts (etc.) + index = 0; + count = 1; + last = false; + + // let the subclass conduct any necessary preparation + prepare(); + + // throw away the first 'begin' items (if they exist) + discardIgnoreSubset(begin); + + // get the item we're interested in + if (hasNext()) + // index is 0-based, so we don't update it for the first item + { + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to include our body... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_INCLUDE; + } + + /** + * Continues the iteration when appropriate -- that is, if we (a) have + * more items and (b) don't run over our 'end' (given our 'step'). + */ + @Override + public int doAfterBody() throws JspException { + + // re-sync the index, given our prior behind-the-scenes 'step' + index += step - 1; + + // increment the count by 1 for each round + count++; + + // everything's been prepared for us, so just get the next item + if (hasNext() && !atEnd()) { + index++; + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to re-iterate... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_AGAIN; + } + + /** + * Removes any attributes that this LoopTagSupport set. + *

These attributes are intended to support scripting variables with + * NESTED scope, so we don't want to pollute attribute space by leaving + * them lying around. + */ + public void doFinally() { + /* + * Make sure to un-expose variables, restoring them to their + * prior values, if applicable. + */ + unExposeVariables(); + } + + /** + * Rethrows the given Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + //********************************************************************* + // Accessor methods + + /* + * Overview: The getXXX() methods we provide implement the Tag + * contract. setXXX() accessors are provided only for those + * properties (attributes) that must be known at translation time, + * on the premise that these accessors will vary less than the + * others in terms of their interface with the page author. + */ + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this if necessary, but such a need is + * expected to be rare.) + */ + + public Object getCurrent() { + return item; + } + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this method for more fine-grained control + * over LoopTagStatus, but an effort has been made to simplify + * implementation of subclasses that are happy with reasonable default + * behavior.) + */ + + public LoopTagStatus getLoopStatus() { + + // local implementation with reasonable default behavior + class Status implements LoopTagStatus { + + /* + * All our methods are straightforward. We inherit + * our JavaDoc from LoopTagSupport; see that class + * for more information. + */ + + public Object getCurrent() { + /* + * Access the item through getCurrent() instead of just + * returning the item our containing class stores. This + * should allow a subclass of LoopTagSupport to override + * getCurrent() without having to rewrite getLoopStatus() too. + */ + return (LoopTagSupport.this.getCurrent()); + } + + public int getIndex() { + return (index + begin); // our 'index' isn't getIndex() + } + + public int getCount() { + return (count); + } + + public boolean isFirst() { + return (index == 0); // our 'index' isn't getIndex() + } + + public boolean isLast() { + return (last); // use cached value + } + + public Integer getBegin() { + if (beginSpecified) { + return (new Integer(begin)); + } else { + return null; + } + } + + public Integer getEnd() { + if (endSpecified) { + return (new Integer(end)); + } else { + return null; + } + } + + public Integer getStep() { + if (stepSpecified) { + return (new Integer(step)); + } else { + return null; + } + } + } + + /* + * We just need one per invocation... Actually, for the current + * implementation, we just need one per instance, but I'd rather + * not keep the reference around once release() has been called. + */ + if (status == null) { + status = new Status(); + } + + return status; + } + + /* + * We only support setter methods for attributes that need to be + * offered as Strings or other literals; other attributes will be + * handled directly by implementing classes, since there might be + * both rtexprvalue- and EL-based varieties, which will have + * different signatures. (We can't pollute child classes by having + * base implementations of those setters here; child classes that + * have attributes with different signatures would end up having + * two incompatible setters, which is illegal for a JavaBean. + */ + + /** + * Sets the 'var' attribute. + * + * @param id Name of the exported scoped variable storing the current item + * of the iteration. + */ + public void setVar(String id) { + this.itemId = id; + } + + /** + * Sets the 'varStatus' attribute. + * + * @param statusId Name of the exported scoped variable storing the status + * of the iteration. + */ + public void setVarStatus(String statusId) { + this.statusId = statusId; + } + + + //********************************************************************* + // Protected utility methods + + /* + * These methods validate attributes common to iteration tags. + * Call them if your own subclassing implementation modifies them + * -- e.g., if you set them through an expression language. + */ + + /** + * Ensures the "begin" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateBegin() throws JspTagException { + if (begin < 0) { + throw new JspTagException("'begin' < 0"); + } + } + + /** + * Ensures the "end" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateEnd() throws JspTagException { + if (end < 0) { + throw new JspTagException("'end' < 0"); + } + } + + /** + * Ensures the "step" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateStep() throws JspTagException { + if (step < 1) { + throw new JspTagException("'step' <= 0"); + } + } + + + //********************************************************************* + // Private utility methods + + /** + * (Re)initializes state (during release() or construction) + */ + private void init() { + // defaults for internal bookkeeping + index = 0; // internal index always starts at 0 + count = 1; // internal count always starts at 1 + status = null; // we clear status on release() + item = null; // item will be retrieved for each round + last = false; // last must be set explicitly + beginSpecified = false; // not specified until it's specified :-) + endSpecified = false; // (as above) + stepSpecified = false; // (as above) + deferredExpression = null; + + // defaults for interface with page author + begin = 0; // when not specified, 'begin' is 0 by spec. + end = -1; // when not specified, 'end' is not used + step = 1; // when not specified, 'step' is 1 + itemId = null; // when not specified, no variable exported + statusId = null; // when not specified, no variable exported + } + + /** + * Sets 'last' appropriately. + */ + private void calibrateLast() throws JspTagException { + /* + * the current round is the last one if (a) there are no remaining + * elements, or (b) the next one is beyond the 'end'. + */ + last = !hasNext() || atEnd() || + (end != -1 && (begin + index + step > end)); + } + + /** + * Exposes attributes (formerly scripting variables, but no longer!) + * if appropriate. Note that we don't really care, here, whether they're + * scripting variables or not. + */ + private void exposeVariables() throws JspTagException { + + 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) { + pageContext.removeAttribute(statusId, PageContext.PAGE_SCOPE); + } else { + pageContext.setAttribute(statusId, getLoopStatus()); + } + } + + } + + /** + * Removes page attributes that we have exposed and, if applicable, + * restores them to their prior values (and scopes). + */ + private void unExposeVariables() { + 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); + } + } + + /** + * Cycles through and discards up to 'n' items from the iteration. + * We only know "up to 'n'", not "exactly n," since we stop cycling + * if hasNext() returns false or if we hit the 'end' of the iteration. + * Note: this does not update the iteration index, since this method + * is intended as a behind-the-scenes operation. The index must be + * updated separately. (I don't really like this, but it's the simplest + * way to support isLast() without storing two separate inconsistent + * indices. We need to (a) make sure hasNext() refers to the next + * item we actually *want* and (b) make sure the index refers to the + * item associated with the *current* round, not the next one. + * C'est la vie.) + */ + private void discard(int n) throws JspTagException { + /* + * copy index so we can restore it, but we need to update it + * as we work so that atEnd() works + */ + int oldIndex = index; + while (n-- > 0 && !atEnd() && hasNext()) { + index++; + next(); + } + index = oldIndex; + } + + /** + * Discards items ignoring subsetting rules. Useful for discarding + * items from the beginning (i.e., to implement 'begin') where we + * don't want factor in the 'begin' value already. + */ + private void discardIgnoreSubset(int n) throws JspTagException { + while (n-- > 0 && hasNext()) { + next(); + } + } + + /** + * Returns true if the iteration has past the 'end' index (with + * respect to subsetting), false otherwise. ('end' must be set + * for atEnd() to return true; if 'end' is not set, atEnd() + * always returns false.) + */ + 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/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/JakartaInline.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/JakartaInline.java new file mode 100644 index 000000000..717c76e4e --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/JakartaInline.java @@ -0,0 +1,437 @@ +/* + * 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 jakarta.servlet.jsp.jstl.fmt; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Vector; + +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.jstl.core.Config; + +class JakartaInline { + + // The jstl.jar and standard.jar had a cyclic dependency in this class. + // It depended on MessageSupport and BundleSupport in the standard.jar. + // Inlining code from standard.jar as private code here - note exists + // in the originals to keep in sync. Ick. + + + // Copied over from the implementation's MessageSupport class + // while making the jars non-cyclic + // impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/MessageSupport.java + static final String UNDEFINED_KEY = "???"; + + + // All of the rest is copied from + // impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java + // === START OF COPY FROM BundleSupport === + //********************************************************************* + // Private constants + private static final Locale EMPTY_LOCALE = new Locale("", ""); + + /** + * Gets the default I18N localization context. + * + * @param pc Page in which to look up the default I18N localization context + */ + static LocalizationContext getLocalizationContext(PageContext pc) { + LocalizationContext locCtxt = null; + + Object obj = Config.find(pc, Config.FMT_LOCALIZATION_CONTEXT); + if (obj == null) { + return null; + } + + if (obj instanceof LocalizationContext) { + locCtxt = (LocalizationContext) obj; + } else { + // localization context is a bundle basename + locCtxt = getLocalizationContext(pc, (String) obj); + } + + return locCtxt; + } + + /** + * Gets the resource bundle with the given base name, whose locale is + * determined as follows: + *

Check if a match exists between the ordered set of preferred + * locales and the available locales, for the given base name. + * The set of preferred locales consists of a single locale + * (if the jakarta.servlet.jsp.jstl.fmt.locale configuration + * setting is present) or is equal to the client's preferred locales + * determined from the client's browser settings. + *

If no match was found in the previous step, check if a match + * exists between the fallback locale (given by the + * jakarta.servlet.jsp.jstl.fmt.fallbackLocale configuration + * setting) and the available locales, for the given base name. + * + * @param pageContext Page in which the resource bundle with the + * given base name is requested + * @param basename Resource bundle base name + * @return Localization context containing the resource bundle with the + * given base name and the locale that led to the resource bundle match, + * or the empty localization context if no resource bundle match was found + */ + static LocalizationContext getLocalizationContext(PageContext pc, + String basename) { + LocalizationContext locCtxt = null; + ResourceBundle bundle = null; + + if ((basename == null) || basename.equals("")) { + return new LocalizationContext(); + } + + // Try preferred locales + Locale pref = getLocale(pc, Config.FMT_LOCALE); + if (pref != null) { + // Preferred locale is application-based + bundle = findMatch(basename, pref); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, pref); + } + } else { + // Preferred locales are browser-based + locCtxt = findMatch(pc, basename); + } + + if (locCtxt == null) { + // No match found with preferred locales, try using fallback locale + pref = getLocale(pc, Config.FMT_FALLBACK_LOCALE); + if (pref != null) { + bundle = findMatch(basename, pref); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, pref); + } + } + } + + if (locCtxt == null) { + // try using the root resource bundle with the given basename + try { + ClassLoader cl = getClassLoaderCheckingPrivilege(); + bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE, cl); + if (bundle != null) { + locCtxt = new LocalizationContext(bundle, null); + } + } catch (MissingResourceException mre) { + // do nothing + } + } + + if (locCtxt != null) { + // set response locale + if (locCtxt.getLocale() != null) { + setResponseLocale(pc, locCtxt.getLocale()); + } + } else { + // create empty localization context + locCtxt = new LocalizationContext(); + } + + return locCtxt; + } + + + //********************************************************************* + // Private utility methods + + /* + * Determines the client's preferred locales from the request, and compares + * each of the locales (in order of preference) against the available + * locales in order to determine the best matching locale. + * + * @param pageContext the page in which the resource bundle with the + * given base name is requested + * @param basename the resource bundle's base name + * + * @return the localization context containing the resource bundle with + * the given base name and best matching locale, or null if no + * resource bundle match was found + */ + + private static LocalizationContext findMatch(PageContext pageContext, + String basename) { + LocalizationContext locCtxt = null; + + // Determine locale from client's browser settings. + + for (Enumeration enum_ = getRequestLocales((HttpServletRequest) pageContext.getRequest()); + enum_.hasMoreElements();) { + Locale pref = (Locale) enum_.nextElement(); + ResourceBundle match = findMatch(basename, pref); + if (match != null) { + locCtxt = new LocalizationContext(match, pref); + break; + } + } + + return locCtxt; + } + + /* + * Gets the resource bundle with the given base name and preferred locale. + * + * This method calls java.util.ResourceBundle.getBundle(), but ignores + * its return value unless its locale represents an exact or language match + * with the given preferred locale. + * + * @param basename the resource bundle base name + * @param pref the preferred locale + * + * @return the requested resource bundle, or null if no resource + * bundle with the given base name exists or if there is no exact- or + * language-match between the preferred locale and the locale of + * the bundle returned by java.util.ResourceBundle.getBundle(). + */ + + private static ResourceBundle findMatch(String basename, Locale pref) { + ResourceBundle match = null; + + try { + ClassLoader cl = getClassLoaderCheckingPrivilege(); + ResourceBundle bundle = ResourceBundle.getBundle(basename, pref, cl); + Locale avail = bundle.getLocale(); + if (pref.equals(avail)) { + // Exact match + match = bundle; + } else { + /* + * We have to make sure that the match we got is for + * the specified locale. The way ResourceBundle.getBundle() + * works, if a match is not found with (1) the specified locale, + * it tries to match with (2) the current default locale as + * returned by Locale.getDefault() or (3) the root resource + * bundle (basename). + * We must ignore any match that could have worked with (2) or (3). + * So if an exact match is not found, we make the following extra + * tests: + * - avail locale must be equal to preferred locale + * - avail country must be empty or equal to preferred country + * (the equality match might have failed on the variant) + */ + if (pref.getLanguage().equals(avail.getLanguage()) + && ("".equals(avail.getCountry()) || pref.getCountry().equals(avail.getCountry()))) { + /* + * Language match. + * By making sure the available locale does not have a + * country and matches the preferred locale's language, we + * rule out "matches" based on the container's default + * locale. For example, if the preferred locale is + * "en-US", the container's default locale is "en-UK", and + * there is a resource bundle (with the requested base + * name) available for "en-UK", ResourceBundle.getBundle() + * will return it, but even though its language matches + * that of the preferred locale, we must ignore it, + * because matches based on the container's default locale + * are not portable across different containers with + * different default locales. + */ + match = bundle; + } + } + } catch (MissingResourceException mre) { + } + + 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() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + return cl; + } + // === END OF COPY FROM BundleSupport === + + // impl/src/main/java/org/apache/taglibs/standard/tag/common/core/Util.java + // === START OF COPY FROM Util TO SUPPORT BundleSupport === + + /** + * HttpServletRequest.getLocales() returns the server's default locale + * if the request did not specify a preferred language. + * We do not want this behavior, because it prevents us from using + * the fallback locale. + * We therefore need to return an empty Enumeration if no preferred + * locale has been specified. This way, the logic for the fallback + * locale will be able to kick in. + */ + public static Enumeration getRequestLocales(HttpServletRequest request) { + Enumeration values = request.getHeaders("accept-language"); + if (values == null) { + // No header for "accept-language". Simply return + // a new empty enumeration. + // System.out.println("Null accept-language"); + return new Vector().elements(); + } else if (values.hasMoreElements()) { + // At least one "accept-language". Simply return + // the enumeration returned by request.getLocales(). + // System.out.println("At least one accept-language"); + return request.getLocales(); + } else { + // No header for "accept-language". Simply return + // the empty enumeration. + // System.out.println("No accept-language"); + return values; + } + } + // === END OF COPY FROM Util TO SUPPORT BundleSupport === + + // === START OF COPY FROM SetLocaleSupport TO SUPPORT BundleSupport === + + //********************************************************************* + // Private constants + + private static final char HYPHEN = '-'; + private static final char UNDERSCORE = '_'; + + /* + * Stores the given locale in the response object of the given page + * context, and stores the locale's associated charset in the + * jakarta.servlet.jsp.jstl.fmt.request.charset session attribute, which + * may be used by the action in a page invoked by a + * form included in the response to set the request charset to the same as + * the response charset (this makes it possible for the container to + * decode the form parameter values properly, since browsers typically + * encode form field values using the response's charset). + * + * @param pageContext the page context whose response object is assigned + * the given locale + * @param locale the response locale + */ + + static void setResponseLocale(PageContext pc, Locale locale) { + // set response locale + ServletResponse response = pc.getResponse(); + response.setLocale(locale); + + // get response character encoding and store it in session attribute + if (pc.getSession() != null) { + try { + pc.setAttribute(REQUEST_CHAR_SET, response.getCharacterEncoding(), + PageContext.SESSION_SCOPE); + } catch (IllegalStateException ex) { + } // invalidated session ignored + } + } + + /* + * Returns the locale specified by the named scoped attribute or context + * configuration parameter. + * + *

The named scoped attribute is searched in the page, request, + * session (if valid), and application scope(s) (in this order). If no such + * attribute exists in any of the scopes, the locale is taken from the + * named context configuration parameter. + * + * @param pageContext the page in which to search for the named scoped + * attribute or context configuration parameter + * @param name the name of the scoped attribute or context configuration + * parameter + * + * @return the locale specified by the named scoped attribute or context + * configuration parameter, or null if no scoped attribute or + * configuration parameter with the given name exists + */ + + static Locale getLocale(PageContext pageContext, String name) { + Locale loc = null; + + Object obj = Config.find(pageContext, name); + if (obj != null) { + if (obj instanceof Locale) { + loc = (Locale) obj; + } else { + loc = parseLocale((String) obj, null); + } + } + + return loc; + } + + /** + * Parses the given locale string into its language and (optionally) + * country components, and returns the corresponding + * java.util.Locale object. + *

If the given locale string is null or empty, the runtime's default + * locale is returned. + * + * @param locale the locale string to parse + * @param variant the variant + * @return java.util.Locale object corresponding to the given + * locale string, or the runtime's default locale if the locale string is + * null or empty + * @throws IllegalArgumentException if the given locale does not have a + * language component or has an empty country component + */ + private static Locale parseLocale(String locale, String variant) { + + Locale ret = null; + String language = locale; + String country = null; + int index = -1; + + if (((index = locale.indexOf(HYPHEN)) > -1) + || ((index = locale.indexOf(UNDERSCORE)) > -1)) { + language = locale.substring(0, index); + country = locale.substring(index + 1); + } + + if ((language == null) || (language.length() == 0)) { + // LOCALE_NO_LANGUAGE + throw new IllegalArgumentException("Missing language component in 'value' attribute in <setLocale>"); + } + + if (country == null) { + if (variant != null) { + ret = new Locale(language, "", variant); + } else { + ret = new Locale(language, ""); + } + } else if (country.length() > 0) { + if (variant != null) { + ret = new Locale(language, country, variant); + } else { + ret = new Locale(language, country); + } + } else { + // LOCALE_EMPTY_COUNTRY + throw new IllegalArgumentException("Empty country component in 'value' attribute in <setLocale>"); + } + + return ret; + } + // === END OF COPY FROM SetLocaleSupport TO SUPPORT BundleSupport === + + static final String REQUEST_CHAR_SET = + "jakarta.servlet.jsp.jstl.fmt.request.charset"; +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocaleSupport.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocaleSupport.java new file mode 100644 index 000000000..b3844c6de --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocaleSupport.java @@ -0,0 +1,150 @@ +/* + * 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 jakarta.servlet.jsp.jstl.fmt; + +import java.text.MessageFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import jakarta.servlet.jsp.PageContext; + +/** + * Class which exposes the locale-determination logic for resource bundles + * through convenience methods. + *

This class may be useful to any tag handler implementation that needs + * to produce localized messages. For example, this might be useful for + * exception messages that are intended directly for user consumption on an + * error page. + * + * @author Jan Luehe + */ + +public class LocaleSupport { + + /** + * Retrieves the localized message corresponding to the given key. + *

The given key is looked up in the resource bundle of the default + * I18N localization context, which is retrieved from the + * jakarta.servlet.jsp.jstl.fmt.localizationContext configuration + * setting. + *

If the configuration setting is empty, or the default I18N + * localization context does not contain any resource bundle, or the given + * key is undefined in its resource bundle, the string "???<key>???" is + * returned, where "<key>" is replaced with the given key. + * + * @param pageContext the page in which to get the localized message + * corresponding to the given key + * @param key the message key + * @return the localized message corresponding to the given key + */ + public static String getLocalizedMessage(PageContext pageContext, + String key) { + return getLocalizedMessage(pageContext, key, null, null); + } + + /** + * Retrieves the localized message corresponding to the given key. + *

The given key is looked up in the resource bundle with the given + * base name. + *

If no resource bundle with the given base name exists, or the given + * key is undefined in the resource bundle, the string "???<key>???" is + * returned, where "<key>" is replaced with the given key. + * + * @param pageContext the page in which to get the localized message + * corresponding to the given key + * @param key the message key + * @param basename the resource bundle base name + * @return the localized message corresponding to the given key + */ + public static String getLocalizedMessage(PageContext pageContext, + String key, + String basename) { + return getLocalizedMessage(pageContext, key, null, basename); + } + + /** + * Retrieves the localized message corresponding to the given key, and + * performs parametric replacement using the arguments specified via + * args. + *

See the specification of the <fmt:message> action for a description + * of how parametric replacement is implemented. + *

The localized message is retrieved as in + * {@link #getLocalizedMessage(jakarta.servlet.jsp.PageContext,java.lang.String) getLocalizedMessage(pageContext, key)}. + * + * @param pageContext the page in which to get the localized message + * corresponding to the given key + * @param key the message key + * @param args the arguments for parametric replacement + * @return the localized message corresponding to the given key + */ + public static String getLocalizedMessage(PageContext pageContext, + String key, + Object[] args) { + return getLocalizedMessage(pageContext, key, args, null); + } + + /** + * Retrieves the localized message corresponding to the given key, and + * performs parametric replacement using the arguments specified via + * args. + *

See the specification of the <fmt:message> action for a description + * of how parametric replacement is implemented. + *

The localized message is retrieved as in + * {@link #getLocalizedMessage(jakarta.servlet.jsp.PageContext,java.lang.String, java.lang.String) getLocalizedMessage(pageContext, key, basename)}. + * + * @param pageContext the page in which to get the localized message + * corresponding to the given key + * @param key the message key + * @param args the arguments for parametric replacement + * @param basename the resource bundle base name + * @return the localized message corresponding to the given key + */ + public static String getLocalizedMessage(PageContext pageContext, + String key, + Object[] args, + String basename) { + LocalizationContext locCtxt = null; + String message = JakartaInline.UNDEFINED_KEY + key + JakartaInline.UNDEFINED_KEY; + + if (basename != null) { + locCtxt = JakartaInline.getLocalizationContext(pageContext, basename); + } else { + locCtxt = JakartaInline.getLocalizationContext(pageContext); + } + + if (locCtxt != null) { + ResourceBundle bundle = locCtxt.getResourceBundle(); + if (bundle != null) { + try { + message = bundle.getString(key); + if (args != null) { + MessageFormat formatter = new MessageFormat(""); + if (locCtxt.getLocale() != null) { + formatter.setLocale(locCtxt.getLocale()); + } + formatter.applyPattern(message); + message = formatter.format(args); + } + } catch (MissingResourceException mre) { + } + } + } + + return message; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocalizationContext.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocalizationContext.java new file mode 100644 index 000000000..d3380366d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/fmt/LocalizationContext.java @@ -0,0 +1,98 @@ +/* + * 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 jakarta.servlet.jsp.jstl.fmt; + +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * Class representing an I18N localization context. + *

An I18N localization context has two components: a resource bundle and + * the locale that led to the resource bundle match. + *

The resource bundle component is used by <fmt:message> for mapping + * message keys to localized messages, and the locale component is used by the + * <fmt:message>, <fmt:formatNumber>, <fmt:parseNumber>, <fmt:formatDate>, + * and <fmt:parseDate> actions as their formatting or parsing locale, respectively. + * + * @author Jan Luehe + */ + +public class LocalizationContext { + + // the localization context's resource bundle + final private ResourceBundle bundle; + + // the localization context's locale + final private Locale locale; + + /** + * Constructs an empty I18N localization context. + */ + public LocalizationContext() { + bundle = null; + locale = null; + } + + /** + * Constructs an I18N localization context from the given resource bundle + * and locale. + *

The specified locale is the application- or browser-based preferred + * locale that led to the resource bundle match. + * + * @param bundle The localization context's resource bundle + * @param locale The localization context's locale + */ + public LocalizationContext(ResourceBundle bundle, Locale locale) { + this.bundle = bundle; + this.locale = locale; + } + + /** + * Constructs an I18N localization context from the given resource bundle. + *

The localization context's locale is taken from the given + * resource bundle. + * + * @param bundle The resource bundle + */ + public LocalizationContext(ResourceBundle bundle) { + this.bundle = bundle; + this.locale = bundle.getLocale(); + } + + /** + * Gets the resource bundle of this I18N localization context. + * + * @return The resource bundle of this I18N localization context, or null + * if this I18N localization context is empty + */ + public ResourceBundle getResourceBundle() { + return bundle; + } + + /** + * Gets the locale of this I18N localization context. + * + * @return The locale of this I18N localization context, or null if this + * I18N localization context is empty, or its resource bundle is a + * (locale-less) root resource bundle. + */ + public Locale getLocale() { + return locale; + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/Result.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/Result.java new file mode 100644 index 000000000..60b03e972 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/Result.java @@ -0,0 +1,92 @@ +/* + * 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 jakarta.servlet.jsp.jstl.sql; + +import java.util.SortedMap; + +/** + *

This interface represents the result of a <sql:query> + * action. It provides access to the following information in the + * query result:

+ *
    + *
  • The result rows (getRows() and getRowsByIndex()) + *
  • The column names (getColumnNames()) + *
  • The number of rows in the result (getRowCount()) + *
  • An indication whether the rows returned represent the complete result + * or just a subset that is limited by a maximum row setting + * (isLimitedByMaxRows()) + *
+ *

An implementation of the Result interface provides a + * disconnected view into the result of a query. + * + * @author Justyna Horwat + */ +public interface Result { + + /** + *

Returns the result of the query as an array of SortedMap objects. + * Each item of the array represents a specific row in the query result.

+ *

A row is structured as a SortedMap object where the key is the column name, + * and where the value is the value associated with the column identified by + * the key. The column value is an Object of the Java type corresponding + * to the mapping between column types and Java types defined by the JDBC + * specification when the ResultSet.getObject() method is used.

+ *

The SortedMap must use the Comparator + * java.util.String.CASE_INSENSITIVE_ORDER. + * This makes it possible to access the key as a case insensitive representation + * of a column name. This method will therefore work regardless of the case of + * the column name returned by the database.

+ * + * @return The result rows as an array of SortedMap objects + */ + public SortedMap[] getRows(); + + /** + * Returns the result of the query as an array of arrays. + * The first array dimension represents a specific row in the query result. + * The array elements for each row are Object instances of the Java type + * corresponding to the mapping between column types and Java types defined + * by the JDBC specification when the ResultSet.getObject() method is used. + * + * @return the result rows as an array of Object[] objects + */ + public Object[][] getRowsByIndex(); + + /** + * Returns the names of the columns in the result. The order of the names in the array + * matches the order in which columns are returned in method getRowsByIndex(). + * + * @return the column names as an array of String objects + */ + public String[] getColumnNames(); + + /** + * Returns the number of rows in the cached ResultSet + * + * @return the number of rows in the result + */ + public int getRowCount(); + + /** + * Returns true if the query was limited by a maximum row setting + * + * @return true if the query was limited by a maximum + * row setting + */ + public boolean isLimitedByMaxRows(); +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultImpl.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultImpl.java new file mode 100644 index 000000000..d7901b5b1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultImpl.java @@ -0,0 +1,172 @@ +/* + * 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 jakarta.servlet.jsp.jstl.sql; + +import java.io.Serializable; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + *

This class creates a cached version of a ResultSet. + * It's represented as a Result implementation, capable of + * returing an array of Row objects containing a Column + * instance for each column in the row. It is not part of the JSTL + * API; it serves merely as a back-end to ResultSupport's static methods. + * Thus, we scope its access to the package. + * + * @author Hans Bergsten + * @author Justyna Horwat + */ + +class ResultImpl implements Result, Serializable { + private List rowMap; + private List rowByIndex; + private String[] columnNames; + private boolean isLimited; + + /** + * This constructor reads the ResultSet and saves a cached + * copy. + * It's important to note that this object will be serializable only + * if the objects returned by the ResultSet are serializable too. + * + * @param rs an open ResultSet, positioned before the first + * row + * @param startRow beginning row to be cached + * @param maxRows query maximum rows limit + * @throws java.sql.SQLException if a database error occurs + */ + public ResultImpl(ResultSet rs, int startRow, int maxRows) + throws SQLException { + rowMap = new ArrayList(); + rowByIndex = new ArrayList(); + + ResultSetMetaData rsmd = rs.getMetaData(); + int noOfColumns = rsmd.getColumnCount(); + + // Create the column name array + columnNames = new String[noOfColumns]; + for (int i = 1; i <= noOfColumns; i++) { + columnNames[i - 1] = rsmd.getColumnLabel(i); + } + + // Throw away all rows upto startRow + for (int i = 0; i < startRow; i++) { + rs.next(); + } + + // Process the remaining rows upto maxRows + int processedRows = 0; + while (rs.next()) { + if ((maxRows != -1) && (processedRows == maxRows)) { + isLimited = true; + break; + } + Object[] columns = new Object[noOfColumns]; + SortedMap columnMap = + new TreeMap(String.CASE_INSENSITIVE_ORDER); + + // JDBC uses 1 as the lowest index! + for (int i = 1; i <= noOfColumns; i++) { + Object value = rs.getObject(i); + if (rs.wasNull()) { + value = null; + } + columns[i - 1] = value; + columnMap.put(columnNames[i - 1], value); + } + rowMap.add(columnMap); + rowByIndex.add(columns); + processedRows++; + } + } + + /** + * Returns an array of SortedMap objects. The SortedMap + * object key is the ColumnName and the value is the ColumnValue. + * SortedMap was created using the CASE_INSENSITIVE_ORDER + * Comparator so the key is the case insensitive representation + * of the ColumnName. + * + * @return an array of Map, or null if there are no rows + */ + public SortedMap[] getRows() { + if (rowMap == null) { + return null; + } + + //should just be able to return SortedMap[] object + return (SortedMap[]) rowMap.toArray(new SortedMap[0]); + } + + + /** + * Returns an array of Object[] objects. The first index + * designates the Row, the second the Column. The array + * stores the value at the specified row and column. + * + * @return an array of Object[], or null if there are no rows + */ + public Object[][] getRowsByIndex() { + if (rowByIndex == null) { + return null; + } + + //should just be able to return Object[][] object + return (Object[][]) rowByIndex.toArray(new Object[0][0]); + } + + /** + * Returns an array of String objects. The array represents + * the names of the columns arranged in the same order as in + * the getRowsByIndex() method. + * + * @return an array of String[] + */ + public String[] getColumnNames() { + return columnNames; + } + + /** + * Returns the number of rows in the cached ResultSet + * + * @return the number of cached rows, or -1 if the Result could + * not be initialized due to SQLExceptions + */ + public int getRowCount() { + if (rowMap == null) { + return -1; + } + return rowMap.size(); + } + + /** + * Returns true if the query was limited by a maximum row setting + * + * @return true if the query was limited by a MaxRows attribute + */ + public boolean isLimitedByMaxRows() { + return isLimited; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultSupport.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultSupport.java new file mode 100644 index 000000000..11a33dba1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/ResultSupport.java @@ -0,0 +1,68 @@ +/* + * 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 jakarta.servlet.jsp.jstl.sql; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + *

Supports the creation of a jakarta.servlet.jsp.jstl.sql.Result object + * from a source java.sql.ResultSet object. A Result object makes it much + * easier for page authors to access and manipulate the data resulting + * from a SQL query.

+ *

Note that these methods hide any SQLExceptions that are caused and return + * null - to work around that + * use org.apache.taglibs.standard.tag.common.sql.ResultImpl directly. + * + * @author Justyna Horwat + */ +public class ResultSupport { + + + /** + * Converts a ResultSet object to a Result object. + * + * @param rs the ResultSet object + * @return The Result object created from the ResultSet + */ + public static Result toResult(ResultSet rs) { + try { + return new ResultImpl(rs, -1, -1); + } catch (SQLException ex) { + return null; + } + } + + /** + * Converts maxRows of a ResultSet object to a + * Result object. + * + * @param rs the ResultSet object + * @param maxRows the maximum number of rows to be cached into the Result object. + * @return The Result object created from the ResultSet, + * limited by maxRows + */ + public static Result toResult(ResultSet rs, int maxRows) { + try { + return new ResultImpl(rs, -1, maxRows); + } catch (SQLException ex) { + return null; + } + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/SQLExecutionTag.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/SQLExecutionTag.java new file mode 100644 index 000000000..20d94c9b1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/sql/SQLExecutionTag.java @@ -0,0 +1,56 @@ +/* + * 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 jakarta.servlet.jsp.jstl.sql; + +/** + *

This interface allows tag handlers implementing it to receive + * values for parameter markers in their SQL statements.

+ *

This interface is implemented by both <sql:query> and + * <sql:update>. Its addSQLParameter() method + * is called by nested parameter actions (such as <sql:param>) + * to substitute PreparedStatement parameter values for + * "?" parameter markers in the SQL statement of the enclosing + * SQLExecutionTag action.

+ *

The given parameter values are converted to their corresponding + * SQL type (following the rules in the JDBC specification) before + * they are sent to the database.

+ *

Keeping track of the index of the parameter values being added + * is the responsibility of the tag handler implementing this + * interface

+ *

The SQLExcecutionTag interface is exposed in order + * to support custom parameter actions which may retrieve their + * parameters from any source and process them before substituting + * them for a parameter marker in the SQL statement of the + * enclosing SQLExecutionTag action

+ * + * @author Justyna Horwat + */ +public interface SQLExecutionTag { + + /** + * Adds a PreparedStatement parameter value. + * Must behave as if it calls PreparedStatement.setObject(int, Object). + * For each tag invocation, the integral index passed logically to setObject() + * must begin with 1 and must be incremented by 1 for each subsequent invocation + * of addSQLParameter(). The Object logically passed to setObject() must be the + * unmodified object received in the value argument. + * + * @param value the PreparedStatement parameter value + */ + public void addSQLParameter(Object value); +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PageParser.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PageParser.java new file mode 100644 index 000000000..bdcd3b138 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PageParser.java @@ -0,0 +1,85 @@ +/* + * 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 jakarta.servlet.jsp.jstl.tlv; + +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import jakarta.servlet.jsp.tagext.PageData; +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Support class for working with the SAX Parser. + */ +class PageParser { + + private final SAXParserFactory parserFactory; + + PageParser(boolean namespaceAware) { + parserFactory = AccessController.doPrivileged(new PrivilegedAction() { + public SAXParserFactory run() { + ClassLoader original = Thread.currentThread().getContextClassLoader(); + ClassLoader ours = PageParser.class.getClassLoader(); + try { + if (original != ours) { + Thread.currentThread().setContextClassLoader(ours); + } + return SAXParserFactory.newInstance(); + } finally { + if (original != ours) { + Thread.currentThread().setContextClassLoader(original); + } + } + } + }); + try { + parserFactory.setNamespaceAware(namespaceAware); + parserFactory.setValidating(false); + parserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + } catch (ParserConfigurationException e) { + throw new ExceptionInInitializerError(e); + } catch (SAXNotRecognizedException e) { + throw new ExceptionInInitializerError(e); + } catch (SAXNotSupportedException e) { + throw new ExceptionInInitializerError(e); + } + } + + void parse(PageData pageData, DefaultHandler handler) throws ParserConfigurationException, SAXException, IOException { + SAXParser parser = parserFactory.newSAXParser(); + InputStream is = pageData.getInputStream(); + try { + parser.parse(is, handler); + } finally { + try { + is.close(); + } catch (IOException e) { + // Suppress. + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PermittedTaglibsTLV.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PermittedTaglibsTLV.java new file mode 100644 index 000000000..a15382774 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/PermittedTaglibsTLV.java @@ -0,0 +1,166 @@ +/* + * 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 jakarta.servlet.jsp.jstl.tlv; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.TagLibraryValidator; +import jakarta.servlet.jsp.tagext.ValidationMessage; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A TagLibraryValidator class to allow a TLD to restrict what + * taglibs (in addition to itself) may be imported on a page where it's + * used.

+ *

This TLV supports the following initialization parameter:

+ *
    + *
  • permittedTaglibs: A whitespace-separated list of URIs corresponding + * to tag libraries permitted to be imported on the page in addition to the tag + * library that references PermittedTaglibsTLV (which is allowed implicitly). + *
+ *

This implementation only detects tag libraries declared on the {@code } element, + * including libraries in regular JSP files or JSP Documents with a specific {@code }. + * It does not detect libraries declared on other elements as supported by JSP 2.0. + *

+ * + * @author Shawn Bayern + */ +public class PermittedTaglibsTLV extends TagLibraryValidator { + + //********************************************************************* + // Constants + + // parameter names + private static final String PERMITTED_TAGLIBS_PARAM = "permittedTaglibs"; + + // URI for "" element + private static final String JSP_ROOT_URI = "http://java.sun.com/JSP/Page"; + + // local name of "" element + private static final String JSP_ROOT_NAME = "root"; + + // QName for "" element + private static final String JSP_ROOT_QN = "jsp:root"; + + private static final PageParser parser = new PageParser(false); + + private final Set permittedTaglibs; // what URIs are allowed? + + public PermittedTaglibsTLV() { + permittedTaglibs = new HashSet(); + } + + @Override + public void setInitParameters(Map initParams) { + super.setInitParameters(initParams); + permittedTaglibs.clear(); + String uris = (String) initParams.get(PERMITTED_TAGLIBS_PARAM); + if (uris != null) { + StringTokenizer st = new StringTokenizer(uris); + while (st.hasMoreTokens()) { + permittedTaglibs.add(st.nextToken()); + } + } + } + + @Override + public ValidationMessage[] validate(String prefix, String uri, PageData page) { + try { + PermittedTaglibsHandler h = new PermittedTaglibsHandler(prefix, uri); + parser.parse(page, h); + return h.getResult(); + } catch (SAXException ex) { + return vmFromString(ex.toString()); + } catch (ParserConfigurationException ex) { + return vmFromString(ex.toString()); + } catch (IOException ex) { + return vmFromString(ex.toString()); + } + } + + + //********************************************************************* + // Utility functions + + // constructs a ValidationMessage[] from a single String and no ID + private ValidationMessage[] vmFromString(String message) { + return new ValidationMessage[]{new ValidationMessage(null, message)}; + } + + /** + * The handler that provides the base of our implementation. + */ + private class PermittedTaglibsHandler extends DefaultHandler { + private final String prefix; + private final String uri; + + private boolean failed; + + public PermittedTaglibsHandler(String prefix, String uri) { + this.prefix = prefix; + this.uri = uri; + } + + // TODO: https://issues.apache.org/bugzilla/show_bug.cgi?id=57290 (JSP2.0 Documents) + // If we had a way of determining if a namespace referred to a taglib as opposed to being + // part of XML output we might be able to simplify this using startPrefixMapping events. + @Override + public void startElement(String ns, String ln, String qn, Attributes a) { + // look at namespaces declared on the element + if (qn.equals(JSP_ROOT_QN) || (ns.equals(JSP_ROOT_URI) && ln.equals(JSP_ROOT_NAME))) { + for (int i = 0; i < a.getLength(); i++) { + String name = a.getQName(i); + + // ignore non-namespace attributes + if (!name.startsWith("xmlns:")) { + continue; + } + + String value = a.getValue(i); + // ignore any declaration for our taglib or the JSP namespace + if (value.equals(uri) || value.equals(JSP_ROOT_URI)) { + continue; + } + + // otherwise, ensure that 'value' is in 'permittedTaglibs' set + if (!permittedTaglibs.contains(value)) { + failed = true; + } + } + } + } + + private ValidationMessage[] getResult() { + if (failed) { + return vmFromString( + "taglib " + prefix + " (" + uri + ") allows only the " + + "following taglibs to be imported: " + permittedTaglibs); + } else { + return null; + } + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/ScriptFreeTLV.java b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/ScriptFreeTLV.java new file mode 100644 index 000000000..0bd39fc22 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/main/java/jakarta/servlet/jsp/jstl/tlv/ScriptFreeTLV.java @@ -0,0 +1,243 @@ +/* + * 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 jakarta.servlet.jsp.jstl.tlv; + +import java.io.IOException; +import java.util.Map; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.TagLibraryValidator; +import jakarta.servlet.jsp.tagext.ValidationMessage; +import javax.xml.parsers.ParserConfigurationException; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + *

A TagLibraryValidator for enforcing restrictions against + * the use of JSP scripting elements.

+ *

This TLV supports four initialization parameters, for controlling + * which of the four types of scripting elements are allowed or prohibited:

+ *
    + *
  • allowDeclarations: if true, indicates that declaration elements + * are not prohibited. + *
  • allowScriptlets: if true, indicates that scriptlets are not + * prohibited + *
  • allowExpressions: if true, indicates that top-level expression + * elements (i.e., expressions not associated with request-time attribute + * values) are not prohibited. + *
  • allowRTExpressions: if true, indicates that expression elements + * associated with request-time attribute values are not prohibited. + *
+ *

The default value for all for initialization parameters is false, + * indicating all forms of scripting elements are to be prohibited.

+ * + * @author Mark A. Kolb + * @author Shawn Bayern (minor changes) + */ +public class ScriptFreeTLV extends TagLibraryValidator { + + private static final PageParser parser = new PageParser(true); + + private boolean allowDeclarations = false; + private boolean allowScriptlets = false; + private boolean allowExpressions = false; + private boolean allowRTExpressions = false; + + /** + * Sets the values of the initialization parameters, as supplied in the TLD. + * + * @param initParms a mapping from the names of the initialization parameters + * to their values, as specified in the TLD. + */ + @Override + public void setInitParameters(Map initParms) { + super.setInitParameters(initParms); + String declarationsParm = (String) initParms.get("allowDeclarations"); + String scriptletsParm = (String) initParms.get("allowScriptlets"); + String expressionsParm = (String) initParms.get("allowExpressions"); + String rtExpressionsParm = (String) initParms.get("allowRTExpressions"); + + allowDeclarations = "true".equalsIgnoreCase(declarationsParm); + allowScriptlets = "true".equalsIgnoreCase(scriptletsParm); + allowExpressions = "true".equalsIgnoreCase(expressionsParm); + allowRTExpressions = "true".equalsIgnoreCase(rtExpressionsParm); + } + + /** + * Validates a single JSP page. + * + * @param prefix the namespace prefix specified by the page for the + * custom tag library being validated. + * @param uri the URI specified by the page for the TLD of the + * custom tag library being validated. + * @param page a wrapper around the XML representation of the page + * being validated. + * @return null, if the page is valid; otherwise, a ValidationMessage[] + * containing one or more messages indicating why the page is not valid. + */ + @Override + public ValidationMessage[] validate(String prefix, String uri, PageData page) { + try { + MyContentHandler handler = new MyContentHandler(); + parser.parse(page, handler); + return handler.reportResults(); + } catch (ParserConfigurationException e) { + return vmFromString(e.toString()); + } catch (SAXException e) { + return vmFromString(e.toString()); + } catch (IOException e) { + return vmFromString(e.toString()); + } + } + + /** + * Handler for SAX events. + * Four counters are provided as instance variables, + * for counting occurrences of prohibited scripting elements. + */ + private class MyContentHandler extends DefaultHandler { + private int declarationCount = 0; + private int scriptletCount = 0; + private int expressionCount = 0; + private int rtExpressionCount = 0; + + /** + * This event is received whenever a new element is encountered. + * The qualified name of each such element is compared against + * the names of any prohibited scripting elements. When found, the + * corresponding counter is incremented. + * If expressions representing request-time attribute values are + * prohibited, it is also necessary to check the values of all + * attributes specified by the element. (Trying to figure out + * which attributes actually support request-time attribute values + * and checking only those is far more trouble than it's worth.) + */ + @Override + public void startElement(String namespaceUri, + String localName, String qualifiedName, + Attributes atts) { + if ((!allowDeclarations) + && qualifiedName.equals("jsp:declaration")) { + ++declarationCount; + } else if ((!allowScriptlets) + && qualifiedName.equals("jsp:scriptlet")) { + ++scriptletCount; + } else if ((!allowExpressions) + && qualifiedName.equals("jsp:expression")) { + ++expressionCount; + } + if (!allowRTExpressions) { + countRTExpressions(atts); + } + } + + /** + * Auxiliary method for checking attribute values to see if + * are specified via request-time attribute values. + * Expressions representing request-time attribute values are + * recognized by their "%=" and "%" delimiters. When found, the + * corresponding counter is incremented. + */ + private void countRTExpressions(Attributes atts) { + int stop = atts.getLength(); + for (int i = 0; i < stop; ++i) { + String attval = atts.getValue(i); + if (attval.startsWith("%=") && attval.endsWith("%")) { + ++rtExpressionCount; + } + } + } + + /** + * Constructs a String reporting the number(s) of prohibited + * scripting elements that were detected, if any. + * Returns null if no violations were found, making the result + * of this method suitable for the return value of the + * TagLibraryValidator.validate() method. + *

TODO: The update from 7/13/2001 merely makes this validator + * compliant with the new TLV API, but does not fully take advantage + * of this API. In the future, we should do so... but because + * of the possibility that anti-script checking will be incorporated + * into the base TLV, I've held off for now and just changed this + * class to use the new API. -- SB. + */ + public ValidationMessage[] reportResults() { + if (declarationCount + scriptletCount + expressionCount + + rtExpressionCount > 0) { + StringBuilder results = new StringBuilder("JSP page contains "); + boolean first = true; + if (declarationCount > 0) { + results.append(Integer.toString(declarationCount)); + results.append(" declaration"); + if (declarationCount > 1) { + results.append('s'); + } + first = false; + } + if (scriptletCount > 0) { + if (!first) { + results.append(", "); + } + results.append(Integer.toString(scriptletCount)); + results.append(" scriptlet"); + if (scriptletCount > 1) { + results.append('s'); + } + first = false; + } + if (expressionCount > 0) { + if (!first) { + results.append(", "); + } + results.append(Integer.toString(expressionCount)); + results.append(" expression"); + if (expressionCount > 1) { + results.append('s'); + } + first = false; + } + if (rtExpressionCount > 0) { + if (!first) { + results.append(", "); + } + results.append(Integer.toString(rtExpressionCount)); + results.append(" request-time attribute value"); + if (rtExpressionCount > 1) { + results.append('s'); + } + first = false; + } + results.append("."); + return vmFromString(results.toString()); + } else { + return null; + } + } + } + + + // constructs a ValidationMessage[] from a single String and no ID + + private static ValidationMessage[] vmFromString(String message) { + return new ValidationMessage[]{ + new ValidationMessage(null, message) + }; + } + +} diff --git a/Java-base/tomcat-taglibs-standard/src/spec/src/test/java/javax/servlet/jsp/jstl/tlv/PermittedTaglibsTLVTest.java b/Java-base/tomcat-taglibs-standard/src/spec/src/test/java/javax/servlet/jsp/jstl/tlv/PermittedTaglibsTLVTest.java new file mode 100644 index 000000000..f43c3a9ed --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/spec/src/test/java/javax/servlet/jsp/jstl/tlv/PermittedTaglibsTLVTest.java @@ -0,0 +1,100 @@ +/* + * 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 jakarta.servlet.jsp.jstl.tlv; + +import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import jakarta.servlet.jsp.tagext.PageData; +import jakarta.servlet.jsp.tagext.ValidationMessage; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.easymock.EasyMock; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class PermittedTaglibsTLVTest { + + private static final String URI = "http://jakarta.apache.org/taglibs/standard/permittedTaglibs"; + + private PermittedTaglibsTLV tlv; + private PageData page; + private Map initParams = new HashMap(); + + @Before + public void createTlv() { + tlv = new PermittedTaglibsTLV(); + page = EasyMock.createMock(PageData.class); + } + + @Test + public void tagPermittedWhenDeclaredAtRoot() throws UnsupportedEncodingException { + initParams.put("permittedTaglibs", "urn:test"); + String xmlView = ""; + expect(page.getInputStream()).andStubReturn(new ByteArrayInputStream(xmlView.getBytes("UTF-8"))); + + replay(page); + tlv.setInitParameters(initParams); + ValidationMessage[] messages = tlv.validate(null, URI, page); + assertTrue(messages == null || messages.length == 0); + } + + @Test + public void tagNotPermittedWhenDeclaredAtRoot() throws UnsupportedEncodingException { + initParams.put("permittedTaglibs", "urn:none"); + String xmlView = ""; + expect(page.getInputStream()).andStubReturn(new ByteArrayInputStream(xmlView.getBytes("UTF-8"))); + + replay(page); + tlv.setInitParameters(initParams); + ValidationMessage[] messages = tlv.validate(null, URI, page); + assertNotNull(messages); + assertEquals(1, messages.length); + } + + @Ignore("https://issues.apache.org/bugzilla/show_bug.cgi?id=57290") + @Test + public void tagNotPermittedWhenDeclaredInPage() throws UnsupportedEncodingException { + initParams.put("permittedTaglibs", "urn:none"); + // In the page for this XML view, 'd' and 'x' are taglibs but 'o' is not + String xmlView = "\n" + + "\n" + + "\n" + + "\n" + + " \n" + + "\n" + + ""; + expect(page.getInputStream()).andStubReturn(new ByteArrayInputStream(xmlView.getBytes("UTF-8"))); + + replay(page); + tlv.setInitParameters(initParams); + ValidationMessage[] messages = tlv.validate(null, URI, page); + assertNotNull(messages); + assertEquals(1, messages.length); + } + + +} diff --git a/Java-base/tomcat-taglibs-standard/src/src/assembly/bin.xml b/Java-base/tomcat-taglibs-standard/src/src/assembly/bin.xml new file mode 100644 index 000000000..2a08ac123 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/src/assembly/bin.xml @@ -0,0 +1,43 @@ + + + bin + + tar.gz + zip + + false + + + + LICENSE.txt + NOTICE.txt + + + + target + + + *.jar + + + + target/site/apidocs + apidocs + + + diff --git a/Java-base/tomcat-taglibs-standard/src/src/assembly/src.xml b/Java-base/tomcat-taglibs-standard/src/src/assembly/src.xml new file mode 100644 index 000000000..631731a50 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/src/assembly/src.xml @@ -0,0 +1,36 @@ + + + src + + tar.gz + zip + + ${artifactId}-${project.version}-src + + + + LICENSE.txt + NOTICE.txt + pom.xml + + + + src + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/pom.xml b/Java-base/tomcat-taglibs-standard/src/standard-examples/pom.xml new file mode 100644 index 000000000..3dedaa41b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/pom.xml @@ -0,0 +1,101 @@ + + + + 4.0.0 + + org.apache.taglibs + taglibs-standard + 2.0.0-SNAPSHOT + + + taglibs-standard-examples + war + + Apache Standard Taglib Example WAR + + + An example WAR for the JSP Standard Tag Library (JSTL). + + + + + org.apache.taglibs + taglibs-standard-spec + ${project.version} + + + + org.apache.taglibs + taglibs-standard-impl + ${project.version} + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + provided + + + xalan + xalan + + + org.apache.derby + derby + 10.4.2.0 + + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.rat + apache-rat-plugin + + + + src/main/webapp/**/** + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Address.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Address.java new file mode 100644 index 000000000..18b9e8720 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Address.java @@ -0,0 +1,198 @@ +/* + * 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.taglibs.standard.examples.beans; + +/** + * Object that represents a Customer. + * + * @author Pierre Delisle + */ + +public class Address { + + //********************************************************************* + // Instance variables + + /** + * Holds value of property line1. + */ + private String line1; + + /** + * Holds value of property line2. + */ + private String line2; + + /** + * Holds value of property city. + */ + private String city; + + /** + * Holds value of property zip. + */ + private String zip; + + /** + * Holds value of property state. + */ + private String state; + + /** + * Holds value of property country. + */ + private String country; + + //********************************************************************* + // Constructor + + public Address(String line1, String line2, String city, + String state, String zip, String country) { + setLine1(line1); + setLine2(line2); + setCity(city); + setState(state); + setZip(zip); + setCountry(country); + } + + //********************************************************************* + // Accessors + + /** + * Getter for property line1. + * + * @return Value of property line1. + */ + public String getLine1() { + return line1; + } + + /** + * Setter for property line1. + * + * @param line1 New value of property line1. + */ + public void setLine1(String line1) { + this.line1 = line1; + } + + /** + * Getter for property line2. + * + * @return Value of property line2. + */ + public String getLine2() { + return line2; + } + + /** + * Setter for property line2. + * + * @param line2 New value of property line2. + */ + public void setLine2(String line2) { + this.line2 = line2; + } + + /** + * Getter for property city. + * + * @return Value of property city. + */ + public String getCity() { + return city; + } + + /** + * Setter for property city. + * + * @param city New value of property city. + */ + public void setCity(String city) { + this.city = city; + } + + /** + * Getter for property zip. + * + * @return Value of property zip. + */ + public String getZip() { + return zip; + } + + /** + * Setter for property zip. + * + * @param zip New value of property zip. + */ + public void setZip(String zip) { + this.zip = zip; + } + + /** + * Getter for property country. + * + * @return Value of property country. + */ + public String getCountry() { + return country; + } + + /** + * Setter for property country. + * + * @param country New value of property country. + */ + public void setCountry(String country) { + this.country = country; + } + + /** + * Getter for property state. + * + * @return Value of property state. + */ + public String getState() { + return state; + } + + /** + * Setter for property state. + * + * @param state New value of property state. + */ + public void setState(String state) { + this.state = state; + } + + //********************************************************************* + // Utility Methods + + /** + * Return a String representation of this object. + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(line1).append(" "); + sb.append(city).append(" "); + sb.append(country); + return (sb.toString()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customer.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customer.java new file mode 100644 index 000000000..106e6a4e5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customer.java @@ -0,0 +1,255 @@ +/* + * 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.taglibs.standard.examples.beans; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Object that represents a Customer. + * + * @author Pierre Delisle + */ + +public class Customer { + + //********************************************************************* + // Instance variables + + /** + * Holds value of property key. + */ + int key; + + /** + * Holds value of property lastName. + */ + private String lastName; + + /** + * Holds value of property firstName. + */ + private String firstName; + + /** + * Holds value of property birthDate. + */ + private Date birthDate; + + /** + * Holds value of property address. + */ + private Address address; + + /** + * Holds value of property phoneHome. + */ + private String phoneHome; + + /** + * Holds value of property phoneCell. + */ + private String phoneCell; + + static DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); + + //********************************************************************* + // Constructors + + public Customer() { + } + + public Customer(int key, + String lastName, + String firstName, + Date birthDate, + Address address, + String phoneHome, + String phoneCell) { + init(key, lastName, firstName, birthDate, address, phoneHome, phoneCell); + } + + public void init(int key, + String lastName, + String firstName, + Date birthDate, + Address address, + String phoneHome, + String phoneCell) { + setKey(key); + setLastName(lastName); + setFirstName(firstName); + setBirthDate(birthDate); + setAddress(address); + setPhoneHome(phoneHome); + setPhoneCell(phoneCell); + } + + //********************************************************************* + // Properties + + /** + * Getter for property key. + * + * @return Value of property key. + */ + public int getKey() { + return key; + } + + /** + * Setter for property key. + * + * @param key New value of property key. + */ + public void setKey(int key) { + this.key = key; + } + + /** + * Getter for property lastName. + * + * @return Value of property lastName. + */ + public String getLastName() { + return lastName; + } + + /** + * Setter for property lastName. + * + * @param lastName New value of property lastName. + */ + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + * Getter for property firstName. + * + * @return Value of property firstName. + */ + public String getFirstName() { + return firstName; + } + + /** + * Setter for property firstName. + * + * @param firstName New value of property firstName. + */ + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + * Getter for property birthDate. + * + * @return Value of property birthDate. + */ + public Date getBirthDate() { + return birthDate; + } + + /** + * Setter for property birthDate. + * + * @param birthDate New value of property birthDate. + */ + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + /** + * Getter for property address. + * + * @return Value of property address. + */ + public Address getAddress() { + return address; + } + + /** + * Setter for property address. + * + * @param address New value of property address. + */ + public void setAddress(Address address) { + this.address = address; + } + + /** + * Getter for property phoneHome. + * + * @return Value of property phoneHome. + */ + public String getPhoneHome() { + return phoneHome; + } + + /** + * Setter for property phoneHome. + * + * @param phoneHome New value of property phoneHome. + */ + public void setPhoneHome(String phoneHome) { + this.phoneHome = phoneHome; + } + + /** + * Getter for property phoneCell. + * + * @return Value of property phoneCell. + */ + public String getPhoneCell() { + return phoneCell; + } + + /** + * Setter for property phoneCell. + * + * @param phoneCell New value of property phoneCell. + */ + public void setPhoneCell(String phoneCell) { + this.phoneCell = phoneCell; + } + + //********************************************************************* + // Utility Methods + + /** + * Return a String representation of this object. + */ + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[").append(key).append("] "); + sb.append(getLastName()).append(", "); + sb.append(getFirstName()).append(" "); + sb.append(df.format(getBirthDate())).append(" "); + sb.append(getAddress()).append(" "); + if (getPhoneHome() != null) { + sb.append(getPhoneHome()).append(" "); + } + if (getPhoneCell() != null) { + sb.append(getPhoneCell()); + } + return (sb.toString()); + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customers.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customers.java new file mode 100644 index 000000000..5afd260fd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/beans/Customers.java @@ -0,0 +1,104 @@ +/* + * 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.taglibs.standard.examples.beans; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.Vector; + +/** + * Customers Datastore. + * + * @author Pierre Delisle + */ + +public class Customers { + + //********************************************************************* + // Instance variables + + private static Vector customers = new Vector(); + private static int nextSeqNo = 0; + + //********************************************************************* + // Datastore operations + + public static void create( + String lastName, + String firstName, + String birthDate, + String line1, + String line2, + String city, + String state, + String zip, + String country) { + create(lastName, firstName, birthDate, line1, line2, city, state, zip, + country, null, null); + } + + /** + * Create new customer + */ + public static void create( + String lastName, + String firstName, + String birthDate, + String line1, + String line2, + String city, + String state, + String zip, + String country, + String phoneHome, + String phoneCell) { + Customer customer = + new Customer(++nextSeqNo, lastName, firstName, + genDate(birthDate), genAddress(line1, line2, city, state, zip, country), + phoneHome, phoneCell); + customers.add(customer); + } + + /** + * Find all customers + */ + public static Collection findAll() { + return customers; + } + + //********************************************************************* + // Utility methods + + private static Date genDate(String dateString) { + DateFormat df = new SimpleDateFormat("M/d/y"); + Date date; + try { + date = df.parse(dateString); + } catch (Exception ex) { + date = null; + } + return date; + } + + private static Address genAddress(String line1, String line2, String city, + String state, String zip, String country) { + return new Address(line1, line2, city, state, zip, country); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources.java new file mode 100644 index 000000000..8ae42981c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.examples.i18n; + +import java.util.ListResourceBundle; + +public class Resources extends ListResourceBundle { + private static Object[][] contents; + + static { + contents = new Object[][]{ + {"greetingMorning", "Good Morning!"}, + {"greetingEvening", "Good Evening!"}, + {"serverInfo", "Name/Version of Servlet Container: {0}, " + + "Java Version: {1}"}, + {"currentTime", "Current time: {0}"}, + {"com.acme.labels.cancel", "Cancel"}, + {"java.lang.ArithmeticException", "division by 0"} + }; + } + + public Object[][] getContents() { + return contents; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_de.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_de.java new file mode 100644 index 000000000..0a62ee1e2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_de.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.examples.i18n; + +import java.util.ListResourceBundle; + +public class Resources_de extends ListResourceBundle { + private static Object[][] contents; + + static { + contents = new Object[][]{ + {"greetingMorning", "Guten Morgen!"}, + {"greetingEvening", "Guten Abend!"}, + {"serverInfo", "Name/Version des Servlet Containers: {0}, " + + "Java Version: {1}"}, + {"currentTime", "Heutiges Datum und Uhrzeit: {0}"}, + {"com.acme.labels.cancel", "Abbrechen"}, + {"java.lang.ArithmeticException", "/ durch 0"} + }; + } + + public Object[][] getContents() { + return contents; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_fr.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_fr.java new file mode 100644 index 000000000..3825bbb23 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_fr.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.examples.i18n; + +import java.util.ListResourceBundle; + +public class Resources_fr extends ListResourceBundle { + private static Object[][] contents; + + static { + contents = new Object[][]{ + {"greetingMorning", "Bonjour!!"}, + {"greetingEvening", "Bonsoir!"}, + {"serverInfo", "Nom/Version du Servlet Container: {0}, " + + "Version Java: {1}"}, + {"currentTime", "Nous sommes le: {0}"}, + {"com.acme.labels.cancel", "Annuler"}, + {"java.lang.ArithmeticException", "division par 0"} + }; + } + + public Object[][] getContents() { + return contents; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_it.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_it.java new file mode 100644 index 000000000..be819b112 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/i18n/Resources_it.java @@ -0,0 +1,34 @@ +/* + * 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.taglibs.standard.examples.i18n; + +import java.util.ListResourceBundle; + +public class Resources_it extends ListResourceBundle { + private static Object[][] contents; + + static { + contents = new Object[][]{ + {"greetingMorning", "Buon giorno!"} + }; + } + + public Object[][] getContents() { + return contents; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/startup/Init.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/startup/Init.java new file mode 100644 index 000000000..e00f14633 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/startup/Init.java @@ -0,0 +1,148 @@ +/* + * 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.taglibs.standard.examples.startup; + +import java.util.Enumeration; +import java.util.Hashtable; + +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; + +import org.apache.taglibs.standard.examples.beans.Customers; + +/** + * Initialization class. Builds all the data structures + * used in the "examples" webapp. + * + * @author Pierre Delisle + */ +public class Init implements ServletContextListener { + + //********************************************************************* + // ServletContextListener methods + + // recovers the one context parameter we need + + public void contextInitialized(ServletContextEvent sce) { + //p("contextInitialized"); + init(sce); + } + + public void contextDestroyed(ServletContextEvent sce) { + //p("contextInitialized"); + } + + //********************************************************************* + // Initializations + + private void init(ServletContextEvent sce) { + /* + * Customers + */ + Customers.create("Richard", "Maurice", "5/15/35", + "123 Chemin Royal", "Appt. #301", + "Montreal", "QC", "H3J 9R9", "Canada"); + Customers.create("Mikita", "Stan", "12/25/47", + "45 Fisher Blvd", "Suite 203", + "Chicago", "IL", "65982", "USA", "(320)876-9784", null); + Customers.create("Gilbert", "Rod", "3/11/51", + "123 Main Street", "", + "New-York City", "NY", "19432", "USA"); + Customers.create("Howe", "Gordie", "7/25/46", + "7654 Wings Street", "", + "Detroit", "MG", "07685", "USA", "(465)675-0761", "(465)879-9802"); + Customers.create("Sawchuk", "Terrie", "11/05/46", + "12 Maple Leafs Avenue", "", + "Toronto", "ON", "M5C 1Z1", "Canada"); + sce.getServletContext().setAttribute("customers", Customers.findAll()); + + /** + * Array of primitives (int) + */ + int[] intArray = new int[]{10, 20, 30, 40, 50}; + sce.getServletContext().setAttribute("intArray", intArray); + + /** + * Array of Objects (String) + */ + String[] stringArray = new String[]{ + "A first string", + "La deuxieme string", + "Ella troisiemo stringo", + }; + sce.getServletContext().setAttribute("stringArray", stringArray); + + /** + * String-keyed Map + */ + Hashtable stringMap = new Hashtable(); + sce.getServletContext().setAttribute("stringMap", stringMap); + stringMap.put("one", "uno"); + stringMap.put("two", "dos"); + stringMap.put("three", "tres"); + stringMap.put("four", "cuatro"); + stringMap.put("five", "cinco"); + stringMap.put("six", "seis"); + stringMap.put("seven", "siete"); + stringMap.put("eight", "ocho"); + stringMap.put("nine", "nueve"); + stringMap.put("ten", "diez"); + + /** + * Integer-keyed Map + */ + // we use a Hashtable so we can get an Enumeration easily, below + Hashtable numberMap = new Hashtable(); + sce.getServletContext().setAttribute("numberMap", numberMap); + numberMap.put(new Integer(1), "uno"); + numberMap.put(new Integer(2), "dos"); + numberMap.put(new Integer(3), "tres"); + numberMap.put(new Integer(4), "cuatro"); + numberMap.put(new Integer(5), "cinco"); + numberMap.put(new Integer(6), "seis"); + numberMap.put(new Integer(7), "siete"); + numberMap.put(new Integer(8), "ocho"); + numberMap.put(new Integer(9), "nueve"); + numberMap.put(new Integer(10), "diez"); + + /** + * Enumeration + */ + Enumeration enum_ = numberMap.keys(); + // don't use 'enum' for attribute name because it is a + // reserved word in EcmaScript. + sce.getServletContext().setAttribute("enumeration", enum_); + + /** + * Message arguments for parametric replacement + */ + Object[] serverInfoArgs = + new Object[]{ + sce.getServletContext().getServerInfo(), + System.getProperty("java.version") + }; + sce.getServletContext().setAttribute("serverInfoArgs", serverInfoArgs); + } + + //********************************************************************* + // Initializations + + private void p(String s) { + System.out.println("[Init] " + s); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/CustomerFmtTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/CustomerFmtTag.java new file mode 100644 index 000000000..139a57d64 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/CustomerFmtTag.java @@ -0,0 +1,127 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import java.io.IOException; + +import jakarta.servlet.jsp.JspWriter; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.examples.beans.Customer; + +/** + *

Tag handler for <customerFmt> + * + * @author Pierre Delisle + */ +public class CustomerFmtTag extends TagSupport { + + //********************************************************************* + // Instance variables + + /** + * Holds value of property customer. + */ + private Customer customer; + + /** + * Holds value of property fmt. + */ + private String fmt; + + //********************************************************************* + // Constructors + + public CustomerFmtTag() { + super(); + init(); + } + + private void init() { + customer = null; + fmt = null; + } + + //********************************************************************* + // TagSupport methods + + public int doStartTag() throws JspException { + JspWriter out = pageContext.getOut(); + try { + if (fmt.equalsIgnoreCase("short")) { + out.println(customer.getFirstName() + " " + + customer.getLastName()); + } else if (fmt.equalsIgnoreCase("long")) { + out.println(customer.getFirstName() + " " + + customer.getLastName() + " " + customer.getAddress()); + } else { + out.println("invalid format"); + } + } catch (IOException ex) { + } + + return SKIP_BODY; + } + + // Releases any resources we may have (or inherit) + + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // Accessors + + /** + * Getter for property customer. + * + * @return Value of property customer. + */ + public Customer getCustomer() { + return customer; + } + + /** + * Setter for property customer. + * + * @param customer New value of property customer. + */ + public void setCustomer(Customer customer) { + this.customer = customer; + } + + /** + * Getter for property fmt. + * + * @return Value of property fmt. + */ + public String getFmt() { + return fmt; + } + + /** + * Setter for property fmt. + * + * @param fmt New value of property fmt. + */ + public void setFmt(String fmt) { + this.fmt = fmt; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/DefaultLocaleTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/DefaultLocaleTag.java new file mode 100644 index 000000000..ba5c89419 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/DefaultLocaleTag.java @@ -0,0 +1,42 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; + +/** + *

Tag handler for <locales> + * + * @author Felipe Leme + */ + +public class DefaultLocaleTag extends ConditionalTagSupport { + + private static final Locale defaultLocale = Locale.getDefault(); + + public boolean condition() throws JspTagException { + LocalesTag localesTag = (LocalesTag) findAncestorWithClass(this, LocalesTag.class); + if (localesTag == null) { + throw new JspTagException("defaultLocale bust be inside locales"); + } + return localesTag.getCurrent().equals(defaultLocale); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EscapeHtmlTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EscapeHtmlTag.java new file mode 100644 index 000000000..2b36c7b97 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EscapeHtmlTag.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 org.apache.taglibs.standard.examples.taglib; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.tagext.BodyTagSupport; + +import org.apache.taglibs.standard.examples.util.Util; + +/** + *

Tag handler for <escapeHtml> + * + * @author Pierre Delisle + */ +public class EscapeHtmlTag extends BodyTagSupport { + + //********************************************************************* + // Instance variables + + private Object reader; + private Object writer; + + //********************************************************************* + // Constructors + + public EscapeHtmlTag() { + super(); + init(); + } + + private void init() { + reader = null; + writer = null; + } + + + //********************************************************************* + // Tag's properties + + /** + * Tag's 'reader' attribute + */ + public void setReader(Object reader) { + this.reader = reader; + } + + /** + * Tag's 'writer' attribute + */ + public void setWriter(Object writer) { + this.writer = writer; + } + + //********************************************************************* + // TagSupport methods + + public int doEndTag() throws JspException { + Reader in; + Writer out; + + if (reader == null) { + String bcs = getBodyContent().getString().trim(); + if (bcs == null || bcs.equals("")) { + throw new JspTagException("In <escapeHtml>, 'reader' " + + "not specified and no non-whitespace content inside the tag."); + } + in = Util.castToReader(bcs); + } else { + in = Util.castToReader(reader); + } + + if (writer == null) { + out = pageContext.getOut(); + } else { + out = Util.castToWriter(writer); + } + + transform(in, out); + return EVAL_PAGE; + } + + /** + * Releases any resources we may have (or inherit) + */ + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // Tag's scific behavior methods + + /** + * Transform + */ + public void transform(Reader reader, Writer writer) + throws JspException { + int c; + try { + writer.write("

");
+            while ((c = reader.read()) != -1) {
+                if (c == '<') {
+                    writer.write("<");
+                } else if (c == '>') {
+                    writer.write(">");
+                } else {
+                    writer.write(c);
+                }
+            }
+            writer.write("
"); + } catch (IOException ex) { + throw new JspException("EscapeHtml: " + + "error copying chars", ex); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EvenTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EvenTag.java new file mode 100644 index 000000000..b07b30a55 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/EvenTag.java @@ -0,0 +1,45 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

Tag handler for <odd> + * + * @author Pierre Delisle + */ +public class EvenTag extends TagSupport { + + //********************************************************************* + // TagSupport methods + + public int doStartTag() throws JspException { + LoopTag iteratorTag = (LoopTag) findAncestorWithClass( + this, LoopTag.class); + if (iteratorTag == null) { + throw new JspTagException(" must be nested within a LoopTag"); + } + + int count = iteratorTag.getLoopStatus().getCount(); + return (count % 2 == 0) ? EVAL_BODY_INCLUDE : SKIP_BODY; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/FileTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/FileTag.java new file mode 100644 index 000000000..4106c5e13 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/FileTag.java @@ -0,0 +1,121 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

Tag handler for <file> + * + * @author Pierre Delisle + */ +public class FileTag extends TagSupport { + + //********************************************************************* + // Instance variables + + private String id; + private String file; + + private Reader reader; + + //********************************************************************* + // Constructors + + public FileTag() { + super(); + init(); + } + + private void init() { + id = null; + file = null; + } + + //********************************************************************* + // Tag's properties + + /** + * Tag's 'id' attribute + */ + public void setId(String id) { + this.id = id; + } + + /** + * Tag's 'file' attribute + */ + public void setfile(String file) { + this.file = file; + } + + //********************************************************************* + // TagSupport methods + + public int doStartTag() throws JspException { + reader = getReaderFromFile(file); + exposeVariable(reader); + return EVAL_BODY_INCLUDE; + } + + public int doEndTag() throws JspException { + try { + reader.close(); + } catch (IOException ex) { + } + reader = null; + return EVAL_PAGE; + } + + /** + * Releases any files we may have (or inherit) + */ + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // Tag's specific behavior methods + + public Reader getReaderFromFile(String name) throws JspException { + InputStream in = pageContext.getServletContext(). + getResourceAsStream(name); + if (in == null) { + throw new JspException("Could not access " + name); + } + + return new InputStreamReader(in); + } + + + //********************************************************************* + // Utility methods + + private void exposeVariable(Reader reader) { + if (id != null) { + pageContext.setAttribute(id, reader); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/Functions.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/Functions.java new file mode 100644 index 000000000..dd5b923a6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/Functions.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 org.apache.taglibs.standard.examples.taglib; + +import java.lang.reflect.Array; + +import jakarta.servlet.jsp.JspTagException; + +/** + *

Exmaples taglib Functions

+ * + * @author Pierre Delisle + */ + +public class Functions { + + /** + * Display the collection types supported by c:forEach. + */ + public static String display(Object obj) throws JspTagException { + if (obj == null) { + return ""; + } + if (obj instanceof String) { + return obj.toString(); + } + /* + if (obj instanceof Collection) { + return "FIXME"; + } + if (obj instanceof Map) { + return "FIXME"; + } + if (obj instanceof Iterator) { + Iterator iter = (Iterator)obj; + while (iter.hasNext()) { + iter.next(); + } + return "FIXME"; + } + if (obj instanceof Enumeration) { + Enumeration enum_ = (Enumeration)obj; + while (enum_.hasMoreElements()) { + enum_.nextElement(); + } + return "FIXME"; + } + */ + try { + StringBuilder buf = new StringBuilder(); + int count = Array.getLength(obj); + for (int i = 0; i < count; i++) { + buf.append(Array.get(obj, i).toString()); + if (i < count - 1) { + buf.append(""); + } + } + return buf.toString(); + } catch (IllegalArgumentException ex) { + } + throw new JspTagException("Bad Item"); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/LocalesTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/LocalesTag.java new file mode 100644 index 000000000..74ac2be37 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/LocalesTag.java @@ -0,0 +1,63 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import java.util.Locale; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.jstl.core.LoopTagSupport; + +/** + *

Tag handler for <locales> + * + * @author Felipe Leme + */ +public class LocalesTag extends LoopTagSupport { + + private static final Locale[] locales = Locale.getAvailableLocales(); + private int pointer; + private String varTotal; + + public void setVarTotal(String value) { + varTotal = value; + } + + public void prepare() { + pointer = 0; + if (varTotal != null && varTotal.length() > 0) { + pageContext.setAttribute(varTotal, new Integer(locales.length)); + } + + } + + public boolean hasNext() { + return pointer < locales.length; + } + + public Object next() { + return locales[pointer++]; + } + + public void setBegin(int value) { + super.begin = value; + } + + public void setEnd(int value) { + super.end = value; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/NullAttributeException.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/NullAttributeException.java new file mode 100644 index 000000000..779736c92 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/NullAttributeException.java @@ -0,0 +1,43 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import jakarta.servlet.jsp.JspTagException; + +/** + *

NullAttributeException is a JspTagException that will be thrown + * by the JSTL RI handlers when a tag attribute illegally evaluates + * to 'null'.

+ * + * @author Shawn Bayern + */ + +public class NullAttributeException extends JspTagException { + + /** + * Constructs a ExpressionException with appropriate information. + * + * @param tag The name of the tag in which the error occurred. + * @param att The attribute value for which the error occurred. + */ + public NullAttributeException(String tag, String att) { + super("The '" + att + "' attribute illegally evaluated to 'null' " + + "in <" + tag + ">."); + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/OddTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/OddTag.java new file mode 100644 index 000000000..62fb401c3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/OddTag.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.LoopTag; +import jakarta.servlet.jsp.tagext.TagSupport; + +/** + *

Tag handler for <odd> + * + * @author Pierre Delisle + */ +public class OddTag extends TagSupport { + + //********************************************************************* + // TagSupport methods + + public int doStartTag() throws JspException { + LoopTag iteratorTag = (LoopTag) findAncestorWithClass( + this, LoopTag.class); + if (iteratorTag == null) { + throw new JspTagException(" must be nested within a LoopTag"); + } + + int count = iteratorTag.getLoopStatus().getCount(); +// System.out.println("count: " + count); +// System.out.println("count odd/even: " + (count % 2)); + return (count % 2 == 1) ? EVAL_BODY_INCLUDE : SKIP_BODY; + } +} + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/ResourceTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/ResourceTag.java new file mode 100644 index 000000000..5dd8ef6b4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/ResourceTag.java @@ -0,0 +1,140 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletResponseWrapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.tagext.TagSupport; + +import org.apache.taglibs.standard.examples.util.IOBean; +import org.apache.taglibs.standard.examples.util.ServletResponseWrapperForWriter; + +/** + *

Tag handler for <resource> + * + * @author Pierre Delisle + */ +public class ResourceTag extends TagSupport { + + //********************************************************************* + // Instance variables + + private String id; + private String resource; + + private Reader reader; + + //********************************************************************* + // Constructors + + public ResourceTag() { + super(); + init(); + } + + private void init() { + id = null; + resource = null; + } + + //********************************************************************* + // Tag's properties + + /** + * Tag's 'id' attribute + */ + public void setId(String id) { + this.id = id; + } + + /** + * Tag's 'resource' attribute + */ + public void setResource(String resource) { + this.resource = resource; + } + + //********************************************************************* + // TagSupport methods + + public int doStartTag() throws JspException { + reader = getReaderFromResource(resource); + exposeVariable(reader); + return EVAL_BODY_INCLUDE; + } + + public int doEndTag() throws JspException { + try { + reader.close(); + } catch (IOException ex) { + } + reader = null; + return EVAL_PAGE; + } + + /** + * Releases any resources we may have (or inherit) + */ + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // Tag's scific behavior methods + + private Reader getReaderFromResource(String name) throws JspException { + HttpServletRequest request = + (HttpServletRequest) pageContext.getRequest(); + HttpServletResponse response = + (HttpServletResponse) pageContext.getResponse(); + RequestDispatcher rd = null; + + // The response of the local URL becomes the reader that + // we export. Need temporary storage. + IOBean ioBean = new IOBean(); + Writer writer = ioBean.getWriter(); + ServletResponseWrapper responseWrapper = + new ServletResponseWrapperForWriter( + response, new PrintWriter(writer)); + rd = pageContext.getServletContext().getRequestDispatcher(name); + try { + rd.include(request, responseWrapper); + return ioBean.getReader(); + } catch (Exception ex) { + throw new JspException(ex); + } + } + + //********************************************************************* + // Utility methods + + private void exposeVariable(Reader reader) { + if (id != null) { + pageContext.setAttribute(id, reader); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/UsCustomerTag.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/UsCustomerTag.java new file mode 100644 index 000000000..5b4a54a3a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/taglib/UsCustomerTag.java @@ -0,0 +1,97 @@ +/* + * 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.taglibs.standard.examples.taglib; + +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.jstl.core.ConditionalTagSupport; + +import org.apache.taglibs.standard.examples.beans.Customer; + +/** + *

Tag handler for <usCustomer> + * + * @author Pierre Delisle + */ +public class UsCustomerTag extends ConditionalTagSupport { + + //********************************************************************* + // Instance Variables + + /** + * Holds value of property customer. + */ + private Customer customer; + + //********************************************************************* + // Constructor and lusCustomerecycle management + + public UsCustomerTag() { + super(); + init(); + } + + private void init() { + customer = null; + } + + //********************************************************************* + // TagSupport methods + + public void release() { + super.release(); + init(); + } + + //********************************************************************* + // ConditionalTagSupport methods + + protected boolean condition() throws JspTagException { + try { + if (customer == null) { + throw new NullAttributeException("usCustomer", "test"); + } else { + //System.out.println("country: " + customer.getAddress().getCountry()); + return (customer.getAddress().getCountry().equalsIgnoreCase("USA")); + } + } catch (JspException ex) { + throw new JspTagException(ex.toString()); + } + } + + //********************************************************************* + // Accessors + + /** + * Getter for property customer. + * + * @return Value of property customer. + */ + public Customer getCustomer() { + return customer; + } + + /** + * Setter for property customer. + * + * @param customer New value of property customer. + */ + public void setCustomer(Customer customer) { + this.customer = customer; + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/IOBean.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/IOBean.java new file mode 100644 index 000000000..a1a08d808 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/IOBean.java @@ -0,0 +1,63 @@ +/* + * 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.taglibs.standard.examples.util; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import jakarta.servlet.jsp.JspException; + +/** + *

String repository for Reader/Writer. + * + * @author Pierre Delisle + */ +public class IOBean { + StringWriter stringWriter = null; + String content = null; + + public Reader getReader() throws JspException { + //p("getReader()"); + if (content == null) { + if (stringWriter == null) { + throw new JspException( + "content must first be added to the bean via the writer"); + } + content = stringWriter.toString(); + } + return new StringReader(content); + } + + public Writer getWriter() { + //p("getWriter()"); + content = null; + stringWriter = new StringWriter(); + return stringWriter; + } + + public void release() { + stringWriter = null; + content = null; + } + + private void p(String s) { + System.out.println("[IOBean] " + s); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/ServletResponseWrapperForWriter.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/ServletResponseWrapperForWriter.java new file mode 100644 index 000000000..315c0d87f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/ServletResponseWrapperForWriter.java @@ -0,0 +1,57 @@ +/* + * 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.taglibs.standard.examples.util; + +import java.io.PrintWriter; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; + +/** + * ServletResponseWrapper used for the the generation of + * semi-dynamic pages. + *

This 'wrapped' response object is passed as the second argument + * to the internal RequestDispatcher.include(). It channels + * all output text into the PrintWriter specified in the + * constructor (which is associated with the file where the + * output of the JSP page has to be saved). + * + * @author Pierre Delisle + */ +public class ServletResponseWrapperForWriter + extends HttpServletResponseWrapper { + /** + * The writer that will get all the output of the response. + */ + PrintWriter writer; + + public ServletResponseWrapperForWriter(ServletResponse response, + PrintWriter writer) { + super((HttpServletResponse) response); + this.writer = writer; + } + + /** + * Returns the Writer associated with the response. + */ + public java.io.PrintWriter getWriter() + throws java.io.IOException { + return writer; + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/Util.java b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/Util.java new file mode 100644 index 000000000..d11ccdb3d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/java/org/apache/taglibs/standard/examples/util/Util.java @@ -0,0 +1,63 @@ +/* + * 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.taglibs.standard.examples.util; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; + +import jakarta.servlet.jsp.JspException; + +/** + *

Utility class for examples webapp. + * + * @author Pierre Delisle + */ +public class Util { + + public static Writer castToWriter(Object obj) throws JspException { + if (obj instanceof OutputStream) { + return new OutputStreamWriter((OutputStream) obj); + } else if (obj instanceof Writer) { + return (Writer) obj; + /*@@@ + } else if (obj instanceof String) { + return new StringWriter(); + */ + } + throw new JspException("Invalid type '" + obj.getClass().getName() + + "' for castToWriter()"); + } + + public static Reader castToReader(Object obj) throws JspException { + if (obj instanceof InputStream) { + return new InputStreamReader((InputStream) obj); + } else if (obj instanceof Reader) { + return (Reader) obj; + } else if (obj instanceof String) { + return new StringReader((String) obj); + } + throw new JspException("Invalid type '" + obj.getClass().getName() + + "' for castToReader()"); + } +} + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/ShowSource.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/ShowSource.jsp new file mode 100644 index 000000000..92fdfb7bc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/ShowSource.jsp @@ -0,0 +1,36 @@ + + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + +<%-- + Let's get back the URL as a String so we can use it to + demonstrate "c:import" +--%> +<% pageContext.setAttribute("filepath", + application. + getResource(request.getParameter("filename")).toExternalForm()); %> +<% pageContext.setAttribute("filename", request.getParameter("filename")); %> + + + + JSTL: Source code for <c:out value="${filename}"/> + + +

Source code for:  ${filename}

+ +
+ + + + +
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/Templates/ExamplesTemplate.dwt b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/Templates/ExamplesTemplate.dwt new file mode 100644 index 000000000..200becce7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/Templates/ExamplesTemplate.dwt @@ -0,0 +1,38 @@ + + + +Untitled Document + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
Examples     Introduction + • General PurposeConditionals + • IteratorsImport + • I18N & FormattingXML + • SQLFunctions + • TLVMisc.
+{body} +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/tlds/jstl-examples.tld b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/tlds/jstl-examples.tld new file mode 100644 index 000000000..91fdfa29f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/tlds/jstl-examples.tld @@ -0,0 +1,165 @@ + + + + + Tag Library to support examples webapp + + 1.1 + ex + /jstl-examples-taglib + + + defaultLocale + org.apache.taglibs.standard.examples.taglib.DefaultLocaleTag + JSP + + + + locales + org.apache.taglibs.standard.examples.taglib.LocalesTag + JSP + + var + true + false + + + varStatus + false + false + + + varTotal + false + false + + + begin + false + true + + + end + false + true + + + + + escapeHtml + org.apache.taglibs.standard.examples.taglib.EscapeHtmlTag + JSP + + reader + false + true + + + writer + false + true + + + + + resource + org.apache.taglibs.standard.examples.taglib.ResourceTag + JSP + + id + true + false + + + resource + true + false + + + + + file + org.apache.taglibs.standard.examples.taglib.FileTag + JSP + + id + true + false + + + file + true + true + + + + + odd + org.apache.taglibs.standard.examples.taglib.OddTag + JSP + + + + even + org.apache.taglibs.standard.examples.taglib.EvenTag + JSP + + + + usCustomer + org.apache.taglibs.standard.examples.taglib.UsCustomerTag + JSP + + customer + true + true + + + var + false + false + + + + + customerFmt + org.apache.taglibs.standard.examples.taglib.CustomerFmtTag + empty + + customer + true + true + + + fmt + true + true + + + + + SPath + org.apache.taglibs.standard.extra.spath.SPathTag + empty + + var + true + false + + + select + true + false + + + + + display + org.apache.taglibs.standard.examples.taglib.Functions + java.lang.String display(java.lang.Object) + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/web.xml b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..fa6429ac9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + + JSTL Examples + + Examples for the 'standard' taglib (JSTL) + + + + org.apache.taglibs.standard.examples.startup.Init + + + + index.jsp + index.html + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/Choose.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/Choose.jsp new file mode 100644 index 000000000..2985343a0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/Choose.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Conditional Support -- Mutually Exclusive Conditional Execution Example + + +

Mutually Exclusive Conditional Execution

+ +

USA:blue Canada:red Others:green

+ + + + + + + + + + + + + + ${customer}
+
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/CustomLogicTag.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/CustomLogicTag.jsp new file mode 100644 index 000000000..96e9f5184 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/CustomLogicTag.jsp @@ -0,0 +1,36 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL: Conditional Support -- Custom Logic Tag Example + + + +

Custom Logic Tag

+ +

Customers living in the USA

+ +

Simple Conditional Execution

+ + +
+
+
+ +

Mutually Exclusive Conditional Execution

+ + + + + + + + + + + +
+
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/FailureLocal.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/FailureLocal.jsp new file mode 100644 index 000000000..60bd73383 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/FailureLocal.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Conditional Support -- Mutually Exclusive Conditional Execution Example + + +

Mutually Exclusive Conditional Execution

+ +

USA:blue Canada:red Others:green

+ + + + + + + + + + + + + +
+
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/If.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/If.jsp new file mode 100644 index 000000000..f10b5d9e2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/If.jsp @@ -0,0 +1,19 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Conditional Support -- Simple Conditional Execution Example + + + +

Simple Conditional Execution

+ +

Customers living in the USA

+ + + + ${customer}
+
+
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/index.html new file mode 100644 index 000000000..156c8d96b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/conditionals/index.html @@ -0,0 +1,66 @@ + + + + JSTL: Conditional Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Conditional Tags Examples

+ +

<if> Simple Conditional Execution   + +

+Only shows a customer from the customer list if they are living in the "USA".
+ +

<choose> Mutually Exclusive Conditional Execution  + +

+ +

Customers from the USA will be printed in blue, those from Canada in red, and + others in green.

+ +

Custom Logic Tag   

+ +

JSTL exposes in its API the abstract class ConditionalTagSupport to facilitate + the implementation of custom conditional tags that leverage the standard conditional + behavior defined in JSTL. This example shows custom tag <usCustomer> that + returns true if its customer attribute value points to a US customer. It can + be used both in the context of a simple conditional execution, as well as in + the context of a mutually conditional execution by exposing the result of the + conditional execution in a JSP page attribute via the tag attribute 'var'.

+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Out.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Out.jsp new file mode 100644 index 000000000..866e7007a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Out.jsp @@ -0,0 +1,34 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + JSTL: Expression Language Support -- Expr Example + + + +

<c:out>

+ + + + + + + + + +
+ + no cell phone specified + +
+ +

<c:out> with Reader object

+<% + java.io.Reader reader1 = new java.io.StringReader("Text for a Reader!"); + pageContext.setAttribute("myReader1", reader1); + java.io.Reader reader2 = new java.io.StringReader("Text for a Reader!"); + pageContext.setAttribute("myReader2", reader2); +%> +Reader1 (escapeXml=true) :
+Reader2 (escapeXml=false):
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set.jsp new file mode 100644 index 000000000..cbfd706d5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set.jsp @@ -0,0 +1,34 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Expression Language Support -- Set Example + + +

<c:set>

+ +

Setting application scope attribute "customerTable"

+ + + + + + + + + + +
${customer.lastName} + + no address specified + +
+
+ +

+ Using customerTable in another JSP page + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set2.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set2.jsp new file mode 100644 index 000000000..552291ccf --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/Set2.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + JSTL: Expression Language Support -- Set 2 Example + + + +

<c:set>

+ +

Using "customerTable" application scope attribute defined in Set.jsp a first time

+ + +

Using "customerTable" application scope attribute defined in Set.jsp a second time

+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/index.html new file mode 100644 index 000000000..a0cadb64a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/elsupport/index.html @@ -0,0 +1,64 @@ + + + + JSTL: General-Purpose Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

General-Purpose Tags Examples

+ +

<out>   + +

+This example features <out> used with default values using the default attribute +as well as the tag's body content.
+ +

<set>   +

+ +

We set the value of an application scope attribute from the <set> tag + body content. This application scope variable is then used in a second JSP page.

+ + +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/Demo.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/Demo.jsp new file mode 100644 index 000000000..a8763a7f9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/Demo.jsp @@ -0,0 +1,124 @@ +<%@ page import="java.util.Enumeration, java.util.Locale" %> +<%@ page import="javax.servlet.jsp.jstl.core.Config" %> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Demo Example + + + +

Demo

+ +

+ The following bundles exist in the web application: 'Resources', 'Resources_de', 'Resources_fr', 'Resources_it'. + 'Resources' is the 'base' bundle and contains all messages in English. The italian bundle only holds one message + (key=greetingMorning). +

+ + + + + + <% Config.set(request, Config.FMT_FALLBACK_LOCALE, request.getParameter("fallback")); %> + + + + + + + + + + +
Set application-based locale: + French • + German • + Italian • + Spanish (no bundle) • + None +
Set fallback locale: + French • + German • + Italian • + Spanish (no bundle) • + None +
+

+ + Request parameter "locale":
+ (This value is used to set the application based locale for this example) + +

+ + Application based locale: <%=Config.find(pageContext, Config.FMT_LOCALE)%>
+ (javax.servlet.jsp.jstl.fmt.locale configuration setting) + +

+ + Browser-Based locales: + <% + Enumeration enum_ = request.getLocales(); + while (enum_.hasMoreElements()) { + Locale locale = (Locale)enum_.nextElement(); + out.print(locale); + out.print(" "); + } +%> +
+ (ServletRequest.getLocales() on the incoming request) + +

+ + Fallback locale: <%=Config.find(pageContext, Config.FMT_FALLBACK_LOCALE)%>
+ (javax.servlet.jsp.jstl.fmt.fallbackLocale configuration setting) + +

+ + +

+ • + +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
KEYVALUE
greetingMorning
greetingEvening
currentTime + + + +
serverInfo
undefinedKey
+
+ +

+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTime.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTime.jsp new file mode 100644 index 000000000..f1ea9acff --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTime.jsp @@ -0,0 +1,75 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Date and Time Example + + +

Formatting dates and times using en-US locale

+ + + + +
    +
  • Formatting current date as "GMT":
    + + + + +
  • Formatting current date as "GMT+1:00", and parsing + its date and time components:
    + + + + Parsed date:
    + Parsed time: + +
    + +
  • Parsing SHORT version of current time in different time zones:
    + + + (parsed in "GMT")
    + + + (parsed in "GMT+1:00")
    + + + (parsed in "GMT+3:00")
    + + + (parsed in "PST") + +
  • Parsing FULL version of current time in different time zones
    + (parse result is independent of specified time zone):
    + + + (parsed in "GMT")
    + + + (parsed in "GMT+1:00")
    + + + (parsed in "GMT+3:00")
    + + + (parsed in "PST") +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTimeBrowserLocale.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTimeBrowserLocale.jsp new file mode 100644 index 000000000..33817e14a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatDateTimeBrowserLocale.jsp @@ -0,0 +1,74 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Date and Time Example + + +

Formatting dates and times using browser-based locale

+ + + +
    +
  • Formatting current date as "GMT":
    + + + + +
  • Formatting current date as "GMT+1:00", and parsing + its date and time components:
    + + + + Parsed date:
    + Parsed time: + +
    + +
  • Parsing SHORT version of current time in different time zones:
    + + + (parsed in "GMT")
    + + + (parsed in "GMT+1:00")
    + + + (parsed in "GMT+3:00")
    + + + (parsed in "PST") + +
  • Parsing FULL version of current time in different time zones
    + (parse result is independent of specified time zone):
    + + + (parsed in "GMT")
    + + + (parsed in "GMT+1:00")
    + + + (parsed in "GMT+3:00")
    + + + (parsed in "PST") +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumber.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumber.jsp new file mode 100644 index 000000000..fae2a5b73 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumber.jsp @@ -0,0 +1,41 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Number, Currency, and Percent + Example + + + +

Formatting numbers, currencies, and percentages using en-US + locale +

+ + + +
    +
  • Format "123456789" as number:
    + + +
  • Format "123456789" as percent:
    + 123456789 + +
  • Format "12345.67" as currency:
    + + +
  • Format "12345.67" as currency, with + grouping turned off, the maximum number of digits in the integer portion + limited to 4, and no fraction portion:
    + + +
  • Format "12345.67" as currency:
    +
    + then parse its integer portion only and output the result:
    + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumberBrowserLocale.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumberBrowserLocale.jsp new file mode 100644 index 000000000..3325ea83b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/FormatNumberBrowserLocale.jsp @@ -0,0 +1,52 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Number, Currency, and Percent + Example + + + +

Formatting numbers, currencies, and percentages using browser-based + locale +

+ + +
    +
  • Format "123456789" as number:
    + + +
  • Format "123456789" as percent:
    + 123456789 + +
  • Format "12345.67" as currency:
    + + +
  • Format "12345.67" as currency, with + grouping turned off, the maximum number of digits in the integer portion + limited to 4, and no fraction portion:
    + + +
  • Format "12345.67" as currency:
    +
    + then parse its integer portion only and output the result:
    + + +
+
+ + + +
The following error has occurred:

+
+ +
This is due to a known bug in java.text.NumberFormat (Bugtraq bugid: 4709840). +
+
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanLocale.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanLocale.jsp new file mode 100644 index 000000000..47ff5f45c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanLocale.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- German Locale Example + + +

German Locale

+ + + + + greetingMorning + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautCorrect.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautCorrect.jsp new file mode 100644 index 000000000..58c998526 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautCorrect.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Request Encoding Example + + +

German Umlaut characters decoded correctly:

+ + + +
    +
  • a umlaut: + +
  • o umlaut: + +
  • u umlaut: + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautIncorrect.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautIncorrect.jsp new file mode 100644 index 000000000..686f6659b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/GermanUmlautIncorrect.jsp @@ -0,0 +1,21 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Request Encoding Example + + +

German Umlaut characters decoded incorrectly:

+ +
    +
  • a umlaut: + +
  • o umlaut: + +
  • u umlaut: + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ItalianLocale.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ItalianLocale.jsp new file mode 100644 index 000000000..c59c02fb8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ItalianLocale.jsp @@ -0,0 +1,15 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Italian Locale Example + + +

Italian Locale

+ + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/MissingResourceBundle.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/MissingResourceBundle.jsp new file mode 100644 index 000000000..b7e9f6439 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/MissingResourceBundle.jsp @@ -0,0 +1,22 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Missing Resource Bundle Example + + +

Missing Resource Bundle

+ +
    +
  • Implicit collaboration with <bundle> (via ancestry chain):
    + + + + +
  • Explicit collaboration with <bundle> (via var attribute):
    + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ParametricReplacement.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ParametricReplacement.jsp new file mode 100644 index 000000000..20feef998 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/ParametricReplacement.jsp @@ -0,0 +1,66 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Parametric Replacement Example + + +

Parametric Replacement

+ + + + + + + + + +
    +
  • Using single <param> with 'value' evaluating to String:
    + + + + +
  • Using single <param> with 'value' evaluating to java.util.Date:
    + + + + +
  • Using single <param> with body:
    + + + + + + +
  • Using multiple parameters:
    + + + + + +
+ +
    + + +
  • Locale set to Spanish yields a locale-less localization context. Formatting still done + using the preferred locale:
    + + + +
  • + + + +
  • Locale set to English yields a locale-less localization context. Formatting still done + using the preferred locale:
    + + + +
  • +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/PrefixAttribute.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/PrefixAttribute.jsp new file mode 100644 index 000000000..0d12fdb3b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/PrefixAttribute.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Prefix Attribute Example + + +

Prefix Attribute

+ + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/RequestEncoding.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/RequestEncoding.jsp new file mode 100644 index 000000000..fa1a463d2 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/RequestEncoding.jsp @@ -0,0 +1,20 @@ + + + JSTL: Formatting/I18N Support -- Request Encoding Example + + +This page contains two links, and sends German Umlaut characters as request +parameter values to each of the linked pages.
+Only one of the linked pages decodes and displays the request parameter values +correctly: + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/UndefinedKey.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/UndefinedKey.jsp new file mode 100644 index 000000000..8b182d7ec --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/UndefinedKey.jsp @@ -0,0 +1,15 @@ +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + JSTL: Formatting/I18N Support -- Undefined Key Example + + +

Undefined Key

+ + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/index.html new file mode 100644 index 000000000..bc7723f6f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/format/index.html @@ -0,0 +1,115 @@ + + + + JSTL: I18N-Capable Formatting Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

I18N-Capable Formatting Tags Examples

+ +

Demo +

+Overview demo where the locale to be applied to the page may be changed dynamically.
+ +

German   + +

+Using resource bundle for German locale.
+ +

Italian   + +

+Using resource bundle for Italian locale.
+ +

Missing Resource Bundle   + +

+Trying to access a resource bundle that does not exist.
+ +

Undefined Key   + +

+Looking up an undefined key in a resource bundle.
+ +

Parametric Replacement   + +

+Parametric replacement examples.
+ +

Prefix   + +

+Prepending prefix to message key.
+ +

Date   + +

+Formatting dates and times using en-US locale.
+ +

Date   + +

+Formatting dates and times using browser-based locale.
+ +

Number   + +

+Formatting numbers using en-US locale.
+ +

Number   + +

+Formatting numbers using browser-based locale.
+ +

Request Parameter Decoding   + +

+Decoding and displaying request parameters using the appropriate charset.
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/EscapeXml.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/EscapeXml.jsp new file mode 100644 index 000000000..8c85fb9ec --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/EscapeXml.jsp @@ -0,0 +1,41 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • Escape Xml + + + +

Escape XML

+ + + +

fn:escapeXml

+ + + + + + + + + + + + + + + + + + + + + +
Input StringResult
${s1}${fn:escapeXml(s1)}
+ body of foo + ${fn:escapeXml("body of foo")}
null ${fn:escapeXml(undefined)}
empty string ${fn:escapeXml("")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Length.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Length.jsp new file mode 100644 index 000000000..1c21788b7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Length.jsp @@ -0,0 +1,37 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • Length + + + + + +

fn:length

+ + + + + + + + + + + + + + + + + + + + + +
Input StringResult
${s1}${fn:length(s1)}
${customers}${fn:length(customers)}
null${fn:length(undefined)}
empty string${fn:length("")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Replace.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Replace.jsp new file mode 100644 index 000000000..ea6e160fc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Replace.jsp @@ -0,0 +1,55 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • Replace + + + +

Replace

+ + + +

fn:replace

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstring BeforeSubstring AfterResult
${s1}e*${fn:replace(s1, "e", "*")}
${s2}-${fn:replace(s2, "-", "•")}
${s2}twoempty${fn:replace(s2, "two", "")}
${s2}empty stringone${fn:replace(s2, "", "one")}
nullonetwo ${fn:replace(undefined, "one", "two")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SplitJoin.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SplitJoin.jsp new file mode 100644 index 000000000..0e1810c07 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SplitJoin.jsp @@ -0,0 +1,87 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL Functions • Split/Join + + + +

Split/Join

+ + + + + +

fn:split

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringDelimitersResult
${s1}empty string${ex:display(fn:split(s1, ""))}
${s3}|${ex:display(fn:split(s3, "|"))}
${s3}+${ex:display(fn:split(s3, "+"))}
${s5}|+${ex:display(fn:split(s5, "|+"))}
empty stringempty string ${ex:display(fn:split("", ""))}
+ + +

fn:join

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input ArraySeparatorResult
${ex:display(a1)} +${fn:join(a1, " + ")}
${ex:display(a1)}<sep>${fn:join(a1, " <sep> ")}
${ex:display(a1)}empty string${fn:join(a1, "")}
${ex:display(a1)}null${fn:join(a1, null)}
nullempty string ${fn:join(null, "")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringCapitalization.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringCapitalization.jsp new file mode 100644 index 000000000..77a7f978a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringCapitalization.jsp @@ -0,0 +1,55 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • String Capitalization + + + +

String Capitalization

+ + + +

fn:toLowerCase

+ + + + + + + + + + + + + + + + + +
Input StringResult
${s1}${fn:toLowerCase(s1)}
null ${fn:toLowerCase(undefined)}
empty ${fn:toLowerCase("")}
+ +

fn:toUpperCase

+ + + + + + + + + + + + + + + + + +
Input StringResult
${s1}${fn:toUpperCase(s1)}
null ${fn:toUpperCase(undefined)}
empty ${fn:toUpperCase("")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringSubset.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringSubset.jsp new file mode 100644 index 000000000..1cf59091b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/StringSubset.jsp @@ -0,0 +1,183 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • String Subset + + + +

String Subset

+ + + + +

fn:substring

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringbeginIndexendIndexResult
${zip}6-1P.O. Box: ${fn:substring(zip, 6, -1)}
${s1}1117${fn:substring(s1, 11, 17)}
${s1}125 ${fn:substring(s1, 12, 5)}
${s1}23-1${fn:substring(s1, 23, -1)}
${s1}23999${fn:substring(s1, 23, 999)}
${s1}-1-1${fn:substring(s1, -1, -1)}
${s1}9912 ${fn:substring(s1, 99, 12)}
empty string26 ${fn:substring("", 2, 6)}
null26 ${fn:substring(undefined, 2, 6)}
+ +

fn:substringAfter

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringsubstringResult
${zip}-P.O. Box: ${fn:substringAfter(zip, "-")}
${s1}There${fn:substringAfter(s1, "There")}
${s1}on a${fn:substringAfter(s1, "on a")}
${s1}not found ${fn:substringAfter(s1, "not found")}
${s1}null${fn:substringAfter(s1, undefined)}
${s1}empty string${fn:substringAfter(s1, "")}
empty stringcastle ${fn:substringAfter("", "castle")}
nullcastle ${fn:substringAfter(undefined, "castle")}
nullempty string ${fn:substringAfter(undefined, "")}
+ +

fn:substringBefore

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringsubstringResult
${zip}-Zip without P.O. Box: ${fn:substringBefore(zip, "-")}
${s1}on a${fn:substringBefore(s1, "on a")}
${s1}castle${fn:substringBefore(s1, "castle")}
${s1}null ${fn:substringBefore(s1, undefined)}
${s1}empty string ${fn:substringBefore(s1, "")}
empty stringcastle ${fn:substringBefore("", "castle")}
nullcastle ${fn:substringBefore(undefined, "castle")}
nullempty string ${fn:substringBefore(undefined, "")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SubstringContained.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SubstringContained.jsp new file mode 100644 index 000000000..b8a7c80e7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/SubstringContained.jsp @@ -0,0 +1,227 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • Substring Contained in String + + + +

Substring Contained in String

+ + + +

fn:contains

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstringResult
${s1}castle${fn:contains(s1, "castle")}
${s1}CASTLE${fn:contains(s1, "CASTLE")}
${s1}null${fn:contains(s1, undefined)}
${s1}empty string${fn:contains(s1, "")}
nullcastle${fn:contains(undefined, "castle")}
nullempty string${fn:contains(undefined, "")}
+ +

fn:containsIgnoreCase

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstringResult
${s1}castle${fn:containsIgnoreCase(s1, "castle")}
${s1}CASTLE${fn:containsIgnoreCase(s1, "CASTLE")}
${s1}CaStLe${fn:containsIgnoreCase(s1, "CaStLe")}
${s1}null${fn:containsIgnoreCase(s1, undefined)}
${s1}empty string${fn:containsIgnoreCase(s1, "")}
nullcastle${fn:containsIgnoreCase(undefined, "castle")}
nullempty string${fn:containsIgnoreCase(undefined, "")}
+ +

fn:startsWith

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstringResult
${s1}castle${fn:startsWith(s1, "castle")}
${s1}There is${fn:startsWith(s1, "There is")}
${s1}null${fn:startsWith(s1, undefined)}
${s1}empty string${fn:startsWith(s1, "")}
nullcastle${fn:startsWith(undefined, "castle")}
nullempty string${fn:startsWith(undefined, "")}
+ +

fn:endsWith

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstringResult
${s1}castle${fn:endsWith(s1, "castle")}
${s1}cloud${fn:endsWith(s1, "cloud")}
${s1}null${fn:endsWith(s1, undefined)}
${s1}empty string${fn:endsWith(s1, "")}
nullcastle${fn:endsWith(undefined, "castle")}
nullempty string${fn:endsWith(undefined, "")}
+ +

fn:indexOf

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringSubstringResult
${s1}castle${fn:indexOf(s1, "castle")}
${s1}cloud${fn:indexOf(s1, "cloud")}
${s1}null${fn:indexOf(s1, undefined)}
${s1}empty string${fn:indexOf(s1, "")}
nullcastle${fn:indexOf(undefined, "castle")}
nullempty string${fn:indexOf(undefined, "")}
Display text in between brackets
${text}'(' and ')'${fn:substring(text, fn:indexOf(text, '(')+1, fn:indexOf(text, ')'))}
+ +

+ + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Trim.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Trim.jsp new file mode 100644 index 000000000..e06dbf315 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/Trim.jsp @@ -0,0 +1,56 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + JSTL Functions • Trim + + + +

Trim

+ + + + +

fn:trim

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input StringResult
+
${custId} (without trim)
+
+
${custId} (with trim)
+
${s1}${fn:trim(s1)}
+
    3 spaces before and after   
+
+
${fn:trim("    3 spaces before and after   ")}
+
null ${fn:trim(undefined)}
empty string ${fn:trim("")}
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/index.html new file mode 100644 index 000000000..da3d8f267 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/functions/index.html @@ -0,0 +1,95 @@ + + + + JSTL: Functions Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Functions Examples

+ +

Length of a Collection or a String   + +

+length
+ +

String Capitalization    + +

+toUpperCase toLowerCase
+ +

String Subset    + +

+substring substringAfter substringBefore
+ +

Trim    + +

+trim
+ +

Replace    + +

+replace
+ +

Substring Contained in String    + +

+contains containsIgnoreCase startsWith endsWith indexOf
+ +

Split/Join    + +

+split join
+ +

EscapeXml    + +

+escapeXml
+ + +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/global.css b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/global.css new file mode 100644 index 000000000..3c907cf93 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/global.css @@ -0,0 +1,15 @@ +body { + font-family: Arial, Helvetica, sans-serif +} + +h1 { + color: #000099 +} + +h2 { + color: #000099 +} + +h3 { + color: #000099 +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/code.gif b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/code.gif new file mode 100644 index 000000000..93af2cd13 Binary files /dev/null and b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/code.gif differ diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/execute.gif b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/execute.gif new file mode 100644 index 000000000..f64d70fd2 Binary files /dev/null and b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/execute.gif differ diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/return.gif b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/return.gif new file mode 100644 index 000000000..af4f68f4a Binary files /dev/null and b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/images/return.gif differ diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Absolute.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Absolute.jsp new file mode 100644 index 000000000..a846c598b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Absolute.jsp @@ -0,0 +1,19 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL: I/O Support -- Absolute URL Example + + +

Absolute URL

+ +

CNN's RSS XML feed:

+
+ + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/AbsoluteFtp.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/AbsoluteFtp.jsp new file mode 100644 index 000000000..a366295fa --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/AbsoluteFtp.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- Absolute URL Example (non-HTTP) + + +

Absolute URL (non-HTTP)

+ +

Free Software Foundation's FTP site:

+
+
+  
+ 
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ContextRelative.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ContextRelative.jsp new file mode 100644 index 000000000..db342a958 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ContextRelative.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- Context-relative URL example + + +Assuming you have the "examples" webapp installed, here's a file from it... + +URL:
+Name: + +
+
+  
+ 
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Encode.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Encode.jsp new file mode 100644 index 000000000..3e84393da --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Encode.jsp @@ -0,0 +1,47 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- URL Encoding Example + + +

URL Encoding

+ +

<c:url>

+ +Disable cookies in your browser to see URL rewriting. + + + + + + + + + + + + + + + + + + + + + + + + + + +
"base", param=ABC
"base", param=123
"base", param=&
"base", param="JSTL is fun"
"base", param="ü@foo-bar"
"base", météo="légère pluie @ Saint-Denis-de-la-Réunion"
+ +

+ Compose the url, then use it in an HTML anchor tag: + + + + + Link back to this page () \ No newline at end of file diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/EncodeContextRelative.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/EncodeContextRelative.jsp new file mode 100644 index 000000000..4737915cc --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/EncodeContextRelative.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- URL Encoding Example + + +

URL Encoding

+ +

<urlEncode>

+ + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeString.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeString.jsp new file mode 100644 index 000000000..69968703f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeString.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- String exposure + + +

String exposure

+ + + +

CNN's RSS XML feed:

+
+
+  
+ 
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeStringRelative.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeStringRelative.jsp new file mode 100644 index 000000000..aada929ec --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/ExposeStringRelative.jsp @@ -0,0 +1,17 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- String exposure for relative URL + + +

String exposure for relative URL

+ +

Escaped (raw HTML)

+ + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/LocalSample.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/LocalSample.jsp new file mode 100644 index 000000000..9eb6de551 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/LocalSample.jsp @@ -0,0 +1,14 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- Simple static example to be included + in other pages + + +

Local example target page

+ +

• This output comes from LocalSample.jsp •

+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Param.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Param.jsp new file mode 100644 index 000000000..9ab6cb526 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Param.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<%-- + -- These URLs likely don't exist, but the error that gets reported + -- back should help you see how modifies the URL. + -- + --%> + + + + + <%-- encoded --%> + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Relative.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Relative.jsp new file mode 100644 index 000000000..a46e57938 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/Relative.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- Relative URL Example + + +

Relative URL

+ +

Import from current directory:

+
+
+  
+ 
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/StartSlash.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/StartSlash.jsp new file mode 100644 index 000000000..f7932c138 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/StartSlash.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: I/O Support -- Malformed URL example + + + +
+
+  
+ 
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.html new file mode 100644 index 000000000..ca2dec16f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.html @@ -0,0 +1,124 @@ + + + + JSTL: Import Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Import Tags Examples

+ +

If you are using a Proxy server, you will need to set the following System + Properties when starting the VM:

+
+    http.proxyHost
+    http.proxyPort
+    ftp.proxyHost
+    ftp.proxyPort
+
+
+ +

Absolute   + +

+Using an Absolute URL to import a resource.
+ +

Relative   + +

+Using a Relative URL to import a resource.
+ +

Context Relative   + +

+Importing a resource relative to a foreign context.
+ +

Absolute (FTP)   + +

+Using an Absolute URL to import a resource using a different protocol other than +HTTP.
+ +

Encode   + +

+URL encoding examples.
+ +

Encode Context Relative   + +

+URL encoding examples using a relative context and nested param tags.
+ +

Encode Query String   + +

+URL encoding examples using a relative context and query string.
+ +

String Exposure Absolute   + +

+Exposing the content of the resource as a String Object.
+ +

String Exposure Relative   + +

+Exposing the content of a relative URL's resource as a String Object.
+ +

Param   + +

+Using + +element to specify request parameters. Also demonstrating how request +parameters can be URL encoded (default). (NOTE: Returns error page by default.) +
+ +

Malformed URL   + +

+A relative URL must start with a "/" in a foreign context. (NOTE: This example +will result in a ServletException describing the error condition).
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.jsp new file mode 100644 index 000000000..77085ed3f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/index.jsp @@ -0,0 +1,99 @@ + + + + JSTL: Import Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLVMisc.
+ +<%@ include file="links.html" %> +

Context Relative Examples

+ +

For the context relative examples you will need to supply an available relative + context name and url before executing the tags.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Context + +
Url + +
Param name: + + Param value: + +
Param name: + + Param value: + +
Param name: + + Param value: + +
+

+ +

+
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/links.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/links.html new file mode 100644 index 000000000..6c30a1e49 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/links.html @@ -0,0 +1,57 @@ +

Import Tags Examples

+

If you are using a Proxy server, you will need to set the following System + Properties when starting the VM:

+
+    http.proxyHost
+    http.proxyPort
+    ftp.proxyHost
+    ftp.proxyPort
+
+
+

Absolute   + +

+Using an Absolute URL to import a resource.
+

Relative   + +

+Using a Relative URL to import a resource.
+

Absolute (FTP)   + +

+Using an Absolute URL to import a resource using a different protocol other than +HTTP.
+

Encode   + +

+URL encoding examples.
+

String Exposure Absolute   + +

+Exposing the content of the resource as a String Object.
+

String Exposure Relative   + +

+Exposing the content of a relative URL's resource as a String Object.
+

Param   + +

+Using <param> element to specify request parameters. Also demonstrating how request +parameters can be URL encoded (default). (NOTE: Returns error page that shows +how request parameters are encoded)
+

Malformed URL   + +

+A relative URL must start with a "/" in a foreign context. (NOTE: This example +will result in a ServletException describing the error condition).
diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/relativeLinks.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/relativeLinks.html new file mode 100644 index 000000000..b8a1a5880 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/relativeLinks.html @@ -0,0 +1,12 @@ +

Import Tags Context Relative Examples

+ +

Context Relative   + +

+Importing a resource relative to a foreign context.
+

Encode Context Relative   + +

+URL encoding examples using a relative context and nested param tags.
diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/session.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/session.jsp new file mode 100644 index 000000000..3e851320d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/import/session.jsp @@ -0,0 +1,33 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> + + + + Jakarta DBTAGS Taglib Example + + + +<% + String _param = request.getParameter("contextName"); + session.setAttribute("_contextName", _param); + _param = request.getParameter("contextUrl"); + session.setAttribute("_contextUrl", _param); + + _param = request.getParameter("paramValue1"); + session.setAttribute("_paramValue1", _param); + _param = request.getParameter("paramValue2"); + session.setAttribute("_paramValue2", _param); + _param = request.getParameter("paramValue3"); + session.setAttribute("_paramValue3", _param); + + _param = request.getParameter("paramName1"); + session.setAttribute("_paramName1", _param); + _param = request.getParameter("paramName2"); + session.setAttribute("_paramName2", _param); + _param = request.getParameter("paramName3"); + session.setAttribute("_paramName3", _param); +%> + +<%@ include file="relativeLinks.html" %> + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/index.html new file mode 100644 index 000000000..7bc9f743b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/index.html @@ -0,0 +1,124 @@ + + + + JSTL: Examples Web Application + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Welcome to the standard-examples web application!

+ +

This web application includes a variety of sample JSP pages that showcase the + Tomcat Standard tags. + +

Examples

+ +

The JSTL examples have been divided in the following categories:

+ +

The navigation bar at the top of each index page provides quick navigation + to each set of example pages.

+ +

When navigating the examples, the following icons will allow you to look at + the source code as well as execute the example JSP page.

+ + + + + + + + + +
Look at the source code of the example JSP page
Execute the example JSP page
+

Infrastructure

+ +

The source code for the JSTL examples includes class startup.Init + to initilialize the objects used in the examples. This allows us to mimic the + environment that would normally be used within an MVC architecture: the Controller + invokes the business logic, saves the objects required by the web application + into JSP scoped attributes (usually request), and then invokes the proper JSP + page. For the sake of this "examples" webapp, all objects are saved + in the application scope.

+ +

The application attributes are:

+
    +
  • customers
    + A collection of Customer objects +
  • +
  • intArray
    + An array of int's +
  • +
  • stringArray
    + An array of Strings +
  • +
  • numberMap
    + A Map instance associating Integer objects with their Spanish names +
  • +
  • enumeration
    + An enumeration on numberMap from above.
    +
  • +
+

The classes of interest that hold the information manipulated by the JSP pages + are:

+
    +
  • Customer +
      +
    • int key
    • +
    • String lastName
    • +
    • String firstName
    • +
    • Date birthDate
    • +
    • Address address
      +
      +
    • +
    +
  • +
  • Address +
      +
    • String line1
    • +
    • String line2
    • +
    • String city
    • +
    • String state
    • +
    • String country
    • +
    +
  • +
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/BoundaryCases.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/BoundaryCases.jsp new file mode 100644 index 000000000..807f2038c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/BoundaryCases.jsp @@ -0,0 +1,60 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Miscellaneous -- Various Iterator Tests Example + + +

Various tests for Iterator tags

+ +

Iteration with only end specified (no items): end="10"

+(illegal) +<%-- + + • + +--%> + +

Iteration with only begin specified (no items): begin="10"

+(illegal) +<%-- + + ${i} • + +--%> + +

Iteration with only begin specified (with items): begin="2"

+ + + index: ${status.index} • + count: ${status.count} • + item: ${i}
+
+ +

Iteration with only end specified (with items): end="1"

+ + + index: ${status.index} • + count: ${status.count} • + item: ${i}>
+
+ +

Iteration with begin > end

+ + + index: ${status.index} • + count: ${status.count} • + item: ${i}
+
+ + index: ${status.index} • + count: ${status.count} • + item: ${i}
+
+
+ + Exception: ${ex} + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Collaboration.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Collaboration.jsp new file mode 100644 index 000000000..1f4eac508 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Collaboration.jsp @@ -0,0 +1,44 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL: Iterator Support 2-- Collaboration Example + + +

Collaboration

+ +

Without custom tags

+ + + + + + + + + + +
+ + + + + +
+ +

Using custom tags <even> and <odd>

+ + + + + + + + +
+ + +
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/DataTypes.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/DataTypes.jsp new file mode 100644 index 000000000..2d4770724 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/DataTypes.jsp @@ -0,0 +1,40 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Iterator Support -- Data Types Example + + +

Data Types

+ +

Array of primitives (int)

+ + + • + + +

Array of objects (String)

+ + +
+
+ +

Enumeration (warning: this only works until enumeration is exhausted!)

+ + +
+
+ +

Properties (Map)

+ + + =
+
+ +

String (Comma Separated Values)

+ + +
+
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Extensability.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Extensability.jsp new file mode 100644 index 000000000..2646e9bec --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Extensability.jsp @@ -0,0 +1,51 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#CodeName
(default locale)
+ + + + + + +
+Showing locales to of
+
+ + ">previous    + + + ">next    + +
+ diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/ForTokens.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/ForTokens.jsp new file mode 100644 index 000000000..483a5ca81 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/ForTokens.jsp @@ -0,0 +1,25 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Iterator Support -- forTokens Example + + + +

<forTokens>

+ +

String with '|' delimiter

+ + + • + + +

String with '|' and ',' delimiters

+ + + • + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Simple.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Simple.jsp new file mode 100644 index 000000000..e0f7c7676 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Simple.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Iterator Support -- Simple Iteration Example + + + +

Simple Iteration

+ +

Customer list

+ + + ${customer}
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/SimpleRange.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/SimpleRange.jsp new file mode 100644 index 000000000..066c78bfa --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/SimpleRange.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Iterator Support -- Simple Range Iteration Example + + +

Simple Range Iteration

+ +

1 to 10

+ + + ${i} • + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Status.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Status.jsp new file mode 100644 index 000000000..5678554c1 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/Status.jsp @@ -0,0 +1,54 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Iterator Support -- Iteration Status Example + + +

Iteration Status

+ +

Using status information: current, index, count, first, last

+ + + + + + + + + + + + + + + + + + + + + + +
indexcountlast namefirst namefirst?last?
+

There are + customers in the list. + +

+ +

Iteration using range attributes

+ + + begin:begin     + end:end     + step:step
+ sequence: +
+ + +
There are numbers in the list. +
+
+

+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/index.html new file mode 100644 index 000000000..3b1e5ccd9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/iterators/index.html @@ -0,0 +1,111 @@ + + + + JSTL: Iterator Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Iterator Tags Examples

+ +

Simple   + +

+Simply displays the default toString() value of the items in the +Customers collection.
+ +

Range    + +

+ +

Another simple example. Similar to the previous one, except that in this case + there is no collection to iterate over. The items attribute is + optional in the <forEach> tag. When it is not specified, + the range attributes must be used to iterate a specific number of times over + the tag's body. In this example, we simply iterate over the integer values specified + by the range attributes.

+ +

Data Types   

+ +

The <forEach> tag supports a large number of data types + for the collection of objects to iterate over. In this example, we feature the + following data types: array of primitives, array of objects, Enumeration, Properties + (Map), String (Comma Separated Values).

+ +

Iteration Status   

+ +

The iterator tag exposes a wealth of information relative to the iteration + taking place. This example features some of that status information.

+ +

Collaboration   

+ +

The iterator tags expose interface IteratorTag to allow custom tags to establish + implicit collaboration. This example shows two custom tags, <even> and + <odd> who take advantage of this implicit collaboration.

+ +

<forTokens>   

+ +

The <forEach> tag provides the basic iteration capabilities. <forTokens> + is a specialization for the handling of Strings of tokens. Essentially the same + as <forEach>, except that it only applies to Strings of tokens and that + it has an extra attribute "delims" to specify the token delimiter.

+ +

Extensibility   

+ +

JSTL exposes in its API the abstract class LoopTagSupport to facilitate + the implementation of custom iterator tags that leverage the standard iteration + behavior defined in JSTL. This example shows a custom iterator tag that shows all Locale objects available in the + server and a custom conditional sub-tag that + display the default locale.

+ +

Boundary Case Tests   + +

+Failure and minimal value examples.
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/DriverSetup.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/DriverSetup.jsp new file mode 100644 index 000000000..3cb4dc6b7 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/DriverSetup.jsp @@ -0,0 +1,22 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> + + + + JSTL: SQL action examples + + + +

SQL Driver Setup Example

+ + +
+<sql:setDataSource
+  var="example"
+  driver="RmiJdbc.RJDriver"
+  url="jdbc:rmi://localhost:1099/jdbc:cloudscape:CloudscapeDB;create=true"
+/>
+
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryDirect.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryDirect.jsp new file mode 100644 index 000000000..e5e44dcd4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryDirect.jsp @@ -0,0 +1,89 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: SQL action examples + + + +

SQL Direct Query Execution

+ +

This example demonstrates how the row and columns can be directly accessed using various direct mechanisms. + +

+ + + + + + + + + + create table mytable ( + nameid int primary key, + name varchar(80) + ) + + + + INSERT INTO mytable VALUES (1,'Paul Oakenfold') + + + INSERT INTO mytable VALUES (2,'Timo Maas') + + + INSERT INTO mytable VALUES (3,'Paul van Dyk') + + + + SELECT * FROM mytable + + + + +


+ +

Using the Row index and Column name

+Row[0].NAMEID: +
+Row[0].NAME: +
+Row[1].NAMEID: +
+Row[1].NAME: +
+Row[2].NAMEID: +
+Row[2].NAME: +
+ +
+ +

Using the Row and Column index

+Row[0][0]: +
+Row[0][1]: +
+Row[1][0]: +
+Row[1][1]: +
+Row[2][0]: +
+Row[2][1]: +
+ + + drop table mytable + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryIterate.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryIterate.jsp new file mode 100644 index 000000000..7a48e49be --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryIterate.jsp @@ -0,0 +1,104 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: SQL action examples + + + +

SQL Query Execution using an iterator

+ + + + + + + + + + create table mytable ( + nameid int primary key, + name varchar(80) + ) + + + + INSERT INTO mytable VALUES (1,'Paul Oakenfold') + + + INSERT INTO mytable VALUES (2,'Timo Maas') + + + INSERT INTO mytable VALUES (3,'Paul van Dyk') + + + + + SELECT * FROM mytable + + + + +
+ +

Iterating over each Row of the result

+ + + + + + + + + +
+ +
+ +

Iterating over Columns without knowing the index

+ + + + + + + + +
Name: Value:
+ +
+ +

Putting it all together

+ +<%-- Easiest example showing how to populate a table --%> + + + <%-- Get the column names for the header of the table --%> + + + + + <%-- Get the value of each column while iterating over rows --%> + + + + + + +
+ + + + drop table mytable + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryParam.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryParam.jsp new file mode 100644 index 000000000..d868e5bdd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/QueryParam.jsp @@ -0,0 +1,72 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: SQL action examples + + + + <% request.setAttribute("newName", new String("Paul van Dyk")); %> + +

SQL Query Execution using parameters

+ +

Using parameter marker's to insert values in the SQL statements

+ + + + + + + + + + create table mytable ( + nameid int primary key, + name varchar(80) + ) + + + + INSERT INTO mytable VALUES (1,'Paul Oakenfold') + + + + INSERT INTO mytable VALUES (?,'Timo Maas') + + + + + INSERT INTO mytable VALUES (?,?) + + + + + + SELECT * FROM mytable + + + + + + + + + + + +
+ + + drop table mytable + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Transaction.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Transaction.jsp new file mode 100644 index 000000000..95e20c9cf --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Transaction.jsp @@ -0,0 +1,60 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> + + + + JSTL: SQL action examples + + + +

SQL Transactions

+ + + + + + +

You can group transactions together using the <sql:transaction> tag.

+ +

Creating table using a transaction

+ + + + create table mytable ( + nameid int primary key, + name varchar(80) + ) + + + +

DONE: Creating table using a transaction

+ +
+ +

Populating table in one transaction

+ + + + INSERT INTO mytable VALUES (1,'Paul Oakenfold') + + + INSERT INTO mytable VALUES (2,'Timo Maas') + + + INSERT INTO mytable VALUES (3,'Paul van Dyk') + + + +

DONE: Populating table in one transaction

+ + + drop table mytable + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Update.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Update.jsp new file mode 100644 index 000000000..22eb548db --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/Update.jsp @@ -0,0 +1,115 @@ +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: SQL action examples + + + +

SQL Update Execution

+ + + + + + +
+ + + + + create table mytable ( + nameid int primary key, + name varchar(80) + ) + + +

Inserting three rows into table

+ + INSERT INTO mytable VALUES (1,'Paul Oakenfold') + + + INSERT INTO mytable VALUES (2,'Timo Maas') + + + INSERT INTO mytable VALUES (3,'Paul van Dyk') + + +

DONE: Inserting three rows into table

+ + + + SELECT * FROM mytable + + +
+ +<%-- An example showing how to populate a table --%> + + <%-- Get the column names for the header of the table --%> + + + + + <%-- Get the value of each column while iterating over rows --%> + + + + + + + +
+ + +

Deleting second row from table

+ + + DELETE FROM mytable WHERE nameid=2 + + +

DONE: Deleting second row from table

+ + + SELECT * FROM mytable + + + +<%-- Yet another example showing how to populate a table --%> + + + <%-- Get the column names for the header of the table --%> + + + <%-- Each row is a Map object key'd by the column name --%> + + + + + + + + + + <%-- Get the value of each column while iterating over rows --%> + + + + +
+ + + + drop table mytable + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/index.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/index.jsp new file mode 100644 index 000000000..b8bc608ae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/index.jsp @@ -0,0 +1,108 @@ + + + + JSTL: SQL Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLVMisc.
+ +

SQL Tags Examples

+ +

These examples create their own table for demonstration purposes. Every database + supports table creation in a slightly different way. For instance, different + databases have different types and constraints. The simplest possible table + was chosen, however it may still not be supported by your particular database. + Check your database documentation or administrator if you have problems creating + the table and modify the examples acordingly. Here is the table used in the + examples:

+

+    create table mytable (
+    nameid int primary key,
+    name varchar(80)
+    )
+
+

Enter your Driver Name and DataBase URL to test the Database Tag Library.

+ +

NOTE: You will need to have the DataBase Driver classes available to your server's + classloader or in your server's CLASSPATH at startup.

+ +
+ + + + + + + + + + + + + + + + + + + + +
Driver: + +
URL: + +

+ +

The following two fields are Optional. They are included + for convenience.
+ NOTE: an unsecure form is used.

+
User Name: + +
Password: + +
+

+ +

+
+
+

NOTE: You can access the tags directly here to look at the source. If you do + not provide a valid Driver and URL using the above form, the tags will NOT run properly.

+<%@ include file="links.html" %> + +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library • support +   development   + comments to JSR-52
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/links.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/links.html new file mode 100644 index 000000000..c7fd4c223 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/links.html @@ -0,0 +1,43 @@ +

DataBase Tags Examples

+ +

Query Iterate   + +

+Example showing how to iterate over the result of a query.
+ +

Update   + +

+Example showing several database updates.
+ +

Direct Query   + +

+Example showing how the the result of a query can be directly accessed.
+ +

Query Parameters   + +

+Example showing how query parameters can be used to create an SQL query.
+ +

Transaction   + +

+Example showing how to setup transactions.
+ +

Driver Setup   + +

+A sample page showing how a driver can be configured. NOTE: this is meant for prototyping and simple applications.
+ diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/session.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/session.jsp new file mode 100644 index 000000000..7afd78aae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/sql/session.jsp @@ -0,0 +1,17 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + Jakarta DBTAGS Taglib Example + + + + + + + + +<%@ include file="links.html" %> + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsError.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsError.jsp new file mode 100644 index 000000000..f136227d0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsError.jsp @@ -0,0 +1,28 @@ +<%@ taglib prefix="permittedTaglibs" uri="http://jakarta.apache.org/taglibs/standard/permittedTaglibs" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL: Tag Library Validator -- PermittedTaglibs Error + + + +

This JSP page uses taglibs that are not permitted. A translation error will occur.

+ +

Using custom tags <even> and <odd>

+ + + + + + + + +
+ + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsOk.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsOk.jsp new file mode 100644 index 000000000..0610f27ae --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/PermittedTaglibsOk.jsp @@ -0,0 +1,30 @@ +<%@ taglib prefix="permittedTaglibs" uri="http://jakarta.apache.org/taglibs/standard/permittedTaglibs" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + JSTL: Tag Library Validator -- ScriptFree OK + + + +

This JSP page only uses permitted taglibs (which in this case are the JSTL taglibs)

+ + + + + + + + + + +
+ + + + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeError.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeError.jsp new file mode 100644 index 000000000..17d6fd76c --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeError.jsp @@ -0,0 +1,15 @@ +<%@ taglib prefix="scriptfree" uri="http://jakarta.apache.org/taglibs/standard/scriptfree" %> + + + JSTL: Tag Library Validator -- ScriptFree Error + + + +

This JSP page is NOT free of scripting elements. Translation error will occur.

+ +<% java.util.Date date = new java.util.Date(); %> + +Date is: <%= date %> + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeOk.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeOk.jsp new file mode 100644 index 000000000..94d0a6fa9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/ScriptFreeOk.jsp @@ -0,0 +1,25 @@ +<%@ taglib prefix="scriptfree" uri="http://jakarta.apache.org/taglibs/standard/scriptfree" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + JSTL: Tag Library Validator -- ScriptFree OK + + + +

This JSP page is free of scripting elements

+ + + + + + + + + +
+ + no cell phone specified + +
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/index.html new file mode 100644 index 000000000..39f828aea --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/tlv/index.html @@ -0,0 +1,78 @@ + + + + JSTL: Tag Library Validators Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

Tag Library Validators Examples

+ +

ScriptFree OK   + +

+ +

This example shows a JSP page using the ScriptFree TLV. Because this page does + not use any scripting element, there are no translation errors and the page + is properly processed.

+ +

ScriptFree Error   + +

+ +

This example shows a JSP page using the ScriptFree TLV. Because this page uses + scripting elements, a translation error is reported when accessing the page.

+ +

PermittedTaglibs OK   + +

+ +

This example shows a JSP page using the PermittedTaglibs TLV. Because this + page only uses permitted tag libraries, there are no translation errors and + the page is properly processed.

+ +

+ +

PermittedTaglibs Error   + +

+ +

This example shows a JSP page using the PermittedTaglibs TLV. Because this + page uses tag libraries that are not allowed, a translation error is reported + when accessing the page.

+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Filter.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Filter.jsp new file mode 100644 index 000000000..9dea84012 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Filter.jsp @@ -0,0 +1,33 @@ +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> +<%@ taglib prefix="ex" uri="/jstl-examples-taglib" %> + + + + JSTL: XML Support -- Parse / Filter / Out + + +

Parse / Filter / Out

+ + + + + + + + foo + + + + bar + + + + + + + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEach.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEach.jsp new file mode 100644 index 000000000..7cb1d29f6 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEach.jsp @@ -0,0 +1,85 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse / ForEach + + + + +

<x:parse> / <x:forEach>

+ + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + +
ExpressionResult
+<x:forEach select="$document//a" varStatus="status">
+  ${status.index}:  <x:out select="."/> <br>
+<x:forEach>
+
+
+ + ${status.index}: +
+
+
+<x:forEach select="$document//a" begin="1" end="2" varStatus="status">
+  -> <x:out select="."/> <br>
+<x:forEach>
+
+
+ + ${status.index}: +
+
+
+<x:forEach select="$document//a" varStatus="status">
+  ${status.index}:  
+  <x:if select=".//d">
+    <d> element present
+  <x:if>
+  <br>
+<x:forEach>
+
+
+ + ${status.index}: + + <d> element present + +
+
+
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEachDoc.xml b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEachDoc.xml new file mode 100644 index 000000000..30ccb729d --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ForEachDoc.xml @@ -0,0 +1,15 @@ + + + + foo 1 + + + bar 2 + + + bar 3 + + + foo 4 + + \ No newline at end of file diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/If.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/If.jsp new file mode 100644 index 000000000..bd5ede3f0 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/If.jsp @@ -0,0 +1,42 @@ +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse / If + + +

Parse / If

+ + + + + + foo + + + + bar + + + + + + $a//c exists + + +
+ + + $a/a/d exists + + +
+ + + $a/w/o/l exists + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Out.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Out.jsp new file mode 100644 index 000000000..3f25c62ed --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Out.jsp @@ -0,0 +1,82 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse / Out + + + + +

<x:parse> / <x:out>

+ + + + + + + + + + +
+
+
+ + + + + + <%-- + + + + + --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionResult
3 + 3
$doc//sport +
+
$doc/games/country/* +
+
$doc//* +
+
$doc/games/country +
+
$doc/games/country[last()] +
+
$doc//@id +
+
$doc//country[@id='Denmark'] +
+
+
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Parse.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Parse.jsp new file mode 100644 index 000000000..0976ce22f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Parse.jsp @@ -0,0 +1,30 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse + + +

Parse from Objects and URLs

+ + + + + + foo + + + + bar + + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ParseWithEntities.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ParseWithEntities.jsp new file mode 100644 index 000000000..9b24fc888 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/ParseWithEntities.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse + + +

Parse from Objects and URLs

+ + + + + + ]> + + &included; + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Set.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Set.jsp new file mode 100644 index 000000000..84f6a5105 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Set.jsp @@ -0,0 +1,31 @@ +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse / Set / Out + + +

Parse / Set / Out

+ + + + + + foo + + + + + bar + + + + + + + + +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Transform.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Transform.jsp new file mode 100644 index 000000000..e074e9a58 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/Transform.jsp @@ -0,0 +1,58 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Transform + + +

Parse / Expr

+ + + header! + + + + + + + +

+
+ +
+
+ +Prints "header" as a header:
+ + +
+ +Prints "header" in normal size:
+ + + +
+ +
+

Transformations using output from XPath expressions

+ + + + +
+ +

Inline transformations

+ + + + + Paragraph one! + Paragraph foo! + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/TransformWithInclusion.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/TransformWithInclusion.jsp new file mode 100644 index 000000000..e3b606455 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/TransformWithInclusion.jsp @@ -0,0 +1,32 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Transform + + +

Parse / Expr

+ + + + + +]> + + &included; + + + + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/When.jsp b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/When.jsp new file mode 100644 index 000000000..be312c708 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/When.jsp @@ -0,0 +1,68 @@ +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + JSTL: XML Support -- Parse / When + + +

Parse / When

+ + + + + + foo + + + + bar + + + + + + + @foo = bar + + + @foo = foo + + + @foo not recognized + + + +
+ + + + @foo = foo + + + @foo = bar + + + @foo not recognized + + + +
+ + + + @foo = barr + + + @foo = fooo + + + @foo not recognized + + + +
+ +
+ + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/games.xml b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/games.xml new file mode 100644 index 000000000..e528b6919 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/games.xml @@ -0,0 +1,31 @@ + + + + + Lux 1 + swimming + 23 + M + + + Lux 2 + wrestling + 31 + M + + + + + Den 1 + cycling + 18 + F + + + Den 2 + sailing + 27 + M + + + \ No newline at end of file diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/included.xml b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/included.xml new file mode 100644 index 000000000..572429076 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/included.xml @@ -0,0 +1,3 @@ + + YES! + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/includedStylesheet.xsl b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/includedStylesheet.xsl new file mode 100644 index 000000000..ff71c51a8 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/includedStylesheet.xsl @@ -0,0 +1,10 @@ + + + +

+ +

+
+ +
diff --git a/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/index.html b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/index.html new file mode 100644 index 000000000..d6aaa0d75 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-examples/src/main/webapp/xml/index.html @@ -0,0 +1,93 @@ + + + + JSTL: XML Tags Examples + + + + + + + + + + + + + +
standard taglib • implementation + of the JSP Standard Tag Library
Examples     Introduction + • General Purpose + • Conditionals + • Iterators • + ImportI18N + & FormattingXML + • SQLFunctions + • TLV +
+ +

XML Examples

+ +

Out    +

+Retrieving a String from a parsed XML document
+ +

Filter    + +

+Applying a SAX XMLFilter object to a document before parsing
+ +

ForEach    + +

+Iterating over XML nodes
+ +

If    + +

+Basing a decision on the status of an XML document
+ +

Parse    +

+Parsing XML documents directly from Objects and from URLs.
+ +

Set    + +

+Storing an object resulting from an XPath expression
+ +

Transform    + +

+Applying XSLT transformations
+ +

When    + +

+Mutually exclusive conditionals based on the status of an XML document
+ +

Parse with entities    + +

+Parsing a document with relative entity references (using systemId)
+ +

Transform with inclusion    + +

+Transformations using XSLT tags like <xsl:include> (with xsltSystemId)
+ +
+ + + + +
standard taglib • implementation + of the JSP Standard Tag Library
+ + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/pom.xml b/Java-base/tomcat-taglibs-standard/src/standard-test/pom.xml new file mode 100644 index 000000000..cc9fda82b --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/pom.xml @@ -0,0 +1,231 @@ + + + + 4.0.0 + + org.apache.taglibs + taglibs-parent + 3 + + + taglibs-standard-test + 1.2.3-SNAPSHOT + Apache Standard Taglib Cactus Tests + war + + 2003 + + The Cactus tests for the Jakarta Standard JSTL implementation + + + http://tomcat.apache.org/taglibs/standard/ + + + scm:svn:http://svn.apache.org/repos/asf/tomcat/taglibs/standard/trunk/standard-test + scm:svn:https://svn.apache.org/repos/asf/tomcat/taglibs/standard/trunk/standard-test + http://svn.apache.org/viewvc/tomcat/taglibs/standard/trunk/standard-test + + + + + apache.website + Apache Website + scpexe://people.apache.org/www/tomcat.apache.org/taglibs/standard/standard-test/ + + + + + Henri Yandell + Bjorn Townsend + + + + + org.apache.taglibs + taglibs-standard-impl + 1.2.3-SNAPSHOT + + + org.apache.taglibs + taglibs-standard-spec + 1.2.3-SNAPSHOT + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided + + + jakarta.el + jakarta.el-api + 1.0 + provided + + + + xalan + xalan + 2.7.1 + + + + org.apache.cactus + cactus.core.framework.javaEE.13-14 + 1.8.1 + test + + + org.apache.cactus + cactus.core.framework.wrapper.javaEE.14 + 1.8.1 + test + + + org.apache.cactus + cactus.integration.shared.api + 1.8.1 + test + + + org.apache.derby + derby + 10.4.2.0 + + + + junit + junit + 3.8.2 + test + + + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + WEB-INF/classes + target/test-classes + + + + + + + org.apache.cactus + cactus.integration.maven2 + 1.8.1 + + target/taglibs-standard-test-1.2.3-SNAPSHOT.war + target/cactus-taglibs-standard-test-1.2.3-SNAPSHOT.war + + + + cactus-cactifywar + pre-integration-test + + cactifywar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + surefire-it + integration-test + + test + + + false + + + cactus.contextURL + http://localhost:8080/taglibs-standard-test + + + + + + + + + org.mortbay.jetty + maven-jetty-plugin + 6.1.24 + + 10 + 9999 + stop + + + 8080 + 60000 + + + + + + start-jetty + pre-integration-test + + run-war + + + 0 + true + target/cactus-taglibs-standard-test-1.2.3-SNAPSHOT.war + + + + stop-jetty + post-integration-test + + stop + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/WEB-INF/web.xml b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..c5a171518 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,25 @@ + + + + jstl test + jstl test + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/functions/TestEndsWith.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/functions/TestEndsWith.jsp new file mode 100644 index 000000000..5584805fd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/functions/TestEndsWith.jsp @@ -0,0 +1,21 @@ +<%-- +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. +--%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fm" uri="http://java.sun.com/jsp/jstl/functions" %> + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test34109.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test34109.jsp new file mode 100644 index 000000000..43828e7bf --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test34109.jsp @@ -0,0 +1,21 @@ +<%-- +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. +--%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.jsp new file mode 100644 index 000000000..3e267a830 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.jsp @@ -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. +--%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + +<% + java.io.StringReader o = (java.io.StringReader)pageContext.getAttribute("xmlSource"); + System.out.println("o: " + o); + char[] buf = new char[1]; + while (o.read(buf) > 0) + { + System.out.print(buf); + } + System.out.println(""); + System.out.println("------"); + o.reset(); +%> + + +<% + System.out.println("XX parsed ok"); +%> + +worked: ${xmldoc} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.xml b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.xml new file mode 100644 index 000000000..5d66aa128 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/Test37466.xml @@ -0,0 +1,19 @@ + + + data data data + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestOutTag.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestOutTag.jsp new file mode 100644 index 000000000..666b51530 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestOutTag.jsp @@ -0,0 +1,33 @@ +<%-- +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. +--%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +Start + + + + + + +<%-- this will be trimmed --%> + Default from Body + +cats & dogs +cats & dogs +Reader + + +End diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestSetTag.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestSetTag.jsp new file mode 100644 index 000000000..47dc88328 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/core/TestSetTag.jsp @@ -0,0 +1,20 @@ +<%-- +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. +--%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp new file mode 100644 index 000000000..bb3465457 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.jsp @@ -0,0 +1,34 @@ +<%-- +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. +--%> + + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test33054.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test33054.jsp new file mode 100644 index 000000000..1e0f21f31 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test33054.jsp @@ -0,0 +1,33 @@ +<%-- +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. +--%> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> + + + + + + SELECT id, name, id as id1, name as name1, id as id2, name as name2 FROM Bug33054 + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test43831.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test43831.jsp new file mode 100644 index 000000000..8d95869cd --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/sql/Test43831.jsp @@ -0,0 +1,37 @@ +<%-- +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. +--%> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> + + + + + + SELECT name as wonka FROM Bug43831 + + + + + + + + + + + + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.jsp new file mode 100644 index 000000000..f9bc91592 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.jsp @@ -0,0 +1,46 @@ +<%-- +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. +--%> + +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> + + + + + + + + + + + + + + + + + + + + + + + + + +Correct: ${correct}
+Incorrect: ${incorrect} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.xml b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.xml new file mode 100644 index 000000000..e3bcd3684 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test30068.xml @@ -0,0 +1,20 @@ + + + + 42 + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test35216.jsp b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test35216.jsp new file mode 100644 index 000000000..b226dcf16 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/main/webapp/org/apache/taglibs/standard/tag/el/xml/Test35216.jsp @@ -0,0 +1,24 @@ +<%-- +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. +--%> +<%@ page session="false" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %> + + + + + foo + diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/functions/TestEndsWith.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/functions/TestEndsWith.java new file mode 100644 index 000000000..b730e11d4 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/functions/TestEndsWith.java @@ -0,0 +1,49 @@ +/* + * 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.taglibs.standard.functions; + +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class TestEndsWith + extends JspTestCase { + + public TestEndsWith(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testEndsWith() throws Exception { + String var = "var1"; + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + Boolean actual = (Boolean) pageContext.getAttribute(var, + PageContext.APPLICATION_SCOPE); + assertEquals(Boolean.TRUE, actual); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test34109.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test34109.java new file mode 100644 index 000000000..4a29dab28 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test34109.java @@ -0,0 +1,48 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test34109 extends JspTestCase { + + public Test34109(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test34109() throws Exception { + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + + String genurl = (String) pageContext.getAttribute("genurl", PageContext.APPLICATION_SCOPE); + + assertTrue("The URL should be /foo/test.jsp", genurl.startsWith("/foo/test.jsp")); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test37466.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test37466.java new file mode 100644 index 000000000..ef6c7cc2a --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/Test37466.java @@ -0,0 +1,55 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import java.net.*; +import jakarta.servlet.http.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test37466 extends JspTestCase { + + public Test37466(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test37466() throws Exception { + String serverName = pageContext.getRequest().getServerName(); + int serverPort = pageContext.getRequest().getServerPort(); + String contextPath = ( (HttpServletRequest) pageContext.getRequest() ).getContextPath(); + String jspPath = TestUtil.getTestJsp(this); + String testPath = "http://" + serverName + ":" + serverPort + contextPath + jspPath;; + + URL url = new URL(testPath); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("HEAD"); + + String responseCode = Integer.toString(connection.getResponseCode()); + assertEquals(testPath + "The response code should be 200", "200", responseCode); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestOutTag.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestOutTag.java new file mode 100644 index 000000000..f31c30854 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestOutTag.java @@ -0,0 +1,40 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import org.apache.cactus.ServletTestCase; +import org.apache.cactus.WebResponse; +import org.apache.taglibs.standard.testutil.TestUtil; + +import jakarta.servlet.RequestDispatcher; +import java.io.StringReader; + +/** + */ +public class TestOutTag extends ServletTestCase { + + public void testValue() throws Exception { + request.setAttribute("cats", new StringReader("cats & dogs")); + request.setAttribute("dogs", new StringReader("cats & dogs")); + RequestDispatcher rd = config.getServletContext().getRequestDispatcher(TestUtil.getTestJsp(this)); + rd.forward(request, response); + } + + public void endValue(WebResponse response) throws Exception { + assertEquals(TestUtil.loadResource(this), response.getText()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestSetTag.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestSetTag.java new file mode 100644 index 000000000..6bf318f51 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/core/TestSetTag.java @@ -0,0 +1,51 @@ +/* + * 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.taglibs.standard.tag.el.core; + +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class TestSetTag + extends JspTestCase { +// private SetTag setTag = null; + + public TestSetTag(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSetTag() throws Exception { + String var = "var1"; + String expected = "value1"; + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + String actual = (String) pageContext.getAttribute(var, + PageContext.APPLICATION_SCOPE); + assertEquals(expected, actual); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java new file mode 100644 index 000000000..62f0f35c9 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/fmt/TestDateTag.java @@ -0,0 +1,52 @@ +/* + * 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.taglibs.standard.tag.el.fmt; + +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class TestDateTag extends JspTestCase { + + public TestDateTag(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testDateTag() throws Exception { + String var = "varDate"; + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + String actual = (String) pageContext.getAttribute(var, PageContext.APPLICATION_SCOPE); + + // This isn't desired; Cactus doesn't set things up right + assertEquals(new java.util.Date().toString().length(), actual.length()); + + // Ideally we would run this, or something like it +// assertEquals("yyyy-MM-dd".length(), actual.length()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test33054.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test33054.java new file mode 100644 index 000000000..6a61ddb11 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test33054.java @@ -0,0 +1,71 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import java.sql.*; +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test33054 extends JspTestCase { + + public Test33054(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + Connection conn = DriverManager.getConnection("jdbc:derby:cactustest;create=true"); + Statement stmt = conn.createStatement(); + try { stmt.execute("DROP TABLE Bug33054"); } catch(SQLException sqle) { } // ignore + stmt.execute("CREATE TABLE Bug33054 ( id int primary key, name varchar(80) )"); + stmt.execute("INSERT INTO Bug33054 VALUES(1, 'a')"); + + ResultSet rs = stmt.executeQuery("SELECT * FROM Bug33054"); + rs.next(); + assertEquals( 1, rs.getInt(1) ); + assertEquals( "a", rs.getString(2) ); + + rs.close(); + stmt.close(); + conn.close(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + Connection conn = DriverManager.getConnection("jdbc:derby:cactustest"); + Statement stmt = conn.createStatement(); + stmt.execute("DROP TABLE Bug33054"); + stmt.close(); + conn.close(); + } + + public void test33054() throws Exception { + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + + String data = (String) pageContext.getAttribute("bug33054", PageContext.APPLICATION_SCOPE); + + // This fails and isn't something that can easily be fixed. + // See: http://issues.apache.org/bugzilla/show_bug.cgi?id=33054 + //assertEquals( "ID=1NAME=1" + "ID1=1NAME1=a" + "ID2=1NAME2=a", data ); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test43831.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test43831.java new file mode 100644 index 000000000..bb2cfddd5 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/sql/Test43831.java @@ -0,0 +1,73 @@ +/* + * 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.taglibs.standard.tag.el.sql; + +import java.sql.*; +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test43831 extends JspTestCase { + + public Test43831(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + Connection conn = DriverManager.getConnection("jdbc:derby:cactustest;create=true"); + Statement stmt = conn.createStatement(); + try { stmt.execute("DROP TABLE Bug43831"); } catch(SQLException sqle) { } // ignore + stmt.execute("CREATE TABLE Bug43831 ( id int primary key, name varchar(80) )"); + stmt.execute("INSERT INTO Bug43831 VALUES(1, 'a')"); + + ResultSet rs = stmt.executeQuery("SELECT * FROM Bug43831"); + rs.next(); + assertEquals( 1, rs.getInt(1) ); + assertEquals( "a", rs.getString(2) ); + + rs.close(); + stmt.close(); + conn.close(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + Connection conn = DriverManager.getConnection("jdbc:derby:cactustest"); + Statement stmt = conn.createStatement(); + stmt.execute("DROP TABLE Bug43831"); + stmt.close(); + conn.close(); + } + + public void test43831() throws Exception { + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + + String label = (String) pageContext.getAttribute("bug43831Label", PageContext.APPLICATION_SCOPE); + String name = (String) pageContext.getAttribute("bug43831Name", PageContext.APPLICATION_SCOPE); + String column = (String) pageContext.getAttribute("bug43831", PageContext.APPLICATION_SCOPE); + + assertEquals( "Failed to find 'label'", "a", label); + assertNull( "Failed to not find 'name'", name); + assertEquals( "Failed to find label as column name", "wonka", column.toLowerCase()); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test30068.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test30068.java new file mode 100644 index 000000000..16bb9f259 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test30068.java @@ -0,0 +1,50 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import jakarta.servlet.jsp.*; +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test30068 extends JspTestCase { + + public Test30068(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test30068() throws Exception { + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + + String correct = (String) pageContext.getAttribute("correct", PageContext.APPLICATION_SCOPE); + String incorrect = (String) pageContext.getAttribute("incorrect", PageContext.APPLICATION_SCOPE); + + assertEquals("The incorrect answer is not an empty string", "", incorrect); + assertEquals("The correct answer would be 42", "42", correct); + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test35216.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test35216.java new file mode 100644 index 000000000..590a9b17f --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/tag/el/xml/Test35216.java @@ -0,0 +1,45 @@ +/* + * 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.taglibs.standard.tag.el.xml; + +import org.apache.cactus.*; +import org.apache.taglibs.standard.testutil.TestUtil; + +public class Test35216 extends JspTestCase { + + public Test35216(String name) { + super(name); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void test35216() throws Exception { + String toInclude = TestUtil.getTestJsp(this); + pageContext.include(toInclude); + + // fail case throws an exception; so nothing further needed + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/testutil/TestUtil.java b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/testutil/TestUtil.java new file mode 100644 index 000000000..ebacfba37 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/java/org/apache/taglibs/standard/testutil/TestUtil.java @@ -0,0 +1,60 @@ +/* + * 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.taglibs.standard.testutil; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +/** + * Helper class for Cactus tests + */ +public class TestUtil { + + private TestUtil() {} + + /** + * Gets the corresponding test jsp for this test case. As a convention, + * test class and test jsp should have the same package and directory + * structure, and the same base name. + * @return a context-relative path to the test jsp. + */ + public static String getTestJsp(Object obj) { + String className = obj.getClass().getName(); + String baseName = className.replace('.', '/'); + return "/" + baseName + ".jsp"; + } + + public static String loadResource(Object obj) throws IOException { + Class clazz = obj.getClass(); + InputStream is = clazz.getResourceAsStream(clazz.getSimpleName() + ".txt"); + Reader reader = new InputStreamReader(is); + try { + char[] buffer = new char[1024]; + StringBuilder s = new StringBuilder(); + int count; + while ((count = reader.read(buffer)) > 0) { + s.append(buffer, 0, count); + } + return s.toString(); + } finally { + reader.close(); + } + } +} diff --git a/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/resources/org/apache/taglibs/standard/tag/el/core/TestOutTag.txt b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/resources/org/apache/taglibs/standard/tag/el/core/TestOutTag.txt new file mode 100644 index 000000000..d46e3ccc3 --- /dev/null +++ b/Java-base/tomcat-taglibs-standard/src/standard-test/src/test/resources/org/apache/taglibs/standard/tag/el/core/TestOutTag.txt @@ -0,0 +1,16 @@ + + +Start +Hello World +cats & dogs +cats & dogs +5 + +default +Default from Body +<b>cats & dogs</b> +cats & dogs +Reader +cats & dogs +cats & dogs +End diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_587/Dockerfile b/Java/tomcat-taglibs-standard-LoopTagSupport_587/Dockerfile new file mode 100644 index 000000000..0f44816f6 --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_587/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:tomcat-taglibs-standard + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_587/buggy.java b/Java/tomcat-taglibs-standard-LoopTagSupport_587/buggy.java new file mode 100644 index 000000000..0fc389238 --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_587/buggy.java @@ -0,0 +1,658 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.el.ELContext; +import jakarta.el.ValueExpression; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.IterationTag; +import jakarta.servlet.jsp.tagext.TagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; + +/** + *

Base support class to facilitate implementation of iteration tags.

+ *

Since most iteration tags will behave identically with respect to + * actual iterative behavior, JSTL provides this + * base support class to facilitate implementation. Many iteration tags + * will extend this and merely implement the hasNext() and + * next() methods + * to provide contents for the handler to iterate over.

+ *

In particular, this base class provides support for:

+ *
    + *
  • Iteration control, based on protected prepare(), next(), + * and hasNext() methods + *
  • Subsetting (begin, end, step>functionality, + * including validation + * of subset parameters for sensibility) + *
  • item retrieval (getCurrent()) + *
  • status retrieval (LoopTagStatus) + *
  • exposing attributes (set by var and varStatus attributes) + *
+ *

In providing support for these tasks, LoopTagSupport contains + * certain control variables that act to modify the iteration. Accessors + * are provided for these control variables when the variables represent + * information needed or wanted at translation time (e.g., var, + * varStatus). For + * other variables, accessors cannot be provided here since subclasses + * may differ on their implementations of how those accessors are received. + * For instance, one subclass might accept a String and convert it into + * an object of a specific type by using an expression evaluator; others + * might accept objects directly. Still others might not want to expose + * such information to outside control.

+ * + * @author Shawn Bayern + */ + +public abstract class LoopTagSupport + extends TagSupport + implements LoopTag, IterationTag, TryCatchFinally { + //********************************************************************* + // 'Protected' state + + /* + * JavaBean-style properties and other state slaved to them. These + * properties can be set directly by accessors; they will not be + * modified by the LoopTagSupport implementation -- and should + * not be modified by subclasses outside accessors unless those + * subclasses are perfectly aware of what they're doing. + * (An example where such non-accessor modification might be sensible + * is in the doStartTag() method of an EL-aware subclass.) + */ + + /** + * Starting index ('begin' attribute) + */ + protected int begin; + + /** + * Ending index of the iteration ('end' attribute). + * A value of -1 internally indicates 'no end + * specified', although accessors for the core JSTL tags do not + * allow this value to be supplied directly by the user. + */ + protected int end; + + /** + * Iteration step ('step' attribute) + */ + protected int step; + + /** + * Boolean flag indicating whether 'begin' was specified. + */ + protected boolean beginSpecified; + + /** + * Boolean flag indicating whether 'end' was specified. + */ + protected boolean endSpecified; + + /** + * Boolean flag indicating whether 'step' was specified. + */ + protected boolean stepSpecified; + + /** + * Attribute-exposing control + */ + protected String itemId, statusId; + + protected ValueExpression deferredExpression; + + //********************************************************************* + // 'Private' state (implementation details) + + /* + * State exclusively internal to the default, reference implementation. + * (While this state is kept private to ensure consistency, 'status' + * and 'item' happen to have one-for-one, read-only, accesor methods + * as part of the LoopTag interface.) + * + * 'last' is kept separately for two reasons: (a) to avoid + * running a computation every time it's requested, and (b) to + * let LoopTagStatus.isLast() avoid throwing any exceptions, + * which would complicate subtag and scripting-variable use. + * + * Our 'internal index' begins at 0 and increases by 'step' each + * round; this is arbitrary, but it seemed a simple way of keeping + * track of the information we need. To avoid computing + * getLoopStatus().getCount() by dividing index / step, we keep + * a separate 'count' and increment it by 1 each round (as a minor + * performance improvement). + */ + private LoopTagStatus status; // our LoopTagStatus + private Object item; // the current item + private int index; // the current internal index + private int count; // the iteration count + private boolean last; // current round == last one? + + //********************************************************************* + // Constructor + + /** + * Constructs a new LoopTagSupport. As with TagSupport, subclasses + * should not implement constructors with arguments, and no-arguments + * constructors implemented by subclasses must call the superclass + * constructor. + */ + public LoopTagSupport() { + super(); + init(); + } + + + //********************************************************************* + // Abstract methods + + /** + *

Returns the next object over which the tag should iterate. This + * method must be provided by concrete subclasses of LoopTagSupport + * to inform the base logic about what objects it should iterate over.

+ *

It is expected that this method will generally be backed by an + * Iterator, but this will not always be the case. In particular, if + * retrieving the next object raises the possibility of an exception + * being thrown, this method allows that exception to propagate back + * to the JSP container as a JspTagException; a standalone Iterator + * would not be able to do this. (This explains why LoopTagSupport + * does not simply call for an Iterator from its subtags.)

+ * + * @return the java.lang.Object to use in the next round of iteration + * @throws java.util.NoSuchElementException + * if next() is called but no new elements are available + * @throws jakarta.servlet.jsp.JspTagException + * for other, unexpected exceptions + */ + protected abstract Object next() throws JspTagException; + + /** + *

Returns information concerning the availability of more items + * over which to iterate. This method must be provided by concrete + * subclasses of LoopTagSupport to assist the iterative logic + * provided by the supporting base class.

+ *

See next for more information about the + * purpose and expectations behind this tag.

+ * + * @return true if there is at least one more item to iterate + * over, false otherwise + * @throws jakarta.servlet.jsp.JspTagException + * + * @see #next + */ + protected abstract boolean hasNext() throws JspTagException; + + /** + *

Prepares for a single tag invocation. Specifically, allows + * subclasses to prepare for calls to hasNext() and next(). + * Subclasses can assume that prepare() will be called once for + * each invocation of doStartTag() in the superclass.

+ * + * @throws jakarta.servlet.jsp.JspTagException + * + */ + protected abstract void prepare() throws JspTagException; + + + //********************************************************************* + // Lifecycle management and implementation of iterative behavior + + /** + * Releases any resources this LoopTagSupport may have (or inherit). + */ + @Override + public void release() { + super.release(); + init(); + } + + /** + * Begins iterating by processing the first item. + */ + @Override + public int doStartTag() throws JspException { + if (end != -1 && begin > end) { + // JSTL 1.1. We simply do not execute the loop. + return SKIP_BODY; + } + + // we're beginning a new iteration, so reset our counts (etc.) + index = 0; + count = 1; + last = false; + + // let the subclass conduct any necessary preparation + prepare(); + + // throw away the first 'begin' items (if they exist) + discardIgnoreSubset(begin); + + // get the item we're interested in + if (hasNext()) + // index is 0-based, so we don't update it for the first item + { + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to include our body... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_INCLUDE; + } + + /** + * Continues the iteration when appropriate -- that is, if we (a) have + * more items and (b) don't run over our 'end' (given our 'step'). + */ + @Override + public int doAfterBody() throws JspException { + + // re-sync the index, given our prior behind-the-scenes 'step' + index += step - 1; + + // increment the count by 1 for each round + count++; + + // everything's been prepared for us, so just get the next item + if (hasNext() && !atEnd()) { + index++; + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to re-iterate... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_AGAIN; + } + + /** + * Removes any attributes that this LoopTagSupport set. + *

These attributes are intended to support scripting variables with + * NESTED scope, so we don't want to pollute attribute space by leaving + * them lying around. + */ + public void doFinally() { + /* + * Make sure to un-expose variables, restoring them to their + * prior values, if applicable. + */ + unExposeVariables(); + } + + /** + * Rethrows the given Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + //********************************************************************* + // Accessor methods + + /* + * Overview: The getXXX() methods we provide implement the Tag + * contract. setXXX() accessors are provided only for those + * properties (attributes) that must be known at translation time, + * on the premise that these accessors will vary less than the + * others in terms of their interface with the page author. + */ + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this if necessary, but such a need is + * expected to be rare.) + */ + + public Object getCurrent() { + return item; + } + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this method for more fine-grained control + * over LoopTagStatus, but an effort has been made to simplify + * implementation of subclasses that are happy with reasonable default + * behavior.) + */ + + public LoopTagStatus getLoopStatus() { + + // local implementation with reasonable default behavior + class Status implements LoopTagStatus { + + /* + * All our methods are straightforward. We inherit + * our JavaDoc from LoopTagSupport; see that class + * for more information. + */ + + public Object getCurrent() { + /* + * Access the item through getCurrent() instead of just + * returning the item our containing class stores. This + * should allow a subclass of LoopTagSupport to override + * getCurrent() without having to rewrite getLoopStatus() too. + */ + return (LoopTagSupport.this.getCurrent()); + } + + public int getIndex() { + return (index + begin); // our 'index' isn't getIndex() + } + + public int getCount() { + return (count); + } + + public boolean isFirst() { + return (index == 0); // our 'index' isn't getIndex() + } + + public boolean isLast() { + return (last); // use cached value + } + + public Integer getBegin() { + if (beginSpecified) { + return (new Integer(begin)); + } else { + return null; + } + } + + public Integer getEnd() { + if (endSpecified) { + return (new Integer(end)); + } else { + return null; + } + } + + public Integer getStep() { + if (stepSpecified) { + return (new Integer(step)); + } else { + return null; + } + } + } + + /* + * We just need one per invocation... Actually, for the current + * implementation, we just need one per instance, but I'd rather + * not keep the reference around once release() has been called. + */ + if (status == null) { + status = new Status(); + } + + return status; + } + + /* + * We only support setter methods for attributes that need to be + * offered as Strings or other literals; other attributes will be + * handled directly by implementing classes, since there might be + * both rtexprvalue- and EL-based varieties, which will have + * different signatures. (We can't pollute child classes by having + * base implementations of those setters here; child classes that + * have attributes with different signatures would end up having + * two incompatible setters, which is illegal for a JavaBean. + */ + + /** + * Sets the 'var' attribute. + * + * @param id Name of the exported scoped variable storing the current item + * of the iteration. + */ + public void setVar(String id) { + this.itemId = id; + } + + /** + * Sets the 'varStatus' attribute. + * + * @param statusId Name of the exported scoped variable storing the status + * of the iteration. + */ + public void setVarStatus(String statusId) { + this.statusId = statusId; + } + + + //********************************************************************* + // Protected utility methods + + /* + * These methods validate attributes common to iteration tags. + * Call them if your own subclassing implementation modifies them + * -- e.g., if you set them through an expression language. + */ + + /** + * Ensures the "begin" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateBegin() throws JspTagException { + if (begin < 0) { + throw new JspTagException("'begin' < 0"); + } + } + + /** + * Ensures the "end" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateEnd() throws JspTagException { + if (end < 0) { + throw new JspTagException("'end' < 0"); + } + } + + /** + * Ensures the "step" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateStep() throws JspTagException { + if (step < 1) { + throw new JspTagException("'step' <= 0"); + } + } + + + //********************************************************************* + // Private utility methods + + /** + * (Re)initializes state (during release() or construction) + */ + private void init() { + // defaults for internal bookkeeping + index = 0; // internal index always starts at 0 + count = 1; // internal count always starts at 1 + status = null; // we clear status on release() + item = null; // item will be retrieved for each round + last = false; // last must be set explicitly + beginSpecified = false; // not specified until it's specified :-) + endSpecified = false; // (as above) + stepSpecified = false; // (as above) + deferredExpression = null; + + // defaults for interface with page author + begin = 0; // when not specified, 'begin' is 0 by spec. + end = -1; // when not specified, 'end' is not used + step = 1; // when not specified, 'step' is 1 + itemId = null; // when not specified, no variable exported + statusId = null; // when not specified, no variable exported + } + + /** + * Sets 'last' appropriately. + */ + private void calibrateLast() throws JspTagException { + /* + * the current round is the last one if (a) there are no remaining + * elements, or (b) the next one is beyond the 'end'. + */ + last = !hasNext() || atEnd() || + (end != -1 && (begin + index + step > end)); + } + + /** + * Exposes attributes (formerly scripting variables, but no longer!) + * if appropriate. Note that we don't really care, here, whether they're + * scripting variables or not. + */ + private void exposeVariables() throws JspTagException { + + 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) { + pageContext.removeAttribute(statusId, PageContext.PAGE_SCOPE); + } else { + pageContext.setAttribute(statusId, getLoopStatus()); + } + } + + } + + /** + * Removes page attributes that we have exposed and, if applicable, + * restores them to their prior values (and scopes). + */ +/** + * Removes page attributes that we have exposed and, if applicable, + * restores them to their prior values (and scopes). + */ +private void unExposeVariables() { + if (deferredExpression == null) { + { + pageContext.removeAttribute(itemId, jakarta.servlet.jsp.PageContext.PAGE_SCOPE); + } + } else { + // we're deferred ... remove variable mapping + jakarta.el.ELContext myELContext = pageContext.getELContext(); + jakarta.el.VariableMapper vm = myELContext.getVariableMapper(); + vm.setVariable(itemId, null); + } + if (statusId != null) { + pageContext.removeAttribute(statusId, jakarta.servlet.jsp.PageContext.PAGE_SCOPE); + } +} + + /** + * Cycles through and discards up to 'n' items from the iteration. + * We only know "up to 'n'", not "exactly n," since we stop cycling + * if hasNext() returns false or if we hit the 'end' of the iteration. + * Note: this does not update the iteration index, since this method + * is intended as a behind-the-scenes operation. The index must be + * updated separately. (I don't really like this, but it's the simplest + * way to support isLast() without storing two separate inconsistent + * indices. We need to (a) make sure hasNext() refers to the next + * item we actually *want* and (b) make sure the index refers to the + * item associated with the *current* round, not the next one. + * C'est la vie.) + */ + private void discard(int n) throws JspTagException { + /* + * copy index so we can restore it, but we need to update it + * as we work so that atEnd() works + */ + int oldIndex = index; + while (n-- > 0 && !atEnd() && hasNext()) { + index++; + next(); + } + index = oldIndex; + } + + /** + * Discards items ignoring subsetting rules. Useful for discarding + * items from the beginning (i.e., to implement 'begin') where we + * don't want factor in the 'begin' value already. + */ + private void discardIgnoreSubset(int n) throws JspTagException { + while (n-- > 0 && hasNext()) { + next(); + } + } + + /** + * Returns true if the iteration has past the 'end' index (with + * respect to subsetting), false otherwise. ('end' must be set + * for atEnd() to return true; if 'end' is not set, atEnd() + * always returns false.) + */ + 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/Java/tomcat-taglibs-standard-LoopTagSupport_587/metadata.json b/Java/tomcat-taglibs-standard-LoopTagSupport_587/metadata.json new file mode 100644 index 000000000..d94be214d --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_587/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "tomcat-taglibs-standard-LoopTagSupport_587", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java", + "line": 560, + "npe_method": "unExposeVariables", + "deref_field": "itemId", + "npe_class": "LoopTagSupport", + "repo": "tomcat-taglibs-standard", + "bug_id": "LoopTagSupport_587" + } +} diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_587/npe.json b/Java/tomcat-taglibs-standard-LoopTagSupport_587/npe.json new file mode 100644 index 000000000..b7f3267e1 --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_587/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java", + "line": 560, + "npe_method": "unExposeVariables", + "deref_field": "itemId", + "npe_class": "LoopTagSupport" +} \ No newline at end of file diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_596/Dockerfile b/Java/tomcat-taglibs-standard-LoopTagSupport_596/Dockerfile new file mode 100644 index 000000000..0f44816f6 --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_596/Dockerfile @@ -0,0 +1,18 @@ +FROM ghcr.io/kupl/starlab-benchmarks/java-base:tomcat-taglibs-standard + +ENV TZ=Asia/Seoul + +COPY ./metadata.json . +COPY ./npe.json . +COPY ./buggy.java /tmp/buggy.java +RUN export BUGGY_PATH=$(cat metadata.json | jq -r ".npe.filepath") \ + && export BUGGY_LINE=$(cat metadata.json | jq -r ".npe.line") \ + && export BUGGY_MTHD=$(cat metadata.json | jq -r ".npe.npe_method") \ + && mv /tmp/buggy.java $BUGGY_PATH \ + && echo "[{\"filepath\": \"$BUGGY_PATH\", \"line\": $BUGGY_LINE, \"method_name\": \"$BUGGY_MTHD\"}]" | jq . > traces.json + +RUN git init . && git add -A + +RUN $(cat metadata.json | jq -r ".buildCommand") + +RUN $(cat metadata.json | jq -r ".testCommand"); if [ $? -eq 0 ]; then exit 1; fi diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_596/buggy.java b/Java/tomcat-taglibs-standard-LoopTagSupport_596/buggy.java new file mode 100644 index 000000000..8ee2adddf --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_596/buggy.java @@ -0,0 +1,659 @@ +/* + * 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 jakarta.servlet.jsp.jstl.core; + +import jakarta.el.ELContext; +import jakarta.el.ValueExpression; +import jakarta.el.VariableMapper; +import jakarta.servlet.jsp.JspException; +import jakarta.servlet.jsp.JspTagException; +import jakarta.servlet.jsp.PageContext; +import jakarta.servlet.jsp.tagext.IterationTag; +import jakarta.servlet.jsp.tagext.TagSupport; +import jakarta.servlet.jsp.tagext.TryCatchFinally; + +/** + *

Base support class to facilitate implementation of iteration tags.

+ *

Since most iteration tags will behave identically with respect to + * actual iterative behavior, JSTL provides this + * base support class to facilitate implementation. Many iteration tags + * will extend this and merely implement the hasNext() and + * next() methods + * to provide contents for the handler to iterate over.

+ *

In particular, this base class provides support for:

+ *
    + *
  • Iteration control, based on protected prepare(), next(), + * and hasNext() methods + *
  • Subsetting (begin, end, step>functionality, + * including validation + * of subset parameters for sensibility) + *
  • item retrieval (getCurrent()) + *
  • status retrieval (LoopTagStatus) + *
  • exposing attributes (set by var and varStatus attributes) + *
+ *

In providing support for these tasks, LoopTagSupport contains + * certain control variables that act to modify the iteration. Accessors + * are provided for these control variables when the variables represent + * information needed or wanted at translation time (e.g., var, + * varStatus). For + * other variables, accessors cannot be provided here since subclasses + * may differ on their implementations of how those accessors are received. + * For instance, one subclass might accept a String and convert it into + * an object of a specific type by using an expression evaluator; others + * might accept objects directly. Still others might not want to expose + * such information to outside control.

+ * + * @author Shawn Bayern + */ + +public abstract class LoopTagSupport + extends TagSupport + implements LoopTag, IterationTag, TryCatchFinally { + //********************************************************************* + // 'Protected' state + + /* + * JavaBean-style properties and other state slaved to them. These + * properties can be set directly by accessors; they will not be + * modified by the LoopTagSupport implementation -- and should + * not be modified by subclasses outside accessors unless those + * subclasses are perfectly aware of what they're doing. + * (An example where such non-accessor modification might be sensible + * is in the doStartTag() method of an EL-aware subclass.) + */ + + /** + * Starting index ('begin' attribute) + */ + protected int begin; + + /** + * Ending index of the iteration ('end' attribute). + * A value of -1 internally indicates 'no end + * specified', although accessors for the core JSTL tags do not + * allow this value to be supplied directly by the user. + */ + protected int end; + + /** + * Iteration step ('step' attribute) + */ + protected int step; + + /** + * Boolean flag indicating whether 'begin' was specified. + */ + protected boolean beginSpecified; + + /** + * Boolean flag indicating whether 'end' was specified. + */ + protected boolean endSpecified; + + /** + * Boolean flag indicating whether 'step' was specified. + */ + protected boolean stepSpecified; + + /** + * Attribute-exposing control + */ + protected String itemId, statusId; + + protected ValueExpression deferredExpression; + + //********************************************************************* + // 'Private' state (implementation details) + + /* + * State exclusively internal to the default, reference implementation. + * (While this state is kept private to ensure consistency, 'status' + * and 'item' happen to have one-for-one, read-only, accesor methods + * as part of the LoopTag interface.) + * + * 'last' is kept separately for two reasons: (a) to avoid + * running a computation every time it's requested, and (b) to + * let LoopTagStatus.isLast() avoid throwing any exceptions, + * which would complicate subtag and scripting-variable use. + * + * Our 'internal index' begins at 0 and increases by 'step' each + * round; this is arbitrary, but it seemed a simple way of keeping + * track of the information we need. To avoid computing + * getLoopStatus().getCount() by dividing index / step, we keep + * a separate 'count' and increment it by 1 each round (as a minor + * performance improvement). + */ + private LoopTagStatus status; // our LoopTagStatus + private Object item; // the current item + private int index; // the current internal index + private int count; // the iteration count + private boolean last; // current round == last one? + + //********************************************************************* + // Constructor + + /** + * Constructs a new LoopTagSupport. As with TagSupport, subclasses + * should not implement constructors with arguments, and no-arguments + * constructors implemented by subclasses must call the superclass + * constructor. + */ + public LoopTagSupport() { + super(); + init(); + } + + + //********************************************************************* + // Abstract methods + + /** + *

Returns the next object over which the tag should iterate. This + * method must be provided by concrete subclasses of LoopTagSupport + * to inform the base logic about what objects it should iterate over.

+ *

It is expected that this method will generally be backed by an + * Iterator, but this will not always be the case. In particular, if + * retrieving the next object raises the possibility of an exception + * being thrown, this method allows that exception to propagate back + * to the JSP container as a JspTagException; a standalone Iterator + * would not be able to do this. (This explains why LoopTagSupport + * does not simply call for an Iterator from its subtags.)

+ * + * @return the java.lang.Object to use in the next round of iteration + * @throws java.util.NoSuchElementException + * if next() is called but no new elements are available + * @throws jakarta.servlet.jsp.JspTagException + * for other, unexpected exceptions + */ + protected abstract Object next() throws JspTagException; + + /** + *

Returns information concerning the availability of more items + * over which to iterate. This method must be provided by concrete + * subclasses of LoopTagSupport to assist the iterative logic + * provided by the supporting base class.

+ *

See next for more information about the + * purpose and expectations behind this tag.

+ * + * @return true if there is at least one more item to iterate + * over, false otherwise + * @throws jakarta.servlet.jsp.JspTagException + * + * @see #next + */ + protected abstract boolean hasNext() throws JspTagException; + + /** + *

Prepares for a single tag invocation. Specifically, allows + * subclasses to prepare for calls to hasNext() and next(). + * Subclasses can assume that prepare() will be called once for + * each invocation of doStartTag() in the superclass.

+ * + * @throws jakarta.servlet.jsp.JspTagException + * + */ + protected abstract void prepare() throws JspTagException; + + + //********************************************************************* + // Lifecycle management and implementation of iterative behavior + + /** + * Releases any resources this LoopTagSupport may have (or inherit). + */ + @Override + public void release() { + super.release(); + init(); + } + + /** + * Begins iterating by processing the first item. + */ + @Override + public int doStartTag() throws JspException { + if (end != -1 && begin > end) { + // JSTL 1.1. We simply do not execute the loop. + return SKIP_BODY; + } + + // we're beginning a new iteration, so reset our counts (etc.) + index = 0; + count = 1; + last = false; + + // let the subclass conduct any necessary preparation + prepare(); + + // throw away the first 'begin' items (if they exist) + discardIgnoreSubset(begin); + + // get the item we're interested in + if (hasNext()) + // index is 0-based, so we don't update it for the first item + { + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to include our body... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_INCLUDE; + } + + /** + * Continues the iteration when appropriate -- that is, if we (a) have + * more items and (b) don't run over our 'end' (given our 'step'). + */ + @Override + public int doAfterBody() throws JspException { + + // re-sync the index, given our prior behind-the-scenes 'step' + index += step - 1; + + // increment the count by 1 for each round + count++; + + // everything's been prepared for us, so just get the next item + if (hasNext() && !atEnd()) { + index++; + item = next(); + } else { + return SKIP_BODY; + } + + /* + * now discard anything we have to "step" over. + * (we do this in advance to support LoopTagStatus.isLast()) + */ + discard(step - 1); + + // prepare to re-iterate... + exposeVariables(); + calibrateLast(); + return EVAL_BODY_AGAIN; + } + + /** + * Removes any attributes that this LoopTagSupport set. + *

These attributes are intended to support scripting variables with + * NESTED scope, so we don't want to pollute attribute space by leaving + * them lying around. + */ + public void doFinally() { + /* + * Make sure to un-expose variables, restoring them to their + * prior values, if applicable. + */ + unExposeVariables(); + } + + /** + * Rethrows the given Throwable. + */ + public void doCatch(Throwable t) throws Throwable { + throw t; + } + + //********************************************************************* + // Accessor methods + + /* + * Overview: The getXXX() methods we provide implement the Tag + * contract. setXXX() accessors are provided only for those + * properties (attributes) that must be known at translation time, + * on the premise that these accessors will vary less than the + * others in terms of their interface with the page author. + */ + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this if necessary, but such a need is + * expected to be rare.) + */ + + public Object getCurrent() { + return item; + } + + /* + * (Purposely inherit JavaDoc and semantics from LoopTag. + * Subclasses can override this method for more fine-grained control + * over LoopTagStatus, but an effort has been made to simplify + * implementation of subclasses that are happy with reasonable default + * behavior.) + */ + + public LoopTagStatus getLoopStatus() { + + // local implementation with reasonable default behavior + class Status implements LoopTagStatus { + + /* + * All our methods are straightforward. We inherit + * our JavaDoc from LoopTagSupport; see that class + * for more information. + */ + + public Object getCurrent() { + /* + * Access the item through getCurrent() instead of just + * returning the item our containing class stores. This + * should allow a subclass of LoopTagSupport to override + * getCurrent() without having to rewrite getLoopStatus() too. + */ + return (LoopTagSupport.this.getCurrent()); + } + + public int getIndex() { + return (index + begin); // our 'index' isn't getIndex() + } + + public int getCount() { + return (count); + } + + public boolean isFirst() { + return (index == 0); // our 'index' isn't getIndex() + } + + public boolean isLast() { + return (last); // use cached value + } + + public Integer getBegin() { + if (beginSpecified) { + return (new Integer(begin)); + } else { + return null; + } + } + + public Integer getEnd() { + if (endSpecified) { + return (new Integer(end)); + } else { + return null; + } + } + + public Integer getStep() { + if (stepSpecified) { + return (new Integer(step)); + } else { + return null; + } + } + } + + /* + * We just need one per invocation... Actually, for the current + * implementation, we just need one per instance, but I'd rather + * not keep the reference around once release() has been called. + */ + if (status == null) { + status = new Status(); + } + + return status; + } + + /* + * We only support setter methods for attributes that need to be + * offered as Strings or other literals; other attributes will be + * handled directly by implementing classes, since there might be + * both rtexprvalue- and EL-based varieties, which will have + * different signatures. (We can't pollute child classes by having + * base implementations of those setters here; child classes that + * have attributes with different signatures would end up having + * two incompatible setters, which is illegal for a JavaBean. + */ + + /** + * Sets the 'var' attribute. + * + * @param id Name of the exported scoped variable storing the current item + * of the iteration. + */ + public void setVar(String id) { + this.itemId = id; + } + + /** + * Sets the 'varStatus' attribute. + * + * @param statusId Name of the exported scoped variable storing the status + * of the iteration. + */ + public void setVarStatus(String statusId) { + this.statusId = statusId; + } + + + //********************************************************************* + // Protected utility methods + + /* + * These methods validate attributes common to iteration tags. + * Call them if your own subclassing implementation modifies them + * -- e.g., if you set them through an expression language. + */ + + /** + * Ensures the "begin" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateBegin() throws JspTagException { + if (begin < 0) { + throw new JspTagException("'begin' < 0"); + } + } + + /** + * Ensures the "end" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateEnd() throws JspTagException { + if (end < 0) { + throw new JspTagException("'end' < 0"); + } + } + + /** + * Ensures the "step" property is sensible, throwing an exception + * expected to propagate up if it isn't + */ + protected void validateStep() throws JspTagException { + if (step < 1) { + throw new JspTagException("'step' <= 0"); + } + } + + + //********************************************************************* + // Private utility methods + + /** + * (Re)initializes state (during release() or construction) + */ + private void init() { + // defaults for internal bookkeeping + index = 0; // internal index always starts at 0 + count = 1; // internal count always starts at 1 + status = null; // we clear status on release() + item = null; // item will be retrieved for each round + last = false; // last must be set explicitly + beginSpecified = false; // not specified until it's specified :-) + endSpecified = false; // (as above) + stepSpecified = false; // (as above) + deferredExpression = null; + + // defaults for interface with page author + begin = 0; // when not specified, 'begin' is 0 by spec. + end = -1; // when not specified, 'end' is not used + step = 1; // when not specified, 'step' is 1 + itemId = null; // when not specified, no variable exported + statusId = null; // when not specified, no variable exported + } + + /** + * Sets 'last' appropriately. + */ + private void calibrateLast() throws JspTagException { + /* + * the current round is the last one if (a) there are no remaining + * elements, or (b) the next one is beyond the 'end'. + */ + last = !hasNext() || atEnd() || + (end != -1 && (begin + index + step > end)); + } + + /** + * Exposes attributes (formerly scripting variables, but no longer!) + * if appropriate. Note that we don't really care, here, whether they're + * scripting variables or not. + */ + private void exposeVariables() throws JspTagException { + + 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) { + pageContext.removeAttribute(statusId, PageContext.PAGE_SCOPE); + } else { + pageContext.setAttribute(statusId, getLoopStatus()); + } + } + + } + + /** + * Removes page attributes that we have exposed and, if applicable, + * restores them to their prior values (and scopes). + */ +/** + * Removes page attributes that we have exposed and, if applicable, + * restores them to their prior values (and scopes). + */ +private void unExposeVariables() { + if (deferredExpression == null) { + // "nested" variables are now simply removed + if (itemId != null) { + pageContext.removeAttribute(itemId, jakarta.servlet.jsp.PageContext.PAGE_SCOPE); + } + } else { + // we're deferred ... remove variable mapping + jakarta.el.ELContext myELContext = pageContext.getELContext(); + jakarta.el.VariableMapper vm = myELContext.getVariableMapper(); + vm.setVariable(itemId, null); + } + { + pageContext.removeAttribute(statusId, jakarta.servlet.jsp.PageContext.PAGE_SCOPE); + } +} + + /** + * Cycles through and discards up to 'n' items from the iteration. + * We only know "up to 'n'", not "exactly n," since we stop cycling + * if hasNext() returns false or if we hit the 'end' of the iteration. + * Note: this does not update the iteration index, since this method + * is intended as a behind-the-scenes operation. The index must be + * updated separately. (I don't really like this, but it's the simplest + * way to support isLast() without storing two separate inconsistent + * indices. We need to (a) make sure hasNext() refers to the next + * item we actually *want* and (b) make sure the index refers to the + * item associated with the *current* round, not the next one. + * C'est la vie.) + */ + private void discard(int n) throws JspTagException { + /* + * copy index so we can restore it, but we need to update it + * as we work so that atEnd() works + */ + int oldIndex = index; + while (n-- > 0 && !atEnd() && hasNext()) { + index++; + next(); + } + index = oldIndex; + } + + /** + * Discards items ignoring subsetting rules. Useful for discarding + * items from the beginning (i.e., to implement 'begin') where we + * don't want factor in the 'begin' value already. + */ + private void discardIgnoreSubset(int n) throws JspTagException { + while (n-- > 0 && hasNext()) { + next(); + } + } + + /** + * Returns true if the iteration has past the 'end' index (with + * respect to subsetting), false otherwise. ('end' must be set + * for atEnd() to return true; if 'end' is not set, atEnd() + * always returns false.) + */ + 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/Java/tomcat-taglibs-standard-LoopTagSupport_596/metadata.json b/Java/tomcat-taglibs-standard-LoopTagSupport_596/metadata.json new file mode 100644 index 000000000..f2cb0d48b --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_596/metadata.json @@ -0,0 +1,21 @@ +{ + "language": "java", + "id": "tomcat-taglibs-standard-LoopTagSupport_596", + "buggyPath": ".", + "referencePath": null, + "buildCommand": "mvn package -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100 -DskipTests=true -DskipITs=true -Dtest=None -DfailIfNoTests=false", + "testCommand": "mvn test -V -B -Denforcer.skip=true -Dcheckstyle.skip=true -Dcobertura.skip=true -Drat.skip=true -Dlicense.skip=true -Dfindbugs.skip=true -Dgpg.skip=true -Dskip.npm=true -Dskip.gulp=true -Dskip.bower=true -Drat.numUnapprovedLicenses=100", + "categories": [ + "safety", + "npe" + ], + "npe": { + "filepath": "spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java", + "line": 572, + "npe_method": "unExposeVariables", + "deref_field": "statusId", + "npe_class": "LoopTagSupport", + "repo": "tomcat-taglibs-standard", + "bug_id": "LoopTagSupport_596" + } +} diff --git a/Java/tomcat-taglibs-standard-LoopTagSupport_596/npe.json b/Java/tomcat-taglibs-standard-LoopTagSupport_596/npe.json new file mode 100644 index 000000000..3e6150dd7 --- /dev/null +++ b/Java/tomcat-taglibs-standard-LoopTagSupport_596/npe.json @@ -0,0 +1,7 @@ +{ + "filepath": "spec/src/main/java/jakarta/servlet/jsp/jstl/core/LoopTagSupport.java", + "line": 572, + "npe_method": "unExposeVariables", + "deref_field": "statusId", + "npe_class": "LoopTagSupport" +} \ No newline at end of file